bool http_header::build_response(string& out) const { out.clear(); if (status_ > 0) { if (cgi_mode_) out.format("STATUS: %d\r\n", status_); else { out = "HTTP/1.1 "; out << status_ << " " << http_status(status_) << "\r\n"; time_t now = time(NULL); char buf[64]; date_format(buf, sizeof(buf), now); out << "Date: " << buf << "\r\n"; out << "Server: acl\r\n"; } } if (!cookies_.empty()) { std::list<HttpCookie*>::const_iterator it = cookies_.begin(); for (; it != cookies_.end(); ++it) { out.format_append("Set-Cookie: %s=%s", (*it)->getName(), (*it)->getValue()); const std::list<HTTP_PARAM*>& params = (*it)->getParams(); std::list<HTTP_PARAM*>::const_iterator cit = params.begin(); for (; cit != params.end(); ++ cit) { out.format_append("; %s=%s", (*cit)->name, (*cit)->value); } out << "\r\n"; } } // 添加分段响应字段 if (range_from_ >= 0 && range_to_ >= range_from_ && range_total_ > 0) out << "Content-Range: bytes=" << range_from_ << '-' << range_to_ << '/' << range_total_ << "\r\n"; // 如果是 gzip 压缩数据,当非 chunked 传输时,必须取消 Content-Length 字段, // 同时禁止保持长连接,即: Connection: close if (transfer_gzip_) { out << "Content-Encoding: gzip\r\n"; if (!chunked_transfer_ && keep_alive_) const_cast<http_header*>(this)->keep_alive_ = false; if (content_length_ > 0) const_cast<http_header*>(this)->content_length_ = -1; } build_common(out); out << "\r\n"; return true; }
bool http_header::build_response(string& out) const { out.clear(); if (status_ > 0) { if (cgi_mode_) out.format("STATUS: %d\r\n", status_); else { out = "HTTP/1.1 "; out << status_ << " " << http_status(status_) << "\r\n"; time_t now = time(NULL); char buf[64]; date_format(buf, sizeof(buf), now); out << "Date: " << buf << "\r\n"; } } if (!cookies_.empty()) { std::list<HttpCookie*>::const_iterator it = cookies_.begin(); for (; it != cookies_.end(); ++it) { out.format_append("Set-Cookie: %s=%s", (*it)->getName(), (*it)->getValue()); const std::list<HTTP_PARAM*>& params = (*it)->getParams(); std::list<HTTP_PARAM*>::const_iterator cit = params.begin(); for (; cit != params.end(); ++ cit) { out.format_append("; %s=%s", (*cit)->name, (*cit)->value); } out << "\r\n"; } } build_common(out); out << "\r\n"; return true; }
bool http_header::build_request(string& buf) const { if (url_ == NULL || *url_ == 0) { logger_error("url empty"); return (false); } buf.format("%s %s", method_s_, url_); if (!params_.empty()) { buf << '?'; acl::string tmp; int i = 0; std::list<HTTP_PARAM*>::const_iterator it = params_.begin(); for (; it != params_.end(); ++it) { if (i > 0) buf += '&'; else i++; // 需要对参数进行 URL 编码 tmp.url_encode((*it)->name); buf += tmp.c_str(); // 允许参数值为空指针 if ((*it)->value == NULL) continue; buf += '='; // 允许参数值为空串 if (*((*it)->value) == 0) continue; tmp.url_encode((*it)->value); buf += tmp.c_str(); } } buf += " HTTP/1.1\r\n"; if (accept_compress_) // 因为目前的 zlib_stream 仅支持于此 buf += "Accept-Encoding: gzip\r\n"; if (host_[0] != 0) buf.format_append("Host: %s\r\n", host_); if (!cookies_.empty()) { buf += "Cookie: "; std::list<HttpCookie*>::const_iterator it = cookies_.begin(); for (; it != cookies_.end(); ++it) { if (it != cookies_.begin()) buf += "; "; buf << (*it)->getName() << "=" << (*it)->getValue(); } buf += "\r\n"; } // 添加分段请求字段 if (range_from_ >= 0) { buf << "Range: bytes=" << range_from_ << '-'; if (range_to_ >= range_from_) buf << range_to_; buf += "\r\n"; } build_common(buf); buf += "\r\n"; return (true); }