mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-30 02:47:56 +08:00
optimize http_aclient
This commit is contained in:
parent
f695bf2381
commit
624f828575
@ -18,31 +18,105 @@ class polarssl_conf;
|
||||
class polarssl_io;
|
||||
class http_header;
|
||||
|
||||
/**
|
||||
* HTTP 客户端异步通信类,支持 SSL 加密传输
|
||||
*/
|
||||
class ACL_CPP_API http_aclient : public aio_open_callback
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 构造函数
|
||||
* @param handle {aio_handle&} 异步通信事件引擎句柄
|
||||
* @param ssl_conf {polarssl_conf*} 非 NULL 时自动采用 SSL 通信方式
|
||||
*/
|
||||
http_aclient(aio_handle& handle, polarssl_conf* ssl_conf = NULL);
|
||||
~http_aclient(void);
|
||||
virtual ~http_aclient(void);
|
||||
|
||||
/**
|
||||
* 当对象销毁时的回调方法,子类必须实现
|
||||
*/
|
||||
virtual void destroy(void) = 0;
|
||||
|
||||
/**
|
||||
* 获得 HTTP 请求头,以便于应用添加 HTTP 请求头中的字段内容
|
||||
* @return {http_header&}
|
||||
*/
|
||||
http_header& request_header(void);
|
||||
|
||||
bool open(const char* addr, int conn_timeout);
|
||||
/**
|
||||
* 开始异步连接远程 WEB 服务器
|
||||
* @param addr {const char*} 远程 WEB 服务器地址,格式为:
|
||||
* domain:port 或 ip:port, 当地址为域名时,内部自动进行异步域名解析
|
||||
* 过程,但要求在程序开始时必须通过 aio_handle::set_dns() 设置过域名
|
||||
* 服务器地址,如果地址为 IP 则不需要先设置域名服务器地址
|
||||
* @param conn_timeout {int} 连接超时时间(秒)
|
||||
* @param rw_timeout {int} 网络 IO 读写超时时间(秒)
|
||||
* @return {bool} 返回 false 表示连接失败,返回 true 表示进入异步连接中
|
||||
*/
|
||||
bool open(const char* addr, int conn_timeout, int rw_timeout);
|
||||
|
||||
/**
|
||||
* 当连接成功后的回调方法,子类必须实现,子类应在该方法里构造 HTTP 请求
|
||||
* 并调用 send_request 方法向 WEB 服务器发送 HTTP 请求
|
||||
* @return {bool} 该方法如果返回 false 则内部会自动关闭连接
|
||||
*/
|
||||
virtual bool on_connect(void) = 0;
|
||||
virtual void on_disconnect(void) = 0;
|
||||
virtual void on_connect_timeout(void) = 0;
|
||||
virtual void on_connect_failed(void) = 0;
|
||||
|
||||
/**
|
||||
* 当连接超时后的回调方法
|
||||
*/
|
||||
virtual void on_connect_timeout(void) {}
|
||||
|
||||
/**
|
||||
* 当连接失败后的回调方法
|
||||
*/
|
||||
virtual void on_connect_failed(void) {}
|
||||
|
||||
/**
|
||||
* 当网络读超时时的回调方法
|
||||
*/
|
||||
virtual void on_read_timeout(void) {}
|
||||
|
||||
/**
|
||||
* 对于连接成功后连接关闭后的回调方法
|
||||
*/
|
||||
virtual void on_disconnect(void) {};
|
||||
|
||||
/**
|
||||
* 当接收到 WEB 服务端的响应头时的回调方法,子类必须实现
|
||||
* @param header {const http_header&}
|
||||
* @return {bool} 返回 false 则将会关闭连接,否则继续读
|
||||
*/
|
||||
virtual bool on_http_res_hdr(const http_header& header) = 0;
|
||||
|
||||
/**
|
||||
* 当接收到 WEB 服务端的响应体时的回调方法,子类必须实现,该方法可能
|
||||
* 会被多次回调走到响应数据读完或出错
|
||||
* @param data {char*} 读到的部分数据体内容
|
||||
* @param dlen {size_t} 本次读到的 data 数据的长度
|
||||
* @return {bool} 返回 false 则将会关闭连接,否则继续读
|
||||
*/
|
||||
virtual bool on_http_res_body(char* data, size_t dlen) = 0;
|
||||
virtual bool on_http_res_finish(void) = 0;
|
||||
|
||||
/**
|
||||
* 当读完 HTTP 响应体或出错后的回调方法,子类必须实现
|
||||
* @param success {bool} 是否成功读完 HTTP 响应体数据
|
||||
* @return {bool} 如果成功读完数据体后返回 false 则会关闭连接
|
||||
*/
|
||||
virtual bool on_http_res_finish(bool success) = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* 向 WEB 服务器发送 HTTP 请求,内部在发送后会自动开始读 HTTP 响应过程
|
||||
* @param body {const void*} HTTP 请求的数据体,当为 NULL 时,内部会自
|
||||
* 动采用 HTTP GET 方法
|
||||
* @param len {size_t} body 非 NULL 时表示数据体的长度
|
||||
*/
|
||||
void send_request(const void* body, size_t len);
|
||||
|
||||
protected:
|
||||
// @override
|
||||
bool open_callback(void);
|
||||
// @override dummy
|
||||
bool open_callback(void) { return true; }
|
||||
|
||||
// @override
|
||||
bool timeout_callback(void);
|
||||
@ -59,10 +133,12 @@ protected:
|
||||
protected:
|
||||
aio_handle& handle_;
|
||||
polarssl_conf* ssl_conf_;
|
||||
int rw_timeout_;
|
||||
aio_socket_stream* conn_;
|
||||
http_header* header_;
|
||||
HTTP_HDR_RES* hdr_res_;
|
||||
HTTP_RES* http_res_;
|
||||
bool keep_alive_;
|
||||
|
||||
private:
|
||||
static int connect_callback(ACL_ASTREAM* stream, void* ctx);
|
||||
|
@ -5,42 +5,44 @@
|
||||
//#include "lib_acl.h"
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
|
||||
static acl::polarssl_conf* __ssl_conf;
|
||||
static int __conn_timeout = 5;
|
||||
|
||||
class http_aio_client : public acl::http_aclient
|
||||
{
|
||||
public:
|
||||
http_aio_client(acl::aio_handle& handle, acl::polarssl_conf* ssl_conf,
|
||||
const char* host)
|
||||
: http_aclient(handle, ssl_conf)
|
||||
//, keep_alive_(true)
|
||||
, keep_alive_(false)
|
||||
, host_(host)
|
||||
, debug_(false)
|
||||
, compressed_(false)
|
||||
{
|
||||
}
|
||||
|
||||
~http_aio_client(void)
|
||||
{
|
||||
printf("delete http_aio_client and begin stop aio engine\r\n");
|
||||
handle_.stop();
|
||||
}
|
||||
|
||||
http_aio_client& enable_debug(bool on)
|
||||
{
|
||||
debug_ = on;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
// @override
|
||||
void destroy(void)
|
||||
{
|
||||
printf("http_aio_client will be deleted!\r\n");
|
||||
fflush(stdout);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
// @override
|
||||
bool on_connect(void)
|
||||
{
|
||||
acl::http_header& head = this->request_header();
|
||||
head.set_url("/")
|
||||
.set_content_length(0)
|
||||
.set_host(host_)
|
||||
.accept_gzip(true)
|
||||
//.accept_gzip(false)
|
||||
.set_keep_alive(keep_alive_);
|
||||
|
||||
acl::string buf;
|
||||
head.build_request(buf);
|
||||
printf("---------------request header-----------------\r\n");
|
||||
printf("[%s]\r\n", buf.c_str());
|
||||
printf("---------------begin send http request -------\r\n");
|
||||
fflush(stdout);
|
||||
|
||||
this->send_request(NULL, 0);
|
||||
@ -52,13 +54,13 @@ protected:
|
||||
{
|
||||
printf("disconnect from server\r\n");
|
||||
fflush(stdout);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
// @override
|
||||
void on_connect_timeout(void)
|
||||
{
|
||||
printf("connect timeout\r\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// @override
|
||||
@ -66,8 +68,6 @@ protected:
|
||||
{
|
||||
printf("connect failed\r\n");
|
||||
fflush(stdout);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
// @override
|
||||
@ -76,18 +76,19 @@ protected:
|
||||
acl::string buf;
|
||||
header.build_response(buf);
|
||||
|
||||
compressed_ = header.is_transfer_gzip();
|
||||
|
||||
printf("---------------response header-----------------\r\n");
|
||||
printf("[%s]\r\n", buf.c_str());
|
||||
fflush(stdout);
|
||||
|
||||
keep_alive_ = header.get_keep_alive();
|
||||
return true;
|
||||
}
|
||||
|
||||
// @override
|
||||
bool on_http_res_body(char* data, size_t dlen)
|
||||
{
|
||||
if (0) {
|
||||
if (debug_ && !compressed_) {
|
||||
(void) write(1, data, dlen);
|
||||
} else {
|
||||
printf(">>>read body: %ld\r\n", dlen);
|
||||
@ -96,42 +97,33 @@ protected:
|
||||
}
|
||||
|
||||
// @override
|
||||
bool on_http_res_finish(void)
|
||||
bool on_http_res_finish(bool success)
|
||||
{
|
||||
printf("---------------response over-------------------\r\n");
|
||||
printf("http finish: keep_alive=%s\r\n",
|
||||
keep_alive_ ? "true" : "false");
|
||||
printf("http finish: keep_alive=%s, success=%s\r\n",
|
||||
keep_alive_ ? "true" : "false",
|
||||
success ? "ok" : "failed");
|
||||
fflush(stdout);
|
||||
|
||||
return keep_alive_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool keep_alive_;
|
||||
acl::string host_;
|
||||
bool debug_;
|
||||
bool compressed_;
|
||||
};
|
||||
|
||||
static bool connect_server(acl::aio_handle& handle, const char* addr,
|
||||
const char* host)
|
||||
{
|
||||
http_aio_client* conn = new http_aio_client(handle, __ssl_conf, host);
|
||||
if (!conn->open(addr, __conn_timeout)) {
|
||||
printf("connect %s error\r\n", addr);
|
||||
fflush(stdout);
|
||||
|
||||
delete conn;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void usage(const char* procname)
|
||||
{
|
||||
printf("usage: %s -h[help]\r\n"
|
||||
" -s server_addr\r\n"
|
||||
" -D [if in debug mode, default: false]\r\n"
|
||||
" -c cocorrent\r\n"
|
||||
" -t connect_timeout\r\n"
|
||||
" -t connect_timeout[default: 5]\r\n"
|
||||
" -i rw_timeout[default: 5]\r\n"
|
||||
" -Z [enable_gzip, default: false]\r\n"
|
||||
" -K [keep_alive, default: false]\r\n"
|
||||
" -S polarssl_lib_path[default: none]\n"
|
||||
" -N name_server[default: 8.8.8.8:53]\r\n"
|
||||
, procname);
|
||||
@ -139,11 +131,13 @@ static void usage(const char* procname)
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int ch;
|
||||
acl::polarssl_conf* ssl_conf = NULL;
|
||||
int ch, conn_timeout = 5, rw_timeout = 5;
|
||||
acl::string addr("127.0.0.1:80"), name_server("8.8.8.8:53");
|
||||
acl::string host("www.baidu.com"), ssl_lib_path;
|
||||
bool enable_gzip = false, keep_alive = false, debug = false;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:S:N:H:")) > 0) {
|
||||
while ((ch = getopt(argc, argv, "hs:S:N:H:t:i:ZKD")) > 0) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
@ -160,6 +154,21 @@ int main(int argc, char* argv[])
|
||||
case 'H':
|
||||
host = optarg;
|
||||
break;
|
||||
case 't':
|
||||
conn_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
rw_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'Z':
|
||||
enable_gzip = true;
|
||||
break;
|
||||
case 'K':
|
||||
keep_alive = true;
|
||||
break;
|
||||
case 'D':
|
||||
debug = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -168,23 +177,49 @@ int main(int argc, char* argv[])
|
||||
acl::acl_cpp_init();
|
||||
acl::log::stdout_open(true);
|
||||
|
||||
// 如果设置了 SSL 连接库,则启用 SSL 连接模式
|
||||
if (!ssl_lib_path.empty()) {
|
||||
if (access(ssl_lib_path.c_str(), R_OK) == 0) {
|
||||
__ssl_conf = new acl::polarssl_conf;
|
||||
ssl_conf = new acl::polarssl_conf;
|
||||
} else {
|
||||
printf("disable ssl, %s not found\r\n",
|
||||
ssl_lib_path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// 定义 AIO 事件引擎
|
||||
acl::aio_handle handle(acl::ENGINE_KERNEL);
|
||||
|
||||
// 设置 DNS 域名服务器地址
|
||||
handle.set_dns(name_server.c_str(), 5);
|
||||
|
||||
if (!connect_server(handle, addr, host)) {
|
||||
// 开始异步连接远程 WEB 服务器
|
||||
http_aio_client* conn = new http_aio_client(handle, ssl_conf, host);
|
||||
if (!conn->open(addr, conn_timeout, rw_timeout)) {
|
||||
printf("connect %s error\r\n", addr.c_str());
|
||||
fflush(stdout);
|
||||
|
||||
delete conn;
|
||||
return 1;
|
||||
}
|
||||
|
||||
conn->enable_debug(debug);
|
||||
|
||||
// 设置 HTTP 请求头,也可将此过程放在 conn->on_connect() 里
|
||||
acl::http_header& head = conn->request_header();
|
||||
head.set_url("/")
|
||||
.set_content_length(0)
|
||||
.set_host(host)
|
||||
.accept_gzip(enable_gzip)
|
||||
.set_keep_alive(keep_alive);
|
||||
|
||||
acl::string buf;
|
||||
head.build_request(buf);
|
||||
printf("---------------request header-----------------\r\n");
|
||||
printf("[%s]\r\n", buf.c_str());
|
||||
fflush(stdout);
|
||||
|
||||
// 开始 AIO 事件循环过程
|
||||
while (true) {
|
||||
// 如果返回 false 则表示不再继续,需要退出
|
||||
if (!handle.check()) {
|
||||
@ -193,7 +228,6 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
handle.check();
|
||||
delete __ssl_conf;
|
||||
return (0);
|
||||
delete ssl_conf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,11 @@ namespace acl
|
||||
http_aclient::http_aclient(aio_handle& handle, polarssl_conf* ssl_conf /* NULL */)
|
||||
: handle_(handle)
|
||||
, ssl_conf_(ssl_conf)
|
||||
, rw_timeout_(0)
|
||||
, conn_(NULL)
|
||||
, hdr_res_(NULL)
|
||||
, http_res_(NULL)
|
||||
, keep_alive_(false)
|
||||
{
|
||||
header_ = NEW http_header;
|
||||
}
|
||||
@ -37,7 +39,7 @@ http_header& http_aclient::request_header(void)
|
||||
return *header_;
|
||||
}
|
||||
|
||||
bool http_aclient::open(const char* addr, int conn_timeout)
|
||||
bool http_aclient::open(const char* addr, int conn_timeout, int rw_timeout)
|
||||
{
|
||||
ACL_AIO* aio = handle_.get_handle();
|
||||
if (acl_aio_connect_addr(aio, addr, conn_timeout,
|
||||
@ -46,6 +48,7 @@ bool http_aclient::open(const char* addr, int conn_timeout)
|
||||
logger_error("connect %s error %s", addr, last_serror());
|
||||
return false;
|
||||
}
|
||||
rw_timeout_ = rw_timeout;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -54,17 +57,30 @@ int http_aclient::connect_callback(ACL_ASTREAM *stream, void *ctx)
|
||||
http_aclient* me = (http_aclient*) ctx;
|
||||
|
||||
if (stream == NULL) {
|
||||
me->on_connect_failed();
|
||||
if (last_error() == ACL_ETIMEDOUT) {
|
||||
me->on_connect_timeout();
|
||||
me->destroy();
|
||||
} else {
|
||||
me->on_connect_failed();
|
||||
me->destroy();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 连接成功,创建 C++ AIO 连接对象
|
||||
me->conn_ = new aio_socket_stream(&me->handle_, stream, true);
|
||||
|
||||
// 注册连接关闭回调处理对象
|
||||
me->conn_->add_close_callback(me);
|
||||
|
||||
// 注册 IO 超时回调处理对象
|
||||
me->conn_->add_timeout_callback(me);
|
||||
|
||||
if (!me->ssl_conf_) {
|
||||
return me->on_connect() ? 0 : -1;
|
||||
}
|
||||
|
||||
// 因为配置了 SSL 通信方式,所以需要创建 SSL IO 过程,开始 SSL 握手
|
||||
polarssl_io* ssl_io = new polarssl_io(*me->ssl_conf_, false, true);
|
||||
if (me->conn_->setup_hook(ssl_io) == ssl_io || !ssl_io->handshake()) {
|
||||
logger_error("open ssl failed");
|
||||
@ -74,26 +90,27 @@ int http_aclient::connect_callback(ACL_ASTREAM *stream, void *ctx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 开始 SSL 握手过程,read_wait 对应的回调方法为 read_wakeup
|
||||
me->conn_->add_read_callback(me);
|
||||
me->conn_->read_wait(0);
|
||||
me->conn_->read_wait(me->rw_timeout_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool http_aclient::open_callback(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool http_aclient::timeout_callback(void)
|
||||
{
|
||||
this->on_read_timeout();
|
||||
return false;
|
||||
}
|
||||
|
||||
void http_aclient::close_callback(void)
|
||||
{
|
||||
// 网络关闭时回调子类重载方法
|
||||
this->on_disconnect();
|
||||
// 对象销毁
|
||||
this->destroy();
|
||||
}
|
||||
|
||||
// 在 SSL 握手阶段,该方法会多次调用,直至 SSL 握手成功或失败
|
||||
bool http_aclient::read_wakeup(void)
|
||||
{
|
||||
polarssl_io* ssl_io = (polarssl_io*) conn_->get_hook();
|
||||
@ -105,12 +122,15 @@ bool http_aclient::read_wakeup(void)
|
||||
logger_error("ssl handshake error!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// SSL 握手成功后,回调连接成功方法,通知子类可以发送请求数据
|
||||
if (ssl_io->handshake_ok()) {
|
||||
conn_->del_read_callback(this);
|
||||
conn_->disable_read();
|
||||
return this->on_connect();
|
||||
}
|
||||
|
||||
// 继续 SSL 握手过程
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -128,14 +148,27 @@ int http_aclient::http_res_hdr_cllback(int status, void* ctx)
|
||||
|
||||
http_hdr_res_parse(me->hdr_res_);
|
||||
|
||||
// 将 C HTTP 响应头转换成 C++ HTTP 响应头,并回调子类方法
|
||||
http_header header(*me->hdr_res_);
|
||||
if (!me->on_http_res_hdr(header)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
me->http_res_ = http_res_new(me->hdr_res_);
|
||||
me->keep_alive_ = header.get_keep_alive();
|
||||
me->http_res_ = http_res_new(me->hdr_res_);
|
||||
|
||||
// 如果响应数据体长度为 0,则表示该 HTTP 响应完成
|
||||
if (header.get_content_length() == 0) {
|
||||
if (me->on_http_res_finish(true) && me->keep_alive_) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 开始异步读取 HTTP 响应体数据
|
||||
http_res_body_get_async(me->http_res_, me->conn_->get_astream(),
|
||||
http_res_callback, me, 0);
|
||||
http_res_callback, me, me->rw_timeout_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,18 +181,25 @@ int http_aclient::http_res_callback(int status, char* data, int dlen, void* ctx)
|
||||
case HTTP_CHAT_CHUNK_TRAILER:
|
||||
return 0;
|
||||
case HTTP_CHAT_OK:
|
||||
if (data == NULL || dlen <= 0) {
|
||||
return me->on_http_res_finish();
|
||||
if (data && dlen > 0) {
|
||||
// 将读到的 HTTP 响应体数据传递给子类
|
||||
if (!me->on_http_res_body(data, (size_t) dlen)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!me->on_http_res_body(data, (size_t) dlen)) {
|
||||
|
||||
// 读完 HTTP 响应数据,回调完成方法
|
||||
if (me->on_http_res_finish(true) && me->keep_alive_) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return me->on_http_res_finish() ? 0 : -1;
|
||||
case HTTP_CHAT_ERR_IO:
|
||||
case HTTP_CHAT_ERR_PROTO:
|
||||
(void) me->on_http_res_finish();
|
||||
(void) me->on_http_res_finish(false);
|
||||
return -1;
|
||||
case HTTP_CHAT_DATA:
|
||||
// 将读到的 HTTP 响应体数据传递给子类
|
||||
return me->on_http_res_body(data, (size_t) dlen) ? 0 : -1;
|
||||
default:
|
||||
return 0;
|
||||
@ -176,16 +216,20 @@ void http_aclient::send_request(const void* body, size_t len)
|
||||
header_->set_method(HTTP_METHOD_POST);
|
||||
}
|
||||
|
||||
// 创建 HTTP 请求头并发送
|
||||
string buf;
|
||||
header_->build_request(buf);
|
||||
conn_->write(buf.c_str(), (int) buf.size());
|
||||
|
||||
if (body && len > 0) {
|
||||
// 发送 HTTP 请求体
|
||||
conn_->write(body, (int) len);
|
||||
}
|
||||
|
||||
// 开始读取 HTTP 响应头
|
||||
hdr_res_ = http_hdr_res_new();
|
||||
http_hdr_res_get_async(hdr_res_, conn_->get_astream(),
|
||||
http_res_hdr_cllback, this, 0);
|
||||
http_res_hdr_cllback, this, rw_timeout_);
|
||||
}
|
||||
|
||||
} // namespace acl
|
||||
|
@ -80,12 +80,18 @@ http_header::http_header(const HTTP_HDR_RES& hdr_res, dbuf_guard* dbuf /* = NULL
|
||||
accept_compress_ = false;
|
||||
status_ = hdr_res.reply_status;
|
||||
cgi_mode_ = false;
|
||||
range_from_ = -1;
|
||||
range_to_ = -1;
|
||||
content_length_ = hdr_res.hdr.content_length;
|
||||
chunked_transfer_ = hdr_res.hdr.chunked ? true : false;
|
||||
transfer_gzip_ = false;
|
||||
|
||||
if (http_hdr_res_range(&hdr_res, &range_from_,
|
||||
&range_to_, &range_total_) == -1) {
|
||||
|
||||
range_from_ = -1;
|
||||
range_to_ = -1;
|
||||
range_total_ = -1;
|
||||
}
|
||||
|
||||
upgrade_ = NULL;
|
||||
ws_origin_ = NULL;
|
||||
ws_sec_key_ = NULL;
|
||||
@ -96,9 +102,16 @@ http_header::http_header(const HTTP_HDR_RES& hdr_res, dbuf_guard* dbuf /* = NULL
|
||||
ACL_ITER iter;
|
||||
acl_foreach(iter, hdr_res.hdr.entry_lnk) {
|
||||
HTTP_HDR_ENTRY* entry = (HTTP_HDR_ENTRY*) iter.data;
|
||||
if (!entry->off) {
|
||||
add_entry(entry->name, entry->value);
|
||||
if (entry->off) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcasecmp(entry->name, "Content-Encoding")) {
|
||||
if (!strcasecmp(entry->value, "gzip")) {
|
||||
transfer_gzip_ = true;
|
||||
}
|
||||
}
|
||||
add_entry(entry->name, entry->value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,12 +138,15 @@ http_header::http_header(const HTTP_HDR_REQ& hdr_req, dbuf_guard* dbuf /* = NULL
|
||||
accept_compress_ = false;
|
||||
status_ = 0;
|
||||
cgi_mode_ = false;
|
||||
range_from_ = -1;
|
||||
range_to_ = -1;
|
||||
content_length_ = hdr_req.hdr.content_length;
|
||||
chunked_transfer_ = hdr_req.hdr.chunked ? true : false;
|
||||
transfer_gzip_ = false;
|
||||
|
||||
if (http_hdr_req_range(&hdr_req, &range_from_, &range_to_) == -1) {
|
||||
range_from_ = -1;
|
||||
range_to_ = -1;
|
||||
}
|
||||
|
||||
upgrade_ = NULL;
|
||||
ws_origin_ = NULL;
|
||||
ws_sec_key_ = NULL;
|
||||
|
@ -262,19 +262,19 @@ HTTP_API const char *http_hdr_req_cookie_get(HTTP_HDR_REQ *hh, const char *name)
|
||||
|
||||
/**
|
||||
* 从HTTP请求头中取得HTTP请求的方法, 如: POST, GET, CONNECT
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @return {const char*} 返回请示方法. NULL: error; !NULL: OK.
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_method(HTTP_HDR_REQ *hh);
|
||||
HTTP_API const char *http_hdr_req_method(const HTTP_HDR_REQ *hh);
|
||||
|
||||
/**
|
||||
* 从HTTP请求头中获取请求URL中某个请求字段的数据,
|
||||
* 如取: /cgi-bin/test.cgi?n1=v1&n2=v2 中的 n2的值v2
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param name {const char*} 请求参数中的变量名
|
||||
* @return {const char*} !NULL: ok, 返回变量值的内存指针; NULL: 出错,或请求的变量名不存在.
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_param(HTTP_HDR_REQ *hh, const char *name);
|
||||
HTTP_API const char *http_hdr_req_param(const HTTP_HDR_REQ *hh, const char *name);
|
||||
|
||||
/**
|
||||
* 从HTTP请求头中获取请求行中的访问路径部分, 不包含主机名但包含参数.
|
||||
@ -284,10 +284,10 @@ HTTP_API const char *http_hdr_req_param(HTTP_HDR_REQ *hh, const char *name);
|
||||
* GET http://www.test.com[:80]/cgi-bin/test.cgi?n1=v1&n2=v2 HTTP/1.1
|
||||
* 则分析后的结果数据为:
|
||||
* /cgi-bin/test.cgi?n1=v1&n2=v2
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @return {const char*} 请示的URL. !NULL: OK; NULL: error.
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_url_part(HTTP_HDR_REQ *hh);
|
||||
HTTP_API const char *http_hdr_req_url_part(const HTTP_HDR_REQ *hh);
|
||||
|
||||
/**
|
||||
* 从HTTP请求头中获取请求行中的访问路径部分, 不包含主机名及参数.
|
||||
@ -297,18 +297,18 @@ HTTP_API const char *http_hdr_req_url_part(HTTP_HDR_REQ *hh);
|
||||
* GET http://www.test.com[:80]/cgi-bin/test.cgi?n1=v1&n2=v2 HTTP/1.1
|
||||
* 则分析后的结果数据为:
|
||||
* /cgi-bin/test.cgi
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @return {const char*} 请示的URL. !NULL: OK; NULL: error.
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_url_path(HTTP_HDR_REQ *hh);
|
||||
HTTP_API const char *http_hdr_req_url_path(const HTTP_HDR_REQ *hh);
|
||||
|
||||
/**
|
||||
* 从HTTP请求协议头中获得服务器的主机IP或域名,格式为:IP|domain[:PORT]
|
||||
* 如: 192.168.0.22:80, or www.test.com:8088
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @return {const char*} 返回用户请示的主机名. !NULL: ok; NULL: error.
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_host(HTTP_HDR_REQ *hh);
|
||||
HTTP_API const char *http_hdr_req_host(const HTTP_HDR_REQ *hh);
|
||||
|
||||
/**
|
||||
* 从HTTP请求头协议中获得完整的URL请求字符串
|
||||
@ -317,7 +317,7 @@ HTTP_API const char *http_hdr_req_host(HTTP_HDR_REQ *hh);
|
||||
* HOST: www.test.com
|
||||
* 则经该函数后则返回:
|
||||
* http://www.test.com/cgi-bin/test.cgi?n1=v1&n2=v2
|
||||
* @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @param hh {const HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空
|
||||
* @return {const char*} 请示的URL. !NULL: OK; NULL: error.
|
||||
* @example:
|
||||
* void test(HTTP_HDR_REQ *hh)
|
||||
@ -353,7 +353,7 @@ HTTP_API const char *http_hdr_req_host(HTTP_HDR_REQ *hh);
|
||||
* acl_myfree(url2);
|
||||
* }
|
||||
*/
|
||||
HTTP_API const char *http_hdr_req_url(HTTP_HDR_REQ *hh);
|
||||
HTTP_API const char *http_hdr_req_url(const HTTP_HDR_REQ *hh);
|
||||
|
||||
/**
|
||||
* 分析HTTP请求头中的 Range 字段
|
||||
@ -364,8 +364,8 @@ HTTP_API const char *http_hdr_req_url(HTTP_HDR_REQ *hh);
|
||||
* 请求的 Range 格式:
|
||||
* Range: bytes={range_from}-, bytes={range_from}-{range_to}
|
||||
*/
|
||||
HTTP_API int http_hdr_req_range(HTTP_HDR_REQ *hdr_req, http_off_t *range_from,
|
||||
http_off_t *range_to);
|
||||
HTTP_API int http_hdr_req_range(const HTTP_HDR_REQ *hdr_req,
|
||||
http_off_t *range_from, http_off_t *range_to);
|
||||
|
||||
/*---------------------------- HTTP 响应头操作函数 ---------------------------*/
|
||||
/* in http_hdr_res.c */
|
||||
@ -415,12 +415,13 @@ HTTP_API int http_hdr_res_parse(HTTP_HDR_RES *hdr_res);
|
||||
* @param range_from {http_off_t*} 存储偏移起始位置, 不能为空
|
||||
* @param range_to {http_off_t*} 存储偏移结束位置, 不能为空
|
||||
* @param total_length {http_off_t*} 整个数据文件的总长度, 可为空
|
||||
* @return {int} 返回 0 表示成功,-1 表示失败
|
||||
* 注: * {range_from}, {range_to} 下标从0开始
|
||||
* 响应的 Range 格式:
|
||||
* Content-Range: bytes {range_from}-{range_to}/{total_length}
|
||||
*/
|
||||
HTTP_API int http_hdr_res_range(HTTP_HDR_RES *hdr_res, http_off_t *range_from,
|
||||
http_off_t *range_to, http_off_t *total_length);
|
||||
HTTP_API int http_hdr_res_range(const HTTP_HDR_RES *hdr_res,
|
||||
http_off_t *range_from, http_off_t *range_to, http_off_t *total_length);
|
||||
|
||||
/* in http_rfc1123.c */
|
||||
|
||||
@ -742,4 +743,3 @@ HTTP_API http_off_t http_buf_size_get(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -914,14 +914,14 @@ HTTP_HDR_REQ *http_hdr_req_rewrite(const HTTP_HDR_REQ *hh, const char *url)
|
||||
|
||||
/* 取得HTTP请求的方法 */
|
||||
|
||||
const char *http_hdr_req_method(HTTP_HDR_REQ *hh)
|
||||
const char *http_hdr_req_method(const HTTP_HDR_REQ *hh)
|
||||
{
|
||||
return hh->method;
|
||||
}
|
||||
|
||||
/* 获取请求URL中某个请求字段的数据, 如取: /cgi-bin/n1=v1&n2=v2 中的 n2的值v2 */
|
||||
|
||||
const char *http_hdr_req_param(HTTP_HDR_REQ *hh, const char *name)
|
||||
const char *http_hdr_req_param(const HTTP_HDR_REQ *hh, const char *name)
|
||||
{
|
||||
const char *myname = "http_hdr_req_get";
|
||||
|
||||
@ -937,7 +937,7 @@ const char *http_hdr_req_param(HTTP_HDR_REQ *hh, const char *name)
|
||||
return acl_htable_find(hh->params_table, name);
|
||||
}
|
||||
|
||||
const char *http_hdr_req_url_part(HTTP_HDR_REQ *hh)
|
||||
const char *http_hdr_req_url_part(const HTTP_HDR_REQ *hh)
|
||||
{
|
||||
const char *myname = "http_hdr_req_url_part";
|
||||
|
||||
@ -952,7 +952,7 @@ const char *http_hdr_req_url_part(HTTP_HDR_REQ *hh)
|
||||
return acl_vstring_str(hh->url_part);
|
||||
}
|
||||
|
||||
const char *http_hdr_req_url_path(HTTP_HDR_REQ *hh)
|
||||
const char *http_hdr_req_url_path(const HTTP_HDR_REQ *hh)
|
||||
{
|
||||
if (ACL_VSTRING_LEN(hh->url_path) == 0)
|
||||
return NULL;
|
||||
@ -960,7 +960,7 @@ const char *http_hdr_req_url_path(HTTP_HDR_REQ *hh)
|
||||
return acl_vstring_str(hh->url_path);
|
||||
}
|
||||
|
||||
const char *http_hdr_req_host(HTTP_HDR_REQ *hh)
|
||||
const char *http_hdr_req_host(const HTTP_HDR_REQ *hh)
|
||||
{
|
||||
if (hh->host[0] != 0)
|
||||
return hh->host;
|
||||
@ -973,7 +973,7 @@ static void free_vstring(ACL_VSTRING *buf)
|
||||
acl_vstring_free(buf);
|
||||
}
|
||||
|
||||
const char *http_hdr_req_url(HTTP_HDR_REQ *hh)
|
||||
const char *http_hdr_req_url(const HTTP_HDR_REQ *hh)
|
||||
{
|
||||
static acl_pthread_key_t key = (acl_pthread_key_t) -1;
|
||||
ACL_VSTRING *buf;
|
||||
@ -989,7 +989,7 @@ const char *http_hdr_req_url(HTTP_HDR_REQ *hh)
|
||||
return acl_vstring_str(buf);
|
||||
}
|
||||
|
||||
int http_hdr_req_range(HTTP_HDR_REQ *hdr_req, http_off_t *range_from,
|
||||
int http_hdr_req_range(const HTTP_HDR_REQ *hdr_req, http_off_t *range_from,
|
||||
http_off_t *range_to)
|
||||
{
|
||||
const char *myname = "http_hdr_req_range";
|
||||
|
@ -246,7 +246,7 @@ int http_hdr_res_parse(HTTP_HDR_RES *hdr_res)
|
||||
return (http_hdr_parse(hdr));
|
||||
}
|
||||
|
||||
int http_hdr_res_range(HTTP_HDR_RES *hdr_res, http_off_t *range_from,
|
||||
int http_hdr_res_range(const HTTP_HDR_RES *hdr_res, http_off_t *range_from,
|
||||
http_off_t *range_to, http_off_t *total_length)
|
||||
{
|
||||
const char* myname = "http_hdr_res_range";
|
||||
|
Loading…
Reference in New Issue
Block a user