Skip to content

Commit

Permalink
http module in acl has supported gzip transfer in client and server m…
Browse files Browse the repository at this point in the history
…ode.
  • Loading branch information
ubuntu14 committed Aug 18, 2015
1 parent 772ff21 commit d1fe096
Show file tree
Hide file tree
Showing 31 changed files with 875 additions and 199 deletions.
2 changes: 1 addition & 1 deletion app/wizard/tmpl/http/main_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("listen on: %s\r\n", addrs);

// 测试时设置该值 > 0 则指定服务器处理客户端连接过程的
Expand Down
2 changes: 1 addition & 1 deletion app/wizard/tmpl/http/main_threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("listen on: %s\r\n", addrs);

// 测试时设置该值 > 0 则指定服务器处理客户端连接过程的
Expand Down
2 changes: 1 addition & 1 deletion app/wizard/tmpl/master/main_aio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("listen on: %s\r\n", addrs);

// 单独运行方式
Expand Down
2 changes: 1 addition & 1 deletion app/wizard/tmpl/master/main_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("listen on: %s\r\n", addrs);

// 测试时设置该值 > 0 则指定服务器处理客户端连接过程的
Expand Down
2 changes: 1 addition & 1 deletion app/wizard/tmpl/master/main_threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("listen on: %s\r\n", addrs);

// 测试时设置该值 > 0 则指定服务器处理客户端连接过程的
Expand Down
2 changes: 1 addition & 1 deletion app/wizard/tmpl/master/main_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char* argv[])
acl::log::stdout_open(true);

// 监听的地址列表,格式:ip:port1,ip:port2,...
const char* addrs = "127.0.0.1:8888";
const char* addrs = ":8888";
printf("bind on: %s\r\n", addrs);

// 测试时设置该值 > 0 则指定服务器处理客户端连接过程的
Expand Down
11 changes: 11 additions & 0 deletions lib_acl_cpp/changes.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
�޸���ʷ�б���

------------------------------------------------------------------------
346) 2015.8.18
346.1) feature: http_client/http_request ���ڶ�ȡѹ��������ʱ�����Զ�����
��ʱ�������Ϊ 0 ��������Խ���ʹ�ø��Ӷ�

345) 2015.8.17
345.1) http_client gzip ����ѹ���������ͨ��

344) 2015.8.16
344.1) feature: http_client ��֧����Ӧ gzip ѹ�����͵�����
344.2) feature: HttpServletResponse ���е���������������ͳһ�� http_client ����

343) 2015.8.15
343.1) bugfix: redis_string::incoper �ڲ������� INCR �� INCRBY, DECR �� DECRBY
�ķ�������
Expand Down
21 changes: 11 additions & 10 deletions lib_acl_cpp/include/acl_cpp/http/HttpServlet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,36 @@ class ACL_CPP_API HttpServlet
virtual ~HttpServlet(void) = 0;

/**
* 设置本地字符集,如果设置了本地字符集,则在接收 HTTP 请求数据时,会自动将请求的
* 字符集转为本地字符集;该函数必须在 doRun 之前调用才有效
* 设置本地字符集,如果设置了本地字符集,则在接收 HTTP 请求数据时,
* 自动将请求的字符集转为本地字符集;该函数必须在 doRun 之前调用才有效
* @param charset {const char*} 本地字符集,如果该指针为空,
* 则清除本地字符集
* @return {HttpServlet&}
*/
HttpServlet& setLocalCharset(const char* charset);

/**
* 设置 HTTP 会话过程的 IO 读写超时时间;该函数必须在 doRun 之前调用才有效
* 设置 HTTP 会话过程 IO 读写超时时间;该函数必须在 doRun 前调用才有效
* @param rw_timeout {int} 读写超时时间(秒)
* @return {HttpServlet&}
*/
HttpServlet& setRwTimeout(int rw_timeout);

/**
* 针对 POST 方法,该方法设置是否需要解析数据体数据,默认为解析,该函数必须在 doRun
* 之前调用才有效;当数据体为数据流或 MIME 格式,即使调用本方法设置了解析数据,也不
* 会对数据体进行解析
* 针对 POST 方法,该方法设置是否需要解析数据体数据,默认为解析,该函
* 数必须在 doRun 之前调用才有效;当数据体为数据流或 MIME 格式,即使
* 调用本方法设置了解析数据,也不会对数据体进行解析
* @param on {bool} 是否需要解析
* @return {HttpServlet&}
*/
HttpServlet& setParseBody(bool on);

/**
* 针对 POST 方法,该方法设置解析数据体的最大长度,如果数据体,该函数必须在 doRun
* 之前调用才有效
* @param length {int} 最大长度限制,如果请求的数据体长度过大,则直接返回
* false,如果该值 <= 0 则内部不限制数据体长度,调用该函数前内部缺省值为 0
* 针对 POST 方法,该方法设置解析数据体的最大长度,如果数据体,该函数
* 必须在 doRun 之前调用才有效
* @param length {int} 最大长度限制,如果请求的数据体长度过大,则直接
* 返回 false,如果该值 <= 0 则内部不限制数据体长度,调用该函数前
* 内部缺省值为 0
* @return {HttpServlet&}
*/
HttpServlet& setParseBodyLimit(int length);
Expand Down
12 changes: 10 additions & 2 deletions lib_acl_cpp/include/acl_cpp/http/HttpServletRequest.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "acl_cpp/acl_cpp_define.hpp"
#include <vector>
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/http/http_header.hpp"
#include "acl_cpp/http/http_ctype.hpp"
#include "acl_cpp/http/http_type.hpp"
Expand Down Expand Up @@ -135,10 +136,11 @@ class ACL_CPP_API HttpServletRequest
#endif

/**
* 如果客户端的请求是分段数据,则该函数将获得请求头中的长度起始地址及结束地址
* 如果客户端的请求是分段数据,则该函数将获得请求头中的长度起始地址
* 及结束地址
* @param range_from {long long int&} 偏移起始位置
* @param range_to {long long int&} 偏移结束位置
* @return {bool} 若出错或非分段请求则返回 false,若是分段请求则返回 true
* @return {bool} 若出错或非分段请求则返回false,若是分段请求则返回true
* 注:range_from/range_to 下标从 0 开始
*/
#if defined(_WIN32) || defined(_WIN64)
Expand Down Expand Up @@ -278,6 +280,12 @@ class ACL_CPP_API HttpServletRequest
*/
int getKeepAlive(void) const;

/**
* 获得 HTTP 客户端支持的数据压缩算法集合
* @param out {std::vector<string>&} 存储结果集
*/
void getAcceptEncoding(std::vector<string>& out) const;

/*
* 当 HTTP 请求为 POST 方法,通过本函数设置读 HTTP 数据体的
* IO 超时时间值(秒)
Expand Down
33 changes: 27 additions & 6 deletions lib_acl_cpp/include/acl_cpp/http/HttpServletResponse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ class string;
class ostream;
class socket_stream;
class http_header;
class http_client;
class HttpCookie;
class HttpServlet;
class HttpServletRequest;

/**
* 与 HTTP 客户端响应相关的类,该类不应被继承,用户也不需要
Expand Down Expand Up @@ -46,20 +48,30 @@ class ACL_CPP_API HttpServletResponse
/**
* 设置与 HTTP 客户端保持联系长连接
* @param on {bool}
* @return {HttpServletResponse&}
*/
HttpServletResponse& setKeepAlive(bool on);

/**
* 设置 HTTP 响应数据体的 Content-Type 字段值,可字段值可以为:
* text/html 或 text/html; charset=utf8 格式
* @param value {const char*} 字段值
* @return {HttpServletResponse&}
*/
HttpServletResponse& setContentType(const char* value);

/**
* 设置 HTTP 响应数据体采用 gzip 压缩格式
* @param gzip {bool} 是否采用 gzip 压缩格式
* @return {HttpServletResponse&}
*/
HttpServletResponse& setContentEncoding(bool gzip);

/**
* 设置 HTTP 响应数据体中字符集,当已经在 setContentType 设置
* 了字符集,则就不必再调用本函数设置字符集
* @param charset {const char*} 响应体数据的字符集
* @return {HttpServletResponse&}
*/
HttpServletResponse& setCharacterEncoding(const char* charset);

Expand Down Expand Up @@ -88,8 +100,8 @@ class ACL_CPP_API HttpServletResponse
* 对于分区下载,调用本函数设置数据下载的偏移位置(下标从 0 开始)
* @param from {http_off_t} 数据区间起始偏移位置(下标从 0 开始计算)
* @param to {http_off_t} 数据区间结束位置(该值需小于总数据长度)
* @param total {http_off_t} 总数据长度,当数据源为一个静态文件时该值应
* 等于该文件的总长度大小
* @param total {http_off_t} 总数据长度,当数据源为一个静态文件时该值
* 应等于该文件的总长度大小
* @return {HttpServletResponse&}
*/
#if defined(_WIN32) || defined(_WIN64)
Expand Down Expand Up @@ -178,17 +190,18 @@ class ACL_CPP_API HttpServletResponse

/**
* 带格式方式向 HTTP 客户端发送响应数据,内部自动调用
* HttpServletResponse::write(const void*, size_t) 过程,
* 在使用 chunked 方式传输数据时,应该应该最后再调用 write(NULL, 0) 表示数据结束
* HttpServletResponse::write(const void*, size_t) 过程,在使用
* chunked 方式传输数据时,应该应该最后再调用 write(NULL, 0)
* 表示数据结束
* @param fmt {const char*} 变参格式字符串
* @return {int} 成功则返回值 > 0,否则返回 -1
*/
int format(const char* fmt, ...) ACL_CPP_PRINTF(2, 3);

/**
* 带格式方式向 HTTP 客户端发送响应数据,内部自动调用
* HttpServletResponse::write(const string&) 过程,
* 在使用 chunked 方式传输数据时,应该应该最后再调用 write(NULL, 0) 表示数据结束
* HttpServletResponse::write(const string&) 过程,在使用 chunked
* 方式传输数据时,应该应该最后再调用 write(NULL, 0) 表示数据结束
* @param fmt {const char*} 变参格式字符串
* @param ap {va_list} 变参列表
* @return {int} 成功则返回值 > 0,否则返回 -1
Expand All @@ -214,8 +227,16 @@ class ACL_CPP_API HttpServletResponse
*/
ostream& getOutputStream(void) const;

/**
* 设置 http 请求对象,该函数目前只应被 HttpServlet 类内部调用
* @param request {HttpServletRequest*}
*/
void setHttpServletRequest(HttpServletRequest* request);

private:
socket_stream& stream_; // 客户端连接流
HttpServletRequest* request_; // http 请求对象
http_client* client_; // http 响应流对象
http_header* header_; // http 响应头
char charset_[32]; // 字符集
char content_type_[32]; // content-type 类型
Expand Down
26 changes: 19 additions & 7 deletions lib_acl_cpp/include/acl_cpp/http/http_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ class ACL_CPP_API http_client
/**
* 写 HTTP 请求头数据至输出流中
* @param header {http_header&}
* @return {int} 真实写入的数据量, 返回 -1 表示出错
* @return {bool} 写头部数据是否成功
*/
int write_head(const http_header& header);
bool write_head(const http_header& header);

/**
* 发送 HTTP 数据体,可以循环调用此函数,当在第一次调用 write 函数写入
Expand Down Expand Up @@ -282,11 +282,15 @@ class ACL_CPP_API http_client
* @param clean {bool} 在接收数据前是否自动清空 buf 缓冲区
* @param real_size {int*} 若该指针非空,则记录真正读到的数据长度,
* 通过该指针返回的数据值永远 >= 0
* @return {int} 返回值含义如下:
* @return {int} 返回值含义如下:(应用需要通过 body_finish 函数和
* disconnected 函数来判断数据体是否读完或连接是否关闭)
* > 0: 表示已经读到的数据,并且数据还未读完
* == 0: 如果返回值为此值,则可以调用 disconnected()函数来判断连接
* 是否已经关闭;调用 body_finish 函数来判断是否已经读完 HTTP 响应
* 体数据,如果已经读完且连接未关闭,则还可以继续保持长连接
* == 0: 有两种原因会返回 0,当数据读完时返回 0,可调用 body_finish
* 函数判断是否已经读完 HTTP 响应数据;当读到压缩数据的尾部时,
* 因压缩数据的8字节尾部数据是控制字段,所以不做为数据体返回,
* 此时也会返回 0;
* 还可以通过 disconnected() 函数判断连接是否已经被关闭
* 如果数据读完且连接半未关闭,则可以继续保持长连接
* < 0: 表示连接关闭
* 注:read_body 的两个函数不能混用;
* 当为解压缩数据时,则返回的值为解压缩后的数据长度
Expand All @@ -312,7 +316,7 @@ class ACL_CPP_API http_client
* 关闭,当返回 true 时表示读到了一行数据,此时可以通过判断
* body_finish() 返回值来判断是否已经读完了数据体
* @param out {string&} 存储数据体的缓冲区,在该函数内部不会自动清理该
* 缓冲区,用户可在调用该函数前自行清理该缓冲区中的数据(可调用:out.clear())
* 缓冲区,用户可在调用该函数前自行清理该缓冲区(可调用:out.clear())
* @param nonl {bool} 读取一行数据时是否自动去掉尾部的 "\r\n" 或 "\n"
* @param size {size_t*} 当读到完整的一行数据时存放该行数据的长度,
* 当读到一个空行且 nonl 为 true 时,则该值为 0
Expand Down Expand Up @@ -386,9 +390,12 @@ class ACL_CPP_API http_client
bool is_request_; // 是否是客户请求端
int gzip_header_left_; // gzip 头剩余的长度
int last_ret_; // 数据读完后记录最后的返回值
bool head_sent_; // 头部数据是否已经发送完毕
bool body_finish_; // 是否已经读完 HTTP 响应体数据
bool disconnected_; // 网络连接是否已经关闭
bool chunked_transfer_; // 是否为 chunked 传输模式
unsigned gzip_crc32_; // gzip 压缩数据时的检验值
unsigned gzip_total_in_; // gzip 压缩前的总数据长度
string* buf_; // 内部缓冲区,用在按行读等操作中

bool read_request_head(void);
Expand All @@ -399,6 +406,11 @@ class ACL_CPP_API http_client
int read_response_body(string& out, bool clean, int* real_size);

HTTP_HDR* get_http_hdr() const;
bool write_chunk(ostream& out, const void* data, size_t len);
bool write_chunk_trailer(ostream& out);

bool write_gzip(ostream& out, const void* data, size_t len);
bool write_gzip_trailer(ostream& out);
};

} // namespace acl
36 changes: 31 additions & 5 deletions lib_acl_cpp/include/acl_cpp/http/http_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ class ACL_CPP_API http_header
*/
bool is_request(void) const;

//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// HTTP 请求方法函数
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

/**
* 创建 HTTP 请求头数据
Expand Down Expand Up @@ -313,9 +313,9 @@ class ACL_CPP_API http_header
*/
virtual void redicrect_reset(void) {}

//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// HTTP 响应方法函数
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

/**
* 创建 HTTP 响应头数据
Expand Down Expand Up @@ -354,9 +354,34 @@ class ACL_CPP_API http_header
*/
http_header& set_cgi_mode(bool on);

/**
* 是否设置了 CGI 模式
* @return {bool}
*/
bool is_cgi_mode() const
{
return cgi_mode_;
}

/**
* 设置传输的数据是否采用 gzip 方式进行压缩
* @param on {bool}
* @return {http_header&}
*/
http_header& set_transfer_gzip(bool on);

/**
* 获得当前的数据传输是否设置了采用 gzip 压缩方式
* @return {bool}
*/
bool is_transfer_gzip() const
{
return transfer_gzip_;
}

private:
//char* domain_; // HTTP 服务器域名
//unsigned short port_; // HTTP 服务器端口
//unsigned short port_; // HTTP 服务器端口
char* url_; // HTTP 请求的 URL
std::list<HTTP_PARAM*> params_; // 请求参数集合
std::list<HttpCookie*> cookies_; // cookies 集合
Expand All @@ -382,6 +407,7 @@ class ACL_CPP_API http_header
long long int content_length_; // HTTP 数据体长度
#endif
bool chunked_transfer_; // 是否为 chunked 传输模式
bool transfer_gzip_; // 数据是否采用 gzip 压缩
void init(void); // 初始化
void clear(void);
void build_common(string& buf) const; // 构建通用头
Expand Down
Loading

0 comments on commit d1fe096

Please sign in to comment.