acl/lib_protocol/include/http/lib_http.h

740 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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协议头部数据调试类接口
* @param bf {ACL_VSTRING*} 输出结果将会定向至该缓冲区
* @param hh {HTTP_HDR*} 通用HTTP头类型的数据指针不能为空
* @param msg {const char*} 用户希望与头部信息一起输出的自定义信息, 可以为空
*/
HTTP_API void http_hdr_sprint(ACL_VSTRING *bf, 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*} 变参格式字符串
*/
# if defined(WIN32) || defined(WIN64)
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