#ifndef __LIB_HTTP_INCLUDE_H__ #define __LIB_HTTP_INCLUDE_H__ #include "lib_http_status.h" #include "lib_http_struct.h" #ifdef __cplusplus extern "C" { #endif /*---------------------------- 通用 HTTP 头操作函数 --------------------------*/ /* in http_hdr.c */ /** * 生成一个通用HTTP协议头的结构对象 * @param size {size_t} 所需分配内存大小, 等于 HTTP_HDR_REQ 或 HTTP_HDR_RES 的尺寸 * @return {HTTP_HDR*} !NULL: 返回一个HTTP_HDR结构指针; NULL: 出错. */ HTTP_API HTTP_HDR *http_hdr_new(size_t size); /** * 从源HTTP通用头拷贝内部成员变量至一个新的HTTP通用头结构中 * @param src {const HTTP_HDR*} 源HTTP通用头对象,不能为空 * @param dst {HTTP_HDR*} 目的HTTP通用头对象,不能为空 */ HTTP_API void http_hdr_clone(const HTTP_HDR *src, HTTP_HDR *dst); /** * 释放一个HTTP_HDR结构内存 * @param hh {HTTP_HDR*} 类型的数据指针,不能为空 */ HTTP_API void http_hdr_free(HTTP_HDR *hh); /** * 重置一个HTTP通用头的状态,释放内部成员变量,主要用于keep-alive的长连接多次请求 * @param hh {HTTP_HDR*} HTTP通用头类型的数据指针,不能为空 */ HTTP_API void http_hdr_reset(HTTP_HDR *hh); /** * 向 HTTP_HDR 头中增加一个条目 * @param hh {HTTP_HDR*} 通用头类型的数据指针,不能为空 * @param entry {HTTP_HDR_ENTRY*} HTTP头条目结构指针, 不能为空 */ HTTP_API void http_hdr_append_entry(HTTP_HDR *hh, HTTP_HDR_ENTRY *entry); /** * 分析所给数据, 解析出协议, 主/次版本号,并将结果存在通用HTTP头结构内 * @param hh {HTTP_HDR*} 类型的数据指针,不能为空 * @param data {const char*} 数据格式须为: HTTP/1.0 * @return {int} 0: OK; < 0: error. */ HTTP_API int http_hdr_parse_version(HTTP_HDR *hh, const char *data); /** * 分析所有的通用HTTP协议头并存储在 hh 结构中 * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @return {int} 0: ok; < 0: error */ HTTP_API int http_hdr_parse(HTTP_HDR *hh); /** * 由传入的 name, value 对产生一个 HTTP_HDR_ENTRY 对象 * @param name {const char*} 变量名 * @param value {const char*} 变量值 * @return {HTTP_HDR_ENTRY*} 如果为空则是因为输入参数有误 */ HTTP_API HTTP_HDR_ENTRY *http_hdr_entry_build(const char *name, const char *value); /** * 根据传入的一行数据进行分析, 生成一个 HTTP_HDR_ENTRY * @param data {const char*} HTTP 协议头中的一行数据, 如: Content-Length: 200 * @return {HTTP_HDR_ENTRY*} !NULL: ok; NULL: err. */ HTTP_API HTTP_HDR_ENTRY *http_hdr_entry_new(const char *data); HTTP_API HTTP_HDR_ENTRY *http_hdr_entry_head(char *data); HTTP_API HTTP_HDR_ENTRY *http_hdr_entry_new2(char *data); /** * 获取一个 HTTP_HDR_ENTRY 条目 * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param name {const char*} 该 HTTP_HDR_ENTRY 条目的标识名, 不能为空. 如: Content-Length. * @return ret {HTTP_HDR_ENTRY *} ret != NULL: ok; ret == NULL: 出错或不存在. */ HTTP_API HTTP_HDR_ENTRY *http_hdr_entry(const HTTP_HDR *hh, const char *name); /** * 获取HTTP协议头里某个实体头的变量值,如某个实体头为:Host: www.test.com * 要获得 Host 变量的值,调用该函数后便可以取得 www.test.com * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param name {const char*} 该 HTTP_HDR_ENTRY 条目的标识名, 不能为空. 如: Content-Length * @return ret {char*} ret != NULL: ok; ret == NULL: 出错或不存在. */ HTTP_API char *http_hdr_entry_value(const HTTP_HDR *hh, const char *name); /** * 将 HTTP 头中的某个字段进行替换, 该功能起初主要是为了实现 keep-alive 字段的替换 * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param name {const char*} 该 HTTP_HDR_ENTRY 条目的标识名, 不能为空. 如: Content-Length * @param value {const char*} 该 name 字段所对应的新的值 * @param force {int} 如果所替换的字段在原始HTTP请求里不存在, 则强行产生新的 entry 字段并 * 填至该请求头, 当该值为非0值时进行强行添加, 否则若该name在请求里不存在则不添加. * @return {int} 0 表示替换成功; < 0 表示输入参数出错或该 name 字段在该HTTP请求头里不存在 */ HTTP_API int http_hdr_entry_replace(HTTP_HDR *hh, const char *name, const char *value, int force); /** * 将 HTTP 头中的某个字段中包含某个字符串的源字符串进行替换, 可以支持多次匹配替换 * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param name {const char*} 该 HTTP_HDR_ENTRY 条目的标识名, 不能为空. 如: Cookie * @param from {const char*} 替换时的源字符串 * @param to {const char*} 替换时的目标字符串 * @param ignore_case {int} 在查找替换时是否忽略源字符串的大小写 * @return {int} 0: 表示未做任何替换, > 0: 表示替换的次数 */ HTTP_API int http_hdr_entry_replace2(HTTP_HDR *hh, const char *name, const char *from, const char *to, int ignore_case); /** * 禁止HTTP协议头中的某项 * @param hh {HTTP_HDR* } 通用HTTP头类型的数据指针,不能为空 * @param name {const char*} 该 HTTP_HDR_ENTRY 条目的标识名, 不能为空. 如: Content-Length */ HTTP_API void http_hdr_entry_off(HTTP_HDR *hh, const char *name); /** * 调试输出HTTP协议头部数据,调试类接口 * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param msg {const char*} 用户希望与头部信息一起输出的自定义信息, 可以为空 */ HTTP_API void http_hdr_print(const HTTP_HDR *hh, const char *msg); /** * 调试输出HTTP协议头部数据,调试类接口 * @param fp {ACL_VSTREAM*} 某个流指针,输出结果将会定向至该数据流(可以为网络流或文件流) * @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针,不能为空 * @param msg {const char*} 用户希望与头部信息一起输出的自定义信息, 可以为空 */ HTTP_API void http_hdr_fprint(ACL_VSTREAM *fp, const HTTP_HDR *hh, const char *msg); /*-------------------------------- HTTP 请求头操作函数 -----------------------*/ /* in http_hdr_req.c */ /** * 分配一个请求的HTTP协议头对象 * @return {HTTP_HDR_REQ*} HTTP请求头对象 */ HTTP_API HTTP_HDR_REQ *http_hdr_req_new(void); /** * 根据请求的URL,请求的方法,HTTP版本创建一个HTTP请求头对象 * @param url {const char*} 请求的URL,必须是完整的URL,如: * http://www.test.com/path/proc?name=value * http://www.test.com/path/proc * http://www.test.com/ * @param method {const char*} HTTP请求方法,必须为如下之一: * GET, POST, CONNECT, HEAD, 且要注意必须都为大写 * @param version {const char *} HTTP版本,必须为如下之一: * HTTP/1.0, HTTP/1.1 * @return {HTTP_HDR_REQ*} HTTP请求头对象 */ HTTP_API HTTP_HDR_REQ *http_hdr_req_create(const char *url, const char *method, const char *version); /** * 克隆一个HTTP请求头对象,但不复制其中的 chat_ctx, chat_free_ctx_fn * 两个成员变量 * @param hdr_req {const HTTP_HDR_REQ*} HTTP请求头对象 * @return {HTTP_HDR_REQ*} 克隆的HTTP请求头对象 */ HTTP_API HTTP_HDR_REQ *http_hdr_req_clone(const HTTP_HDR_REQ* hdr_req); /** * 根据上次HTTP请求头内容及重定向的URL产生一个新的HTTP请求头 * @param hh {const HTTP_HDR_REQ*} 上次的HTTP请求头对象 * @param url {const char *} 重定向的URL,如果有 http[s]:// 前缀,则认为 * 是完整的URL,新的 Host 字段将由该URL中提取,否则则继承源HTTP请求头中 * 的 Host 字段 * @return {HTTP_HDR_REQ*} 新产生的重定向的HTTP请求头 */ HTTP_API HTTP_HDR_REQ *http_hdr_req_rewrite(const HTTP_HDR_REQ *hh, const char *url); /** * 根据HTTP请求头内容及重定向的URL重新设置该HTTP请求头的信息 * @param hh {const HTTP_HDR_REQ*} 上次的HTTP请求头对象 * @param url {const char *} 重定向的URL,如果有 http[s]:// 前缀,则认为 * 是完整的URL,新的 Host 字段将由该URL中提取,否则则继承源HTTP请求头中 * 的 Host 字段 * @return {int} 0: ok; < 0: error */ HTTP_API int http_hdr_req_rewrite2(HTTP_HDR_REQ *hh, const char *url); /** * 释放HTTP请求头对象 * @param hh {HTTP_HDR_REQ*} HTTP请求头对象 */ HTTP_API void http_hdr_req_free(HTTP_HDR_REQ *hh); /** * 将HTTP请求头对象的成员变量释放并重新初始化 * @param hh {HTTP_HDR_REQ*} HTTP请求头对象 */ HTTP_API void http_hdr_req_reset(HTTP_HDR_REQ *hh); /** * 分析HTTP协议头的cookies * @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空 * @return {int} 0: ok; -1: err. */ HTTP_API int http_hdr_req_cookies_parse(HTTP_HDR_REQ *hh); /** * 分析HTTP请求首行数据(如: GET /cgi-bin/test.cgi?name=value&name2=value2 HTTP/1.0) * 请求的方法(GET)-->hdr_request_method * URL数据分析结果(name=value)-->hdr_request_table * HTTP协议版本号(HTTP/1.0)-->hdr_request_proto * URL数据中的路径部分(/cgi-bin/test.cgi)-->hdr_request_url * @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空 * @return {int} 0: ok; -1: err. */ HTTP_API int http_hdr_req_line_parse(HTTP_HDR_REQ *hh); /** * 分析HTTP请求头协议数据, 其内部会调用 http_hdr_req_line_parse, http_hdr_req_cookies_parse * @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空 * @return {int} 0: ok; -1: err. */ HTTP_API int http_hdr_req_parse(HTTP_HDR_REQ *hh); /** * 分析HTTP请求头协议数据, 其内部会调用 http_hdr_req_line_parse, http_hdr_req_cookies_parse * 如果 parse_params 非 0 则分析HTTP请求 url 中的参数部分; 如果 parse_cookie 非 0 则分析 * HTTP请求中的 cookie 内容 * @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空 * @param parse_params {int} 是否分析请求 url 中的参数部分 * @param parse_cookie {int} 是否分析请求中的 cookie 内容 * @return {int} 0: ok; -1: err. */ HTTP_API int http_hdr_req_parse3(HTTP_HDR_REQ *hh, int parse_params, int parse_cookie); /** * 从HTTP请求头中获得某个cookie值 * @param hh {HTTP_HDR_REQ*) HTTP请求头类型的数据指针,不能为空 * @param name {const char*} 某个cookie的变量名, 不能为空 * @return {const char*} !NULL: 该返回值即为所要求的cookie; NULL: 出错或所要求的cookie不存在 */ 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请求头类型的数据指针,不能为空 * @return {const char*} 返回请示方法. NULL: error; !NULL: OK. */ HTTP_API const char *http_hdr_req_method(HTTP_HDR_REQ *hh); /** * 从HTTP请求头中获取请求URL中某个请求字段的数据, * 如取: /cgi-bin/test.cgi?n1=v1&n2=v2 中的 n2的值v2 * @param hh {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请求头中获取请求行中的访问路径部分, 不包含主机名但包含参数. * 如原请求行数据为: * GET /cgi-bin/test.cgi?n1=v1&n2=v2 HTTP/1.1 * or * 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请求头类型的数据指针,不能为空 * @return {const char*} 请示的URL. !NULL: OK; NULL: error. */ HTTP_API const char *http_hdr_req_url_part(HTTP_HDR_REQ *hh); /** * 从HTTP请求头中获取请求行中的访问路径部分, 不包含主机名及参数. * 如原请求行数据为: * GET /cgi-bin/test.cgi?n1=v1&n2=v2 HTTP/1.1 * or * 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请求头类型的数据指针,不能为空 * @return {const char*} 请示的URL. !NULL: OK; NULL: error. */ HTTP_API const char *http_hdr_req_url_path(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请求头类型的数据指针,不能为空 * @return {const char*} 返回用户请示的主机名. !NULL: ok; NULL: error. */ HTTP_API const char *http_hdr_req_host(HTTP_HDR_REQ *hh); /** * 从HTTP请求头协议中获得完整的URL请求字符串 * 如原HTTP请求头为: * GET /cgi-bin/test.cgi?n1=v1&n2=v2 HTTP/1.1 * HOST: www.test.com * 则经该函数后则返回: * http://www.test.com/cgi-bin/test.cgi?n1=v1&n2=v2 * @param hh {HTTP_HDR_REQ*} HTTP请求头类型的数据指针,不能为空 * @return {const char*} 请示的URL. !NULL: OK; NULL: error. * @example: * void test(HTTP_HDR_REQ *hh) * { * const char *url = http_hdr_req_url(hh); * printf(">>> url: %s\r\n", url ? url : "null"); * } * 注意, 因为 http_hdr_req_url 内部使用到了一个线程局部静态变量内存区, 所以 * 不可如下使用,否则会使返回的数据发生重叠. * void test(HTTP_HDR_REQ *hh1, HTTP_HDR_REQ *hh2) * { * const char *url1 = http_hdr_req_url(hh1); * const char *url2 = http_hdr_req_url(hh2); * printf(">>> url1: %s, url2: %s\n", url1, url2); * } * 因为 url1, url2 实际上都是指向的同一内存区, 所以最终的结果将是 url1, url2 * 内容相同. 如遇此类情形, 应该如下操作: * void test(HTTP_HDR_REQ *hh1, HTTP_HDR_REQ *hh2) * { * const char *ptr; * static char dummy[1]; * char *url1 = dummy, *url2 = dummy; * ptr = http_hdr_req_url(hh1); * if (ptr) * url1 = acl_mystrdup(ptr); * ptr = http_hdr_req_url(hh2); * if (ptr) * url2 = acl_mystrdup(ptr); * printf(">>> url1: %s, url2: %s\n", url1, url2); * if (url1 != dummy) * acl_myfree(url1); * if (url2 != dummy) * acl_myfree(url2); * } */ HTTP_API const char *http_hdr_req_url(HTTP_HDR_REQ *hh); /** * 分析HTTP请求头中的 Range 字段 * @param hdr_req {HTTP_HDR_REQ*} 请求HTTP协议头, 不能为空 * @param range_from {http_off_t*} 存储偏移起始位置 * @param range_to {http_off_t*} 存储偏移结束位置 * 注: * {range_from}, {range_to} 下标从0开始 * 请求的 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 响应头操作函数 ---------------------------*/ /* in http_hdr_res.c */ /** * 分析HTTP响应头中的状态行 *@param hh {HTTP_HDR_RES*} HTTP响应头类型的数据指针,不能为空 *@param dbuf {const char*} 状态行数据, 如: HTTP/1.0 200 OK,不能为空 *@return {int} 0: ok; < 0: error,分析结果存储在 hh 结构中 */ HTTP_API int http_hdr_res_status_parse(HTTP_HDR_RES *hh, const char *dbuf); /** * 创建一个新的HTTP响应头 * @return {HTTP_HDR_RES*} */ HTTP_API HTTP_HDR_RES *http_hdr_res_new(void); /** * 克隆一个HTTP响应头 * @param hdr_res {const HTTP_HDR_RES*} 源HTTP响应头 * @return {HTTP_HDR_RES *} 新产生的HTTP响应头 */ HTTP_API HTTP_HDR_RES *http_hdr_res_clone(const HTTP_HDR_RES *hdr_res); /** * 释放一个HTTP响应头 * @param hh {HTTP_HDR_RES*} HTTP响应头 */ HTTP_API void http_hdr_res_free(HTTP_HDR_RES *hh); /** * 向HTTP响应头重新初始化并释放其中的成员变量 * @param hh {HTTP_HDR_RES*} HTTP响应头 */ HTTP_API void http_hdr_res_reset(HTTP_HDR_RES *hh); /** * 分析HTTP响应头里的数据,并存储分析结果 * @param hdr_res {HTTP_HDR_RES*} HTTP响应头 */ HTTP_API int http_hdr_res_parse(HTTP_HDR_RES *hdr_res); /** * 分析HTTP响应头中的 Range 字段 * @param hdr_res {HTTP_HDR_RES*} 响应HTTP协议头, 不能为空 * @param range_from {http_off_t*} 存储偏移起始位置, 不能为空 * @param range_to {http_off_t*} 存储偏移结束位置, 不能为空 * @param total_length {http_off_t*} 整个数据文件的总长度, 可为空 * 注: * {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); /* in http_rfc1123.c */ /** * 将时间值转换成RFC1123所要求的格式 * @param buf {char*} 存储空间 * @param size {size_t} buf 的空间大小 * @param t {time_t} 时间值 */ HTTP_API const char *http_mkrfc1123(char *buf, size_t size, time_t t); /*----------------------- HTTP 异步读操作函数 --------------------------------*/ /* in http_chat_async.c */ /** * 异步获取一个HTTP REQUEST协议头,数据结果存储在hdr中, 当取得一个完整的HTTP头或 * 出错时调用用户的注册函数 notify * @param hdr {HTTP_HDR_REQ*} HTTP请求头类型结构指针,不能为空 * @param astream {ACL_ASTREAM*} 与客户端连接的数据流, 不能为空 * @param notify {HTTP_HDR_NOTIFY} 当HTTP协议头读完或出错时调用的用户的注册函数 * @param arg {void*} notify 调用时的一个参数 * @param timeout {int} 接收数据过程中的读超时时间 */ HTTP_API void http_hdr_req_get_async(HTTP_HDR_REQ *hdr, ACL_ASTREAM *astream, HTTP_HDR_NOTIFY notify, void *arg, int timeout); /** * 异步获取一个HTTP RESPOND协议头,数据结果存储在hdr中, 当取得一个完整的HTTP头或 * 出错时调用用户的注册函数 notify * @param hdr {HTTP_HDR_REQ*} HTTP响应头类型结构指针,不能为空 * @param astream {ACL_ASTREAM*} 与服务端连接的数据流, 不能为空 * @param notify {HTTP_HDR_NOTIFY} 当HTTP协议头读完或出错时调用的用户的注册函数 * @param arg {void*} notify 调用时的一个参数 * @param timeout {int} 接收数据过程中的读超时时间 */ HTTP_API void http_hdr_res_get_async(HTTP_HDR_RES *hdr, ACL_ASTREAM *astream, HTTP_HDR_NOTIFY notify, void *arg, int timeout); /** * 异步从客户端读取请求的BODY协议体, 在接收过程中边接收连回调用户的 notify * 回调函数, 如果 notify 返回小于 0 的值, 则认为出错且不再继续接收数据 * @param request {HTTP_REQ*} HTTP请求体类型指针, 不能为空, 且 request->hdr 为空 * @param astream {ACL_ASTREAM*} 与客户端连接的数据流, 不能为空 * @param notify {HTTP_BODY_NOTIFY} 接收客户端数据过程中回调的用户的注册函数 * @param arg {void*} notify 调用时的一个参数 * @param timeout {int} 接收数据过程中的读超时时间 */ HTTP_API void http_req_body_get_async(HTTP_REQ *request, ACL_ASTREAM *astream, HTTP_BODY_NOTIFY notify, void *arg, int timeout); /* * 异步从服务器端读取响应数据的BODY协议体, 在接收过程中连接收连回调用户的 * notify 回调函数, 如果 notify 返回小于 0 的值, 则认为出错且不再继续接收数据 * @param respond {HTTP_RES*} HTTP响应体类型指针, 不能为空,且 respond->hdr 不为空 * @param astream {ACL_ASTREAM*} 与服务端连接的数据流, 不能为空 * @param notify {HTTP_BODY_NOTIFY} 接收服务端数据过程中回调的用户的注册函数 * @param arg {void*} notify 调用时的一个参数 * @param timeout {int} 接收数据过程中的读超时时间 */ HTTP_API void http_res_body_get_async(HTTP_RES *respond, ACL_ASTREAM *astream, HTTP_BODY_NOTIFY notify, void *arg, int timeout); /*----------------------- HTTP 同步读操作函数 --------------------------------*/ /* in http_chat_sync.c */ /** * 同步获取一个HTTP REQUEST协议头,数据结果存储在hdr中, 当取得一个完整的HTTP头或 * 出错时调用用户的注册函数 notify * @param hdr {HTTP_HDR_REQ*} HTTP请求头类型结构指针,不能为空 * @param stream {ACL_VSTREAM*} 与客户端连接的数据流, 不能为空 * @param timeout {int} 接收数据过程中的读超时时间 * @return {int} 0: 成功; < 0: 失败 */ HTTP_API int http_hdr_req_get_sync(HTTP_HDR_REQ *hdr, ACL_VSTREAM *stream, int timeout); /** * 同步获取一个HTTP RESPOND协议头,数据结果存储在hdr中, 当取得一个完整的HTTP头或 * 出错时调用用户的注册函数 notify * @param hdr {HTTP_HDR_REQ*} HTTP响应头类型结构指针,不能为空 * @param stream {ACL_VSTREAM*} 与服务端连接的数据流, 不能为空 * @param timeout {int} 接收数据过程中的读超时时间 * @return {int} 0: 成功; < 0: 失败 */ HTTP_API int http_hdr_res_get_sync(HTTP_HDR_RES *hdr, ACL_VSTREAM *stream, int timeout); /** * 同步从客户端读取请求的BODY协议体 * @param request {HTTP_REQ*} HTTP请求体类型指针, 不能为空, 且 request->hdr 为空 * @param stream {ACL_VSTREAM*} 与客户端连接的数据流, 不能为空 * @param buf {void *} 存储结果的内容空间 * @param size {int} buf 的空间大小 * @return ret {http_off_t} 本次读到的HTTP请求体的内容 * 0: 表示读完了HTTP数据体内容,但并不代表数据流已经关闭; * < 0: 表示读出错,流关闭或出错; * > 0: 表示未读完,目前读到ret 个字节的数据 */ HTTP_API http_off_t http_req_body_get_sync(HTTP_REQ *request, ACL_VSTREAM *stream, void *buf, int size); #define http_req_body_get_sync2 http_req_body_get_sync /** * 同步从服务端读取响应的BODY协议体 * @param respond {HTTP_RES*} HTTP响应体类型指针, 不能为空, 且 respond->hdr 为空 * @param stream {ACL_VSTREAM*} 与客户端连接的数据流, 不能为空 * @param buf {void *} 存储结果的内容空间 * @param size {int} buf 的空间大小 * @return ret {http_off_t} 本次读到的HTTP响应体的内容 * 0: 表示读完了HTTP数据体内容,但并不代表数据流已经关闭; * < 0: 表示读出错,流关闭或出错; * > 0: 表示未读完,目前读到ret 个字节的数据 */ HTTP_API http_off_t http_res_body_get_sync(HTTP_RES *respond, ACL_VSTREAM *stream, void *buf, int size); #define http_res_body_get_sync2 http_res_body_get_sync /** * 设置请求协议的控制标志位 * @param request {HTTP_REQ*} HTTP请求体类型指针, 不能为空, 且 request->hdr 为空 * @param name {int} 第一个标志位,当最后一个标志位为 HTTP_CHAT_SYNC_CTL_END 时 * 表示结束 */ HTTP_API void http_chat_sync_reqctl(HTTP_REQ *request, int name, ...); /** * 设置响应协议的控制标志位 * @param respond {HTTP_RES*} HTTP响应体类型指针, 不能为空, 且 respond->hdr 为空 * @param name {int} 第一个标志位,当最后一个标志位为 HTTP_CHAT_SYNC_CTL_END 时 * 表示结束 */ HTTP_API void http_chat_sync_resctl(HTTP_RES *respond, int name, ...); #define HTTP_CHAT_SYNC_CTL_END 0 /**< 结束标志位 */ #define HTTP_CHAT_CTL_BUFF_ONOFF 1 /**< 是否打开数据接收时的预缓冲策略 */ /*------------------------ HTTP 请求体构造及释放函数 ------------------------*/ /* in http_req.c */ /** * 根据HTTP请求头分配一个请求体对象 * @param hdr_req {HTTP_HDR_REQ*} 请求头对象 * @return {HTTP_REQ*} 请求体对象 */ HTTP_API HTTP_REQ *http_req_new(HTTP_HDR_REQ *hdr_req); /** * 释放请求体对象 * @param request {HTTP_REQ*} 请求体对象 */ HTTP_API void http_req_free(HTTP_REQ *request); /*------------------------ HTTP 响应体构造及释放函数 ------------------------*/ /* in http_res.c */ /** * 根据HTTP响应头分配一个响应体对象 * @param hdr_res {HTTP_HDR_RES*} 响应头对象 * @return {HTTP_RES*} 响应体对象 */ HTTP_API HTTP_RES *http_res_new(HTTP_HDR_RES *hdr_res); /** * 释放响应体对象 * @param respond {HTTP_RES*} 响应体对象 */ HTTP_API void http_res_free(HTTP_RES *respond); /*------------------------------ HTTP 头构造函数 -----------------------------*/ /* in http_hdr_build.c */ /** * 向通用HTTP头中添加数据 * @param hdr {HTTP_HDR*} 通用HTTP头对象 * @param name {const char*} 变量名,如 Accept-Encoding: deflate, gzip 中的 Accept-Encoding * @param value {const char*} 变量值,如 Accept-Encoding: deflate, gzip 中的 deflate, gzip */ HTTP_API void http_hdr_put_str(HTTP_HDR *hdr, const char *name, const char *value); /** * 向通用HTTP头中添加数据 * @param hdr {HTTP_HDR*} 通用HTTP头对象 * @param name {const char*} 变量名,如 Content-Length: 1024 中的 Conteng-Length * @param value {const int} 变量值,如 Content-Length: 1024 中的 1024 */ HTTP_API void http_hdr_put_int(HTTP_HDR *hdr, const char *name, int value); /** * 向通用HTTP头中添加数据 * @param hdr {HTTP_HDR*} 通用HTTP头对象 * @param name {const char*} 变量名,如 Accept-Encoding: deflate, gzip 中的 Accept-Encoding * @param fmt {const char*} 变参格式字符串 */ #ifdef WIN32 HTTP_API void http_hdr_put_fmt(HTTP_HDR *hdr, const char *name, const char *fmt, ...); #else HTTP_API void __attribute__((format(printf,3,4))) http_hdr_put_fmt(HTTP_HDR *hdr, const char *name, const char *fmt, ...); #endif /** * 向通用HTTP头中添加时间数据 * @param hdr {HTTP_HDR*} 通用HTTP头对象 * @param name {const char*} 变量名 * @param t {time_t} 时间值 */ HTTP_API void http_hdr_put_time(HTTP_HDR *hdr, const char *name, time_t t); /** * 根据HTTP请求头的字段来设置是否与服务端保持长连接, 结果存储于HTTP响应头中 * @param req {const HTTP_HDR_REQ*} HTTP请求头 * @param res {HTTP_HDR_RES*} HTTP响应头,存储分析结果 */ HTTP_API int http_hdr_set_keepalive(const HTTP_HDR_REQ *req, HTTP_HDR_RES *res); /** * 用返回状态(1xx, 2xx, 3xx, 4xx, 5xx) 初始化一个HTTP响应头 * @param hdr_res {HTTP_HDR_RES*} HTTP响应头,存储分析结果 * @param status {int} 状态号,nxx(1xx, 2xx, 3xx, 4xx, 5xx) */ HTTP_API void http_hdr_res_init(HTTP_HDR_RES *hdr_res, int status); /** * 用返回状态(nxx)生成一个HTTP响应头 * @param status {int} 状态号,nxx(1xx, 2xx, 3xx, 4xx, 5xx) * @return {HTTP_HDR_RES*} 生成的HTTP响应头 */ HTTP_API HTTP_HDR_RES *http_hdr_res_static(int status); /** * 用返回状态(nxx)生成一个HTTP响应头 * @param status {int} 状态号,nxx(4xx, 5xx) * @return {HTTP_HDR_RES*} 生成的HTTP响应头 */ HTTP_API HTTP_HDR_RES *http_hdr_res_error(int status); /** * 根据HTTP通用头生成头的完整内容于BUF中 * @param hdr {const HTTP_HDR*} 通用HTTP头 * @param strbuf {ACL_VSTRING*} 存储结果的缓冲区 */ HTTP_API void http_hdr_build(const HTTP_HDR *hdr, ACL_VSTRING *strbuf); /** * 根据HTTP请求头生成请求头内容于BUF中 * @param hdr_req {const HTTP_HDR_REQ*} HTTP请求头 * @param strbuf {ACL_VSTRING*} 存储结果的缓冲区 */ HTTP_API void http_hdr_build_request(const HTTP_HDR_REQ *hdr_req, ACL_VSTRING *strbuf); /*----------------------------- HTTP 响应状态信息函数 ------------------------*/ /* in http_status.c */ /** * 根据HTTP响应号(nxx)返回该值所代表的字符串 * @param status {int} 状态号,nxx(1xx, 2xx, 3xx, 4xx, 5xx) * @return {const char*} 响应号所对应的字符串表示 */ HTTP_API const char *http_status_line(int status); /*---------------------------- HTTP HTML 模板操作函数 ------------------------*/ /* in http_tmpl.c */ /** * 装载HTTP响应代码的HTML模板 * @param tmpl_path {const char*} HTML模板文件所在的路径 */ HTTP_API void http_tmpl_load(const char *tmpl_path); /** * 读取对应HTTP响应状态码的模板信息 * @param status {int} HTTP 状态响应码 * @return {const ACL_VSTRING*} 对应HTTP响应状态码的模板信息 */ HTTP_API const ACL_VSTRING *http_tmpl_get(int status); /** * 读取对应HTTP响应状态码的标题提示信息 * @param status {int} HTTP 状态响应码 * @return {const char*} 对应HTTP响应状态码的标题提示信息 */ HTTP_API const char *http_tmpl_title(int status); /** * 获得相应HTTP响应状态码的模板提示信息的长度大小 * @param status {int} HTTP 状态响应码 * @return {int} 模板提示信息的长度大小 */ HTTP_API int http_tmpl_size(int status); /*---------------------------- HTTP HTML 模板初始化函数 ----------------------*/ /* in http_init.c */ /** * 初始化HTTP应用协议 * @param tmpl_path {const char*} 模板信息文件的存放路径 */ HTTP_API void http_init(const char *tmpl_path); /** * 是否自动缓冲被释放的 HTTP 头对象,从而使其内存可以重复使用, 该函数在程序初始化 * 时只能被调用一次 * @param max {int} 当该值 > 0 时便自动启用 HTTP 头对象缓冲功能 */ HTTP_API void http_hdr_cache(int max); /** * 设置在进行 HTTP 协议体数据传输时的缓冲区大小 * @param size {http_off_t} 缓冲区大小 */ HTTP_API void http_buf_size_set(http_off_t size); /** * 获得进行 HTTP 协议体数据传输时的缓冲区大小 * @return {http_off_t} 缓冲区大小 */ HTTP_API http_off_t http_buf_size_get(void); #ifdef __cplusplus } #endif #endif