Example #1
0
	http_status_t read_respond_hdr(void)
	{
		acl_assert(vstream_);
		snprintf(data_.i_addr, sizeof(data_.i_addr),
			"%s", ACL_VSTREAM_PEER(vstream_));
		hdr_res_ = http_hdr_res_new();
		int ret = http_hdr_res_get_sync(hdr_res_, vstream_, 60);
		if (ret < 0)
		{
			logger_error("get http respond hdr from %s error %s",
				data_.i_addr, acl_last_serror());
			http_hdr_res_free(hdr_res_);
			hdr_res_ = NULL;
			return (HTTP_ERR_READ_HDR);
		}

		if (http_hdr_res_parse(hdr_res_) < 0)
		{
			logger_error("parse http respond hdr error from %s",
				data_.i_addr);

			http_hdr_res_free(hdr_res_);
			hdr_res_ = NULL;
			return (HTTP_ERR_INVALID_HDR);
		}

		return (HTTP_OK);
	}
Example #2
0
void http_service::win32_proc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	if (lParam == 0)
		return;

	HTTP_IPC_DAT* dat = (HTTP_IPC_DAT*) lParam;

	switch (nMsg - WM_USER)
	{
	case HTTP_MSG_HDR:
		dat->callback->on_hdr(dat->i_addr, dat->i_hdr_res);
		acl_myfree(dat);
		break;
	case HTTP_MSG_DAT:
		dat->callback->on_body(dat->i_ptr, dat->i_dlen);
		if (dat->i_ptr && dat->i_dlen > 0)
			acl_myfree(dat->i_ptr);
		else
		{
			// 调用请求对象的销毁过程
			dat->callback->destroy();
			if (dat->i_hdr_res)
				http_hdr_res_free(dat->i_hdr_res);
		}
		acl_myfree(dat);
		break;
	case HTTP_MSG_ERR:
		dat->callback->on_error(dat->i_error);
		// 调用请求对象的销毁过程
		dat->callback->destroy();
		if (dat->i_hdr_res)
			http_hdr_res_free(dat->i_hdr_res);
		acl_myfree(dat);
		break;
	default:
		// 出现了异常消息
		logger_error("unknown ipc msg: %d", nMsg);
		break;
	}
}
Example #3
0
	virtual void on_message(int nMsg, void* data, int dlen)
	{
		acl_assert(dlen == sizeof(HTTP_IPC_DAT));
		HTTP_IPC_DAT* dat = (HTTP_IPC_DAT*) data;

		switch (nMsg)
		{
		case HTTP_MSG_HDR:
			dat->callback->on_hdr(dat->i_addr, dat->i_hdr_res);
			break;
		case HTTP_MSG_DAT:
			dat->callback->on_body(dat->i_ptr, dat->i_dlen);
			if (dat->i_ptr && dat->i_dlen > 0)
				acl_myfree(dat->i_ptr);
			else
			{
				// 调用请求对象的销毁过程
				dat->callback->destroy();
				if (dat->i_hdr_res)
					http_hdr_res_free(dat->i_hdr_res);
				this->close();  // 自动触发析构过程
			}
			break;
		case HTTP_MSG_ERR:
			dat->callback->on_error(dat->i_error);
			// 调用请求对象的销毁过程
			dat->callback->destroy();
			if (dat->i_hdr_res)
				http_hdr_res_free(dat->i_hdr_res);
			this->close();  // 自动触发析构过程
			break;
		default:
			// 出现了异常消息
			logger_error("unknown ipc msg: %d", nMsg);
			break;
		}
	}
Example #4
0
void http_client::reset(void)
{
	if (buf_)
		buf_->clear();

	if (res_)
	{
		// 说明是长连接的第二次请求,所以需要把上次请求的
		// 响应头对象及响应体对象释放

		acl_assert(hdr_res_);
		http_res_free(res_);
		hdr_res_ = NULL;
		res_ = NULL;
	}
	else if (hdr_res_)
	{
		// 说明是长连接的第二次请求,因为有可能第一次请求
		// 只有响应头,所以仅需要释放上次的响应头对象

		http_hdr_res_free(hdr_res_);
		hdr_res_ = NULL;
	}

	if (req_)
	{
		acl_assert(hdr_req_);
		http_req_free(req_);
		hdr_req_ = NULL;
		req_  = NULL;
	}
	else if (hdr_req_)
	{
		http_hdr_req_free(hdr_req_);
		hdr_req_  = NULL;
	}

	if (zstream_)
	{
		delete zstream_;
		zstream_ = NULL;
	}

	last_ret_ = -1;
	body_finish_ = false;
	chunked_transfer_ = false;
}
Example #5
0
static void timer_retry(PROBE_SERVER *server)
{
	if (server->stream != NULL)
		close_stream(server);

	if (server->res != NULL) {
		http_res_free(server->res);
		server->res = NULL;
		server->hdr_res = NULL;
	} else if (server->hdr_res != NULL) {
		http_hdr_res_free(server->hdr_res);
		server->hdr_res = NULL;
	}
	
	acl_aio_request_timer(server->aio, timer_fn, server,
		server->probe_inter * 1000000, 0);
}
Example #6
0
void http_client::do_reply(int status, const char* cmd,
	const acl::string& body, bool save)
{
	HTTP_HDR_RES* hdr_res = http_hdr_res_static(status);
	http_hdr_set_keepalive(hdr_req_, hdr_res);
	http_hdr_put_str(&hdr_res->hdr, "Content-Type", "text/json");
	http_hdr_put_int(&hdr_res->hdr, "Content-Length", (int) body.size());

	acl::string buf(body.size() + 256);
	http_hdr_build(&hdr_res->hdr, buf.vstring());
	http_hdr_res_free(hdr_res);
	buf.append(body);

	if (save)
		logger("cmd=[%s], reply: [%s]", cmd, buf.c_str());
	acl_aio_writen(conn_, buf.c_str(), (int) buf.size());
}
Example #7
0
void http_util_free(HTTP_UTIL *http_util)
{
	if ((http_util->flag & HTTP_UTIL_FLAG_SET_DUMP_FILE)) {
		if (http_util->dump_stream)
			acl_vstream_close(http_util->dump_stream);
	}

	if (http_util->stream)
		acl_vstream_close(http_util->stream);
	if (http_util->req_buf)
		acl_vstring_free(http_util->req_buf);
	if (http_util->hdr_req)
		http_hdr_req_free(http_util->hdr_req);
	if (http_util->http_res)
		http_res_free(http_util->http_res);
	else if (http_util->hdr_res)
		http_hdr_res_free(http_util->hdr_res);
	acl_myfree(http_util);
}
Example #8
0
bool http_client::read_response_head(void)
{
	// 以防万一,先清除可能的上次请求的残留的中间数据对象
	reset();

	if (stream_ == NULL)
	{
		logger_error("connect stream not open yet");
		disconnected_ = true;
		return false;
	}
	ACL_VSTREAM* vstream = stream_->get_vstream();
	if (vstream == NULL)
	{
		logger_error("connect stream null");
		disconnected_ = true;
		return false;
	}

	hdr_res_ = http_hdr_res_new();
	int   ret = http_hdr_res_get_sync(hdr_res_, vstream, rw_timeout_);
	if (ret == -1)
	{
		http_hdr_res_free(hdr_res_);
		hdr_res_ = NULL;
		disconnected_ = true;
		return false;
	}

	if (http_hdr_res_parse(hdr_res_) < 0)
	{
		logger_error("parse response header error");
		http_hdr_res_free(hdr_res_);
		hdr_res_ = NULL;
		disconnected_ = true;
		return false;
	}

	// 块传输的优先级最高
	if (!hdr_res_->hdr.chunked)
	{
		// 如果服务器响应时明确指明了长度为 0 则表示不没有数据体
		if (hdr_res_->hdr.content_length == 0)
		{
			body_finish_ = true;
			return true;
		}
	}

	const char* ptr = http_hdr_entry_value(&hdr_res_->hdr,
			"Content-Encoding");
	if (ptr && unzip_)
	{
		// 目前仅支持 gzip 数据的解压
		if (strcasecmp(ptr, "gzip") == 0)
		{
			zstream_ = NEW zlib_stream();
			if (zstream_->unzip_begin(false) == false)
			{
				logger_error("unzip_begin error");
				delete zstream_;
				zstream_ = NULL;
			}
			gzip_header_left_ = 10;
		}
		else
			logger_warn("unknown compress format: %s", ptr);
	}

	return true;
}
Example #9
0
void *CHttpClient::DoRequestThread(void* arg)
{
	CHttpClient *phClient = (CHttpClient*) arg;
	HTTP_HDR_REQ *hdr_req = NULL;
	HTTP_HDR_RES *hdr_res = NULL;
	HTTP_RES *http_res = NULL;
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	ACL_VSTREAM *server = NULL;
	const char *pHost = NULL;
	ACL_VSTREAM *fp = NULL;
	int   ret;
	UINT  nForward = 0;
	time_t begin = 0;
	struct timeval begin_tv, end_tv;
	double time_cost = 0;

#undef RETURN
#define RETURN(_x_) do  \
{  \
	if (hdr_req)  \
		http_hdr_req_free(hdr_req);  \
	if (buf)  \
		acl_vstring_free(buf);  \
	if (hdr_res)  \
		http_hdr_res_free(hdr_res);  \
	if (http_res) {  \
		http_res->hdr_res = NULL;  \
		http_res_free(http_res);  \
	}  \
	if (server)  \
		acl_vstream_close(server);  \
	if (fp)  \
		acl_vstream_close(fp);  \
	gettimeofday(&end_tv, NULL); \
	time_cost = stamp_sub(&end_tv, &begin_tv); \
	if (time_cost >= 0) \
		phClient->ReportTime(time_cost); \
	phClient->ReportComplete(); \
	return (_x_);  \
} while(0)

	const char *pUrl = phClient->m_sReqUrl.GetString();
	hdr_req = http_hdr_req_create(pUrl, phClient->m_bPostMethod ? "POST" : "GET",
		phClient->m_bHttp11 ? "HTTP/1.1" : "HTTP/1.0");
	ASSERT(hdr_req);

	if (phClient->m_bZip)
		http_hdr_put_str(&hdr_req->hdr, "Accept-Encoding", "gzip, deflate");
	if (phClient->m_bKeepAlive)
		http_hdr_entry_replace(&hdr_req->hdr, "Connection", "Keep-Alive", 1);
	if (phClient->m_bPostMethod)
		http_hdr_put_int(&hdr_req->hdr, "Content-Length",
			(int) phClient->m_sHttpBody.GetLength());
	if (!phClient->m_sAccept.IsEmpty())
		http_hdr_put_str(&hdr_req->hdr, "Accept", phClient->m_sAccept.GetString());
	if (!phClient->m_sCtype.IsEmpty())
		http_hdr_put_str(&hdr_req->hdr, "Content-Type", phClient->m_sCtype.GetString());

	if (phClient->m_sHttpHdrAppend.GetLength() > 0) {
		ACL_ARGV *argv;
		HTTP_HDR_ENTRY *entry;
		int   i;
		
		argv = acl_argv_split(phClient->m_sHttpHdrAppend.GetString(), "\r\n");
		for (i = 0; i < argv->argc; i++) {
			entry = http_hdr_entry_new(argv->argv[i]);
			if (entry == NULL)
				continue;
			http_hdr_append_entry(&hdr_req->hdr, entry);
		}
		acl_argv_free(argv);
	}

FORWARD:

	http_hdr_build_request(hdr_req, buf);
	pHost = http_hdr_req_host(hdr_req);
	ASSERT(pHost);

	phClient->ReportReqHdr(acl_vstring_str(buf), (int) ACL_VSTRING_LEN(buf));

	CString serverAddr;

	if (phClient->m_bUseAddr)
		serverAddr.Format("%s", phClient->m_sServerAddr);
	if (serverAddr.GetLength() == 0)
		serverAddr.Format("%s", pHost);
	if (strchr(serverAddr.GetString(), ':') == NULL)
		serverAddr.AppendFormat(":80");

	time(&begin);
	gettimeofday(&begin_tv, NULL);
	server = acl_vstream_connect(serverAddr.GetString(),
				ACL_BLOCKING, 10, 10, 4096);
	if (server == NULL) {
		CString msg;

		msg.Format("Connect server(%s) error", serverAddr.GetString());
		phClient->ReportErrConnect(msg.GetString());
		RETURN (NULL);
	}

	if (phClient->m_bLocalSave && fp == NULL) {
		fp = acl_vstream_fopen(phClient->m_sLocalFile.GetString(),
			O_WRONLY | O_CREAT | O_TRUNC, 0600, 4096);
		if (fp == NULL) {
			acl_msg_error("%s(%d): can't create file(%s)",
				__FILE__, __LINE__, phClient->m_sLocalFile.GetString());
			RETURN (NULL);
		}
	}

	ret = acl_vstream_writen(server, acl_vstring_str(buf), ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF) {
		acl_msg_error("%s(%d): write error", __FILE__, __LINE__);
		RETURN (NULL);
	}

	if (phClient->m_bPostMethod && !phClient->m_sHttpBody.IsEmpty())
	{
		if (acl_vstream_writen(server, phClient->m_sHttpBody.GetString(),
			phClient->m_sHttpBody.GetLength()) == ACL_VSTREAM_EOF)
		{
			acl_msg_error("%s(%d): write body error", __FILE__, __LINE__);
			RETURN (NULL);
		}
	}

	hdr_res = http_hdr_res_new();
	if (http_hdr_res_get_sync(hdr_res, server, 10) < 0) {
		acl_msg_error("%s(%d): get res hdr error", __FILE__, __FILE__, __LINE__);
		RETURN (NULL);
	}

	if (http_hdr_res_parse(hdr_res) < 0) {
		acl_msg_error("%s(%d): parse hdr_res error", __FILE__, __LINE__);
		RETURN (NULL);
	}

	http_hdr_build(&hdr_res->hdr, buf);
	phClient->ReportResHdr(acl_vstring_str(buf), (int) ACL_VSTRING_LEN(buf));
	phClient->ReportResContentLength((int) hdr_res->hdr.content_length);

	if (hdr_res->reply_status > 300	&& hdr_res->reply_status < 400) {
		const char* pLocation;
		HTTP_HDR_REQ *hdr_req_tmp;

		if (!phClient->m_bForwardAuto)
			RETURN (NULL);

		if (nForward++ >= phClient->m_nMaxTry) {
			acl_msg_error("%s(%d): too many redirect, nForward(%d)",
				__FILE__, __LINE__, nForward);
			RETURN (NULL);
		}

		pLocation = http_hdr_entry_value(&hdr_res->hdr, "Location");
		if (pLocation == NULL || *pLocation == 0) {
			acl_msg_error("%s(%d): 302 reply with no Location", __FILE__, __LINE__);
			RETURN (NULL);
		}

		hdr_req_tmp = http_hdr_req_rewrite(hdr_req, pLocation);
		if (hdr_req_tmp == NULL)
			RETURN (NULL);
		http_hdr_req_free(hdr_req);
		http_hdr_res_free(hdr_res);
		hdr_req = hdr_req_tmp;
		goto FORWARD;
	}

	http_res = http_res_new(hdr_res);
	while (1) {
		char  tmp_buf[4096];

		ret = (int) http_res_body_get_sync2(http_res, server,
				tmp_buf, sizeof(tmp_buf) - 1);
		if (ret <= 0)
			break;

		phClient->ReportResBody(tmp_buf, ret);
		phClient->ReportResDownLength((int)(time(NULL) - begin), ret);

		if (fp != NULL && acl_vstream_writen(fp, tmp_buf, ret) == ACL_VSTREAM_EOF) {
			acl_msg_error("%s(%d): write to file error", __FILE__, __LINE__);
			break;
		}
	}
	RETURN (NULL);
}
Example #10
0
static void get_url(const char *method, const char *url,
	const char *proxy, const char *dump)
{
	/* 创建 HTTP 请求头 */
	HTTP_HDR_REQ *hdr_req = http_hdr_req_create(url, method, "HTTP/1.1");
	ACL_VSTREAM *stream;
	ACL_VSTRING *buf = acl_vstring_alloc(256);
	HTTP_HDR_RES *hdr_res;
	HTTP_RES *res;
	ACL_FILE *fp = NULL;
	const char *ptr;
	int   ret;

	/* 输出 HTTP 请求头内容 */

	http_hdr_print(&hdr_req->hdr, "---request hdr---");

	/* 如果设定代理服务器,则连接代理服务器地址,
	 * 否则使用 HTTP 请求头里指定的地址
	 */

	if (*proxy)
		acl_vstring_strcpy(buf, proxy);
	else
		acl_vstring_strcpy(buf, http_hdr_req_host(hdr_req));

	/* 获得远程 HTTP 服务器的连接地址 */

	ptr = acl_vstring_memchr(buf, ':');
	if (ptr == NULL)
		acl_vstring_strcat(buf, ":80");
	else {
		int   port;
		ptr++;
		port = atoi(ptr);
		if (port <= 0 || port >= 65535) {
			printf("http server's addr(%s) invalid\n", acl_vstring_str(buf));
			acl_vstring_free(buf);
			http_hdr_req_free(hdr_req);
			return;
		}
	}

	/* 连接远程 http 服务器 */

	stream = acl_vstream_connect(acl_vstring_str(buf) /* 服务器地址 */,
			ACL_BLOCKING /* 采用阻塞方式 */,
			10 /* 连接超时时间为 10 秒 */,
			10 /* 网络 IO 操作超时时间为 10 秒 */,
			4096 /* stream 流缓冲区大小为 4096 字节 */);
	if (stream == NULL) {
		printf("connect addr(%s) error(%s)\n",
			acl_vstring_str(buf), acl_last_serror());
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 构建 HTTP 请求头数据 */

	http_hdr_build_request(hdr_req, buf);

	/* 向 HTTP 服务器发送请求 */

	ret = acl_vstream_writen(stream, acl_vstring_str(buf), ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF) {
		printf("write to server error(%s)\n", acl_last_serror());
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 创建一个 HTTP 响应头对象 */

	hdr_res = http_hdr_res_new();

	/* 读取 HTTP 服务器响应头*/

	ret = http_hdr_res_get_sync(hdr_res, stream, 10 /* IO 超时时间为 10 秒 */);
	if (ret < 0) {
		printf("get http reply header error(%s)\n", acl_last_serror());
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	if (http_hdr_res_parse(hdr_res) < 0) {
		printf("parse http reply header error\n");
		http_hdr_print(&hdr_res->hdr, "--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 如果需要转储至磁盘则需要先打开文件 */

	if (dump != NULL) {
		fp = acl_fopen(dump, "w+");
		if (fp == NULL)
			printf("open file(%s) error(%s)\n",
				dump, acl_last_serror());
	}

	/* 如果 HTTP 响应没有数据体则仅输出 HTTP 响应头即可 */

	if (hdr_res->hdr.content_length == 0
		|| (hdr_res->hdr.content_length == -1
			&& !hdr_res->hdr.chunked
			&& hdr_res->reply_status > 300
			&& hdr_res->reply_status < 400))
	{
		if (fp)
			http_hdr_fprint(ACL_FSTREAM(fp), &hdr_res->hdr,
				"--- reply http header ---");
		else
			http_hdr_fprint(ACL_VSTREAM_OUT, &hdr_res->hdr,
				"--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 输出 HTTP 响应头 */

	http_hdr_print(&hdr_res->hdr, "--- reply http header ---");

	/* 创建 HTTP 响应体对象 */

	res = http_res_new(hdr_res);

	/* 如果有数据体则开始读取 HTTP 响应数据体部分 */
	while (1) {
		http_off_t  n;
		char  buf2[4096];
		
		n = http_res_body_get_sync(res, stream, buf2, sizeof(buf2) - 1);
		if (n <= 0)
			break;

		if (fp) {
			if (acl_fwrite(buf2, (size_t) n, 1, fp) == (size_t) EOF) {
				printf("write to dump file(%s) error(%s)\n",
					dump, acl_last_serror());
				break;
			}
		} else {
			buf2[n] = 0;
			printf("%s", buf2);
		}
	}

	if (fp)
		acl_fclose(fp);
	http_res_free(res);  /* 释放 HTTP 响应对象, hdr_res 会在此函数内部自动被释放 */
	acl_vstream_close(stream);  /* 关闭网络流 */
	acl_vstring_free(buf);  /* 释放内存区 */
	http_hdr_req_free(hdr_req);  /* 释放 HTTP 请求头对象 */
}
Example #11
0
	// 基类 ipc_request 会自动调用此回调处理请求过程
	virtual void run(ipc_client* ipc)
	{
		unsigned int nredirect_limit = data_.callback->get_redirect();
		unsigned int nredirect = 0;
		http_status_t ret;

		while (true)
		{
			if ((ret = connect_server()) != HTTP_OK)
			{
				report_error(ipc, ret);
				break;
			}
			if ((ret = send_request()) != HTTP_OK)
			{
				report_error(ipc, ret);
				break;
			}
			if ((ret = read_respond_hdr()) != HTTP_OK)
			{
				report_error(ipc, ret);
				break;
			}

			acl_assert(hdr_res_);

			// 如果服务器返回的是重定向信息,则进行重定向访问

			if ((hdr_res_->reply_status != 301
				&& hdr_res_->reply_status != 302)
				|| nredirect_limit == 0)
			{
				// 发送响应头收到消息给主线程
				report(ipc, HTTP_MSG_HDR);

				// 连续接收响应体并发响应体收到消息给主线程
				read_respond_body(ipc);
				break;
			}

			// 开始重定向过程

			nredirect++;
			// 防止重定向次数太多而造成了循环
			if (nredirect > nredirect_limit)
			{
				report_error(ipc, HTTP_ERR_REDIRECT_MAX);
				break;
			}

			const char* url = http_hdr_entry_value(
				&hdr_res_->hdr, "Location");

			if (url == NULL)
			{
				logger_error("redirect Location null");
				report_error(ipc, HTTP_ERR_INVALID_HDR);
				break;
			}
			if (data_.callback->redirect(url) == false)
			{
				http_hdr_res_free(hdr_res_);
				hdr_res_ = NULL;
				report_error(ipc, HTTP_ERR_INVALID_HDR);
				break;
			}
			http_hdr_res_free(hdr_res_);
			hdr_res_ = NULL;
			data_.callback->redicrect_reset();
		}

		delete this;
	}