void http_client::print_header(const char* prompt) { if (hdr_res_) http_hdr_print(&hdr_res_->hdr, prompt ? prompt : "dummy"); else if (hdr_req_) http_hdr_print(&hdr_req_->hdr, prompt ? prompt : "dummy"); }
// 正常读到 HTTP 响应头时的回调接口 virtual void on_hdr(const char* addr, const HTTP_HDR_RES* hdr) { printf(">>server addr: %s, http reply status: %d\n", addr, hdr->reply_status); http_hdr_print(&hdr->hdr, "http reply hdr"); content_length_ = hdr->hdr.content_length; if (content_length_ > 0) { if (out_.open_write("test.exe") == false) printf("create file error(%s)\n", acl_last_serror()); } time(&begin_); }
bool CMsnContactManager::GetContacts(const CMsnTicket& ticket, acl::http_client& client) { // 创建请求体 acl::string request_body; if (BuildGetContactRequest(ticket, request_body) == false) return (false); ////////////////////////////////////////////////////////////////////////// // 向 MSN CONTACT 服务器发送请求数据 // 创建 HTTP 请求头 acl::http_header header; header.set_method(acl::HTTP_METHOD_POST); header.set_url(MSN_GET_CONTACT_POST_URL); header.set_host(MSN_CONTACT_SERVER); header.set_content_length(request_body.length()); header.set_content_type("text/xml; charset=utf-8"); header.set_keep_alive(false); header.add_entry("SOAPAction", MSN_GET_CONTACT_SOAP_ACTION); header.add_entry("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); header.add_entry("Accept", "*/*"); header.add_entry("Cache-Control", "no-cache"); // 现在ACL_CPP的压缩库仅支持HTTP传输中的GZIP方式 header.accept_gzip(true); // 发送 HTTP 请求头 acl::string header_buf; header.build_request(header_buf); // 记日志 logger_format("send: %s\r\n", header_buf.c_str()); if (client.get_ostream().write(header_buf) == -1) { logger_error("write http header error"); return (false); } // 发送 HTTP 请求体 // 记录发送体 logger_format("send: %s\r\n", request_body.c_str()); if (client.get_ostream().write(request_body) == -1) { logger_error("write http body error"); return (false); } ////////////////////////////////////////////////////////////////////////// // 从 MSN CONTACT 服务器读取响应数据 if (client.read_head() == false) { logger_error("read http respond head error"); return (false); } const HTTP_HDR_RES* hdr_res = client.get_respond_head(NULL); acl_assert(hdr_res); // 记录响应头 if (debug_fpout_) http_hdr_fprint(debug_fpout_, &hdr_res->hdr, "GetContacts read hdr: "); // 如果没有数据体,则认为失败 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)) { logger_error("http respond no body"); http_hdr_print(&hdr_res->hdr, "error"); return (false); } /* 读书 HTTP 响应体 */ ACL_XML* body = acl_xml_alloc(); int ret; acl::string plain; acl::ofstream fp; fp.open_write("zip_list.text"); int len = 0; while(true) { // 读 HTTP 响应数据体 ret = client.read_body(plain); if (ret < 0) break; else if (client.body_finish()) break; fp.write(plain); acl_xml_update(body, plain.c_str()); } //acl_xml_dump(body, ACL_VSTREAM_OUT); // 分析联系人列表 if (ParseContacts(body) == false) { acl_xml_free(body); return (false); } acl_xml_free(body); return (true); }
bool CMsnContactManager::GetAddresses(const CMsnTicket& ticket, acl::http_client& client) { acl::string request_body; if (BuildGetAddressRequest(ticket, request_body) == false) return (false); /////////////////////////////////////////////////////////////////////// // 向 MSN CONTACT 服务器发送请求数据 // 创建 HTTP 请求头 acl::http_header header; header.set_method(acl::HTTP_METHOD_POST); header.set_url(MSN_ADDRESS_BOOK_POST_URL); header.set_content_type("text/xml; charset=utf-8"); header.set_host(MSN_CONTACT_SERVER); header.set_content_length(request_body.length()); header.set_keep_alive(false); header.add_entry("SOAPAction", MSN_GET_ADDRESS_SOAP_ACTION); header.add_entry("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); header.add_entry("Accept", "*/*"); header.add_entry("Cache-Control", "no-cache"); header.accept_gzip(true); // 发送 HTTP 请求头 acl::string header_buf; header.build_request(header_buf); // 记录发送头 logger_format("send header: %s\r\n", header_buf.c_str()); if (client.get_ostream().write(header_buf) == -1) { logger_error("write http header error"); return (false); } // 发送 HTTP 请求体 // 记录发送体 logger_format("send body: %s\r\n", request_body.c_str()); if (client.get_ostream().write(request_body) == -1) { logger_error("write http body error"); return (false); } /////////////////////////////////////////////////////////////////////// // 从 MSN CONTACT 服务器读取响应数据 if (client.read_head() == false) { logger_error("read http respond head error"); return (false); } const HTTP_HDR_RES* hdr_res = client.get_respond_head(NULL); if (debug_fpout_) http_hdr_fprint(debug_fpout_, &hdr_res->hdr, "GetAddresses read header: "); 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)) { logger_error("http respond no body"); http_hdr_print(&hdr_res->hdr, "error"); return (false); } /* 读书 HTTP 响应体 */ acl::string buf; ACL_SLICE_POOL* slice = acl_slice_pool_create(16, 50, ACL_SLICE_FLAG_GC2 | ACL_SLICE_FLAG_RTGC_OFF | ACL_SLICE_FLAG_LP64_ALIGN); ACL_XML* body = acl_xml_alloc1(slice); int ret; while(true) { ret = client.read_body(buf); if (ret < 0) break; else if (client.body_finish()) break; acl_xml_update(body, buf.c_str()); logger_format("read body: %s\r\n", buf.c_str()); } //acl_xml_dump(body, ACL_VSTREAM_OUT); ParseAddresses(body); /////////////////////////////////////////////////////////////////////// double j = ACL_METER_TIME("---begin---"); //acl_xml_free(body); acl_slice_pool_destroy(slice); double k = ACL_METER_TIME("---end---"); return (true); }
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 请求头对象 */ }