bool https_client::http_request(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { const char* host = req.getRemoteHost(); if (host == NULL || *host == 0) host = req.getLocalAddr(); acl::string server_addr; if (ssl_conf_ == NULL) server_addr.format("%s:80", host); else server_addr.format("%s:443", host); std::auto_ptr<acl::http_client> backend(new acl::http_client); // 连接服务器 if (connect_server(server_addr, *backend) == false) return false; acl::http_client* front = req.getClient(); // 取得 HTTP 请求头数据 acl::string req_hdr; front->sprint_header(req_hdr, NULL); // 转发 HTTP 请求头至服务器 if (backend->get_ostream().write(req_hdr) == -1) { out_.puts(">>>>write header error"); return false; } if (backend->get_ostream().write("\r\n") == -1) { out_.puts(">>>>write CRLF error"); return false; } // 如果还有数据体,则转发请求的数据体给服务器 long long int len = req.getContentLength(); if (len > 0) { char req_body[8192]; int ret; while (true) { ret = front->read_body(req_body, sizeof(req_body) - 1); if (ret < 0) { out_.puts(">>> read req body error"); return false; } if (ret == 0) break; req_body[ret] = 0; out_.write(req_body, ret); if (backend->get_ostream().write(req_body, ret) == -1) { out_.puts(">>> write body to server error"); return false; } } } out_.puts(""); // 开始从后端服务器读取响应头和响应体数据 out_.puts(">>>> begin read res header<<<<<"); if (backend->read_head() == false) { out_.puts(">>>>>>>>read header error<<<<<<<<<<"); return false; } acl::string res_hdr; backend->sprint_header(res_hdr, NULL); if (res.getOutputStream().write(res_hdr) == -1) { out_.puts(">>>>>write res hdr error<<<<<<"); return false; } if (res.getOutputStream().write("\r\n") == -1) { out_.puts(">>>write CRLF error"); return false; } out_.puts("------------------res hdr----------------"); out_.write(res_hdr); out_.puts("------------------res hdr end------------"); char buf[8192]; while (true) { int ret = backend->read_body(buf, sizeof(buf) - 1); if (ret < 0) { logger_error(">>> read body error"); return false; } else if (ret == 0) break; buf[ret] = 0; out_.write(buf, ret); if (res.getOutputStream().write(buf, ret) == -1) { out_.puts(">>> write res body error"); return false; } } const char* ptr = backend->header_value("Transfer-Encoding"); if (ptr == NULL || *ptr == 0 || strcasecmp(ptr, "chunked") != 0) return backend->keep_alive(); // 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次 // res.write 且两个参数均为 0 以表示 chunk 传输数据结束 return res.write(NULL, 0); }
bool http_servlet::doPost(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { res.setContentType("text/xml; charset=gbk") // 设置响应字符集 .setKeepAlive(req.isKeepAlive()) // 设置是否保持长连接 .setContentEncoding(true) // 自动支持压缩传输 .setChunkedTransferEncoding(true); // 采用 chunk 传输方式 // 获得 HTTP 请求的数据类型,正常的参数类型,即 name&value 方式 // 还是 MIME 数据类型,还是数据流类型 acl::http_request_t request_type = req.getRequestType(); if (request_type != acl::HTTP_REQUEST_MULTIPART_FORM) { acl::string buf; buf.format("<root error='should acl::HTTP_REQUEST_MULTIPART_FORM' />\r\n"); (void) res.write(buf); (void) res.write(NULL, 0); return false; } // 先获得 Content-Type 对应的 http_ctype 对象 mime_ = req.getHttpMime(); if (mime_ == NULL) { logger_error("http_mime null"); (void) doReply(req, res, "http_mime null"); return false; } // 获得数据体的长度 content_length_ = req.getContentLength(); if (content_length_ <= 0) { logger_error("body empty"); (void) doReply(req, res, "body empty"); return false; } acl::string filepath; #if defined(_WIN32) || defined(_WIN64) filepath.format("%s\\mime_file", var_cfg_var_path); #else filepath.format("%s/mime_file", var_cfg_var_path); #endif if (fp_.open_write(filepath) == false) { logger_error("open %s error %s", filepath.c_str(), acl::last_serror()); (void) doReply(req, res, "open file error"); return false; } // 设置原始文件存入路径 mime_->set_saved_path(filepath); req_ = &req; res_ = &res; read_body_ = true; // 直接返回,从而触发异步读 HTTP 数据体过程 return true; }