模块契约HTTP Connection

内存与错误

  • 字段数组、字段值、游标和输出描述符支持未对齐存储;
  • 游标和输出不得覆盖字段描述符或任一借用视图;
  • Count 失败时输出为零,Next 失败时不推进游标并清空输出视图;
  • 所有解析、统计、查找和持久性判断都不分配内存;
  • 详细错误由线程错误槽提供。

协议依据:RFC 9110 Section 7.6.1 和 RFC 9112 Section 9.3。

裁剪与依赖

  • 模块:http_connection
  • 功能宏:XRT_FEATURE_HTTP_CONNECTION
  • 直接依赖:http

选项迭代

Connection 使用 RFC 9110 的 #connection-option 语法。空字段、仅含 OWS 的字段和仅含空 列表成员的字段都表示零个选项;非空成员必须是 HTTP token。

xrtHttpConnectionCursorInit 初始化通用的 xhttpfieldtokencursor, xrtHttpConnectionNext 按线路顺序遍历全部重复字段。第一次发布选项前会验证所有 Connection 字段。游标会绑定原字段数组、字段数量和字段名称,不能在迭代中切换输入; 输入存储在游标结束前必须保持有效且不变。

返回的 xstrview 借用原字段值。迭代不分配内存,返回值为:

  • XHTTP_NEXT_ITEM:发布一个选项;
  • XHTTP_NEXT_END:正常结束,同时清空输出视图;
  • XHTTP_NEXT_ERROR:参数、游标或字段语法错误。

xrtHttpConnectionCount 完整验证并统计选项。 xrtHttpConnectionFind 完整验证后执行大小写不敏感的单项查询。 底层通用能力分别是 xrtHttpFieldTokenCount、xrtHttpFieldTokenFind 和 xrtHttpFieldTokenNext。

持久连接

xrtHttpConnectionPersistence 实现 RFC 9112 的 HTTP/1 持久性判断:

  • close 始终返回 XHTTP_CONNECTION_CLOSE;
  • 没有 close 的 HTTP/1.1 默认返回 XHTTP_CONNECTION_PERSIST;
  • HTTP/1.0 默认关闭;
  • HTTP/1.0 只有设置 XHTTP_CONNECTION_ALLOW_HTTP10_KEEP_ALIVE、消息包含

keep-alive,且接收方不是代理或消息是响应时才持久;

  • 非法版本、未知标志或非法字段返回 XHTTP_CONNECTION_ERROR。

消息为响应时设置 XHTTP_CONNECTION_RESPONSE,接收方为代理时设置 XHTTP_CONNECTION_PROXY。允许 HTTP/1.0 Keep-Alive 是显式本地策略,库不会默认开启。

连接持久还要求消息具有自描述长度并被完整消费;该函数只判断版本和 Connection 字段, 不会替代 HTTP/1 消息分帧或传输状态检查。

分层复用

  • 规范写出选项数组使用 xrtHttpTokenListWrite 或 xrtHttpTokenListBuild;
  • 逐跳字段移除策略使用 xrtHttpHopField;
  • TE、Upgrade 等具体协议模块负责校验对应选项与字段是否配套;
  • 传输层负责半关闭、排空和最终关闭,不由本协议层操作套接字。

验证资产

  • tests/http/test_http_connection.c
  • tests/http/test_http_connection_noalloc.c
  • tests/single/test_single_http_connection.c
  • examples/http/connection/main.c

字段

xhttpfield 只有 Name 和 Value 两个借用视图。字段名称不带冒号,字段值不带 两端 OWS 或 CRLF。

xrtHttpFieldParse 解析一条不含 CRLF 的字段行;xrtHttpFieldNext 逐行扫描字段 块;xrtHttpFieldBlockCount 在不保存描述符时完成严格验证和计数。

xrtHttpFieldWrite 写一条字段,xrtHttpFieldBlockWrite 写字段数组和可选最终空行。 两者都支持空输出测量,容量不足时不会部分写出。

查询函数包括:

  • xrtHttpFieldNameEqual:ASCII 不区分大小写字段名比较;
  • xrtHttpFieldFind、Get、Count:查找重复字段;
  • xrtHttpFieldGetUnique:区分缺失、唯一和重复;
  • xrtHttpFieldValueValid:验证字段值字节边界。

字段描述符可以未对齐,但描述符数组、借用文本和写出区不能发生不明确重叠。

Content-Length

xrtHttpContentLengthParse 接受十进制值和 RFC 允许的重复相同列表值,拒绝空值、 符号、非数字、溢出和冲突值。

该函数只解析单个字段值。HTTP/1 parser 会合并全部重复 Content-Length 字段, 同时执行 Transfer-Encoding 冲突和请求分帧检查。

token 与列表

  • xrtHttpTokenValid 验证 RFC tchar;
  • xrtHttpTokenEqual 和 xrtHttpMethodEqual 执行 ASCII 不区分大小写比较;
  • xrtHttpTokenNext 迭代逗号 token-list;
  • xrtHttpFieldTokenNext 跨重复同名字段迭代;
  • xrtHttpFieldTokenCount、Find 处理重复字段集合;
  • xrtHttpQualityParse 解析 0 到 1 的 qvalue 为 0 到 1000 定点数;
  • xrtHttpWeightedTokenNext 迭代带权 token。

xrtHttpOwsTrim 只移除 SP 和 HTAB,不把其他空白字符当作 HTTP OWS。

方法与状态

xrtHttpStatusText 返回内置状态的标准 reason phrase。未知状态返回空视图,调用方 仍可用 uint16 写出扩展状态。

xrtHttpMethodSafe、xrtHttpMethodIdempotent 和 xrtHttpResponseContentAllowed 提供基础协议语义。它们不替代应用权限、重试和 缓存策略。

参数

启用 XRT_MODULE_HTTP_PARAM 后,xhttpparam 表达 name[=value]:

  • XHTTP_PARAM_HAS_VALUE:存在等号和值;
  • XHTTP_PARAM_QUOTED:值来自 quoted-string,视图不含外层双引号;
  • XHTTP_PARAM_NONE:只有名称。

xrtHttpParamNext 迭代分号参数,xrtHttpDirectiveNext 迭代逗号指令。对应的 Count 和 Find 函数使用同一套严格语法。

xrtHttpQuotedValid、Read、Write 处理 quoted-string 和 quoted-pair; xrtHttpParamValueCursorInit 与 xrtHttpParamValueNext 零分配逐字节读取语义值, 并通过 Offset 暴露已经消耗的原始值长度;xrtHttpParamValueWrite 一次性输出 参数语义值;xrtHttpParamWrite 写单个参数。

Build 便利函数返回由 xrtFree 释放的零结尾字符串。热路径应优先使用测量加 调用方缓冲的 Write 版本。

Host 与 request-target

启用 http_host 后,xrtHttpHostParse 返回借用的 xhttpauthority; xrtHttpHostValid 执行同样的严格验证。解析过程不分配内存,IPv6 与 IPvFuture 字面地址的 Host 视图不包含方括号,PortText 保留显式端口的原始文本。

xrtHttpAuthorityValid 验证解析或手工构造的 authority。手工构造数值端口时设置 XHTTP_AUTHORITY_HAS_PORT | XHTTP_AUTHORITY_PORT_VALUE 并填写 Port,不需要伪造 PortText。xrtHttpAuthorityPort 将可用的显式端口写入调用方变量;省略端口或显式 空端口时返回调用方提供的默认值,超出 uint16 的合法协议端口文本不能直接交给 网络层,因此返回失败。

xrtHttpTargetParse 区分 origin-form、absolute-form、authority-form 和 asterisk-form,并结合方法检查 CONNECT 与 OPTIONS 的专用约束。结果同样只借用输入, 核心层不构建 URL 对象,也不执行查询参数解码。

已迁出能力

动态 Header 容器、RFC 8187 扩展值、MIME、Structured Fields、Digest Fields、 Forwarded、Link、Priority、Cache-Status、Proxy-Status 和 Content-Disposition 不属于 XRT HTTP 核心;需要这些高级协议能力时,请使用独立发布的 xhttp 扩展。

xhttpconnectionstatus类型

连接持久性结果区分协议错误、当前响应后关闭和继续复用。

值语义
XHTTP_CONNECTION_ERROR失败
XHTTP_CONNECTION_CLOSE协商了 close
XHTTP_CONNECTION_PERSIST协商持久连接
typedef enum xhttpconnectionstatus { XHTTP_CONNECTION_ERROR = -1, XHTTP_CONNECTION_CLOSE = 0, XHTTP_CONNECTION_PERSIST = 1 } xhttpconnectionstatus;

xhttpconnectionflag类型

HTTP/1.0 持久性判断所需的消息方向、接收角色和本地策略。

值语义
XHTTP_CONNECTION_RESPONSE响应保留连接
XHTTP_CONNECTION_PROXY代理保留连接
XHTTP_CONNECTION_ALLOW_HTTP10_KEEP_ALIVE允许 HTTP/1.0 保活
typedef enum xhttpconnectionflag { XHTTP_CONNECTION_RESPONSE = UINT32_C(0x00000001), XHTTP_CONNECTION_PROXY = UINT32_C(0x00000002), XHTTP_CONNECTION_ALLOW_HTTP10_KEEP_ALIVE = UINT32_C(0x00000004)

xrtHttpConnectionCursorInit函数

初始化重复 Connection 字段选项游标(复用通用 xhttpfieldtokencursor)。

void xrtHttpConnectionCursorInit(xhttpfieldtokencursor* pCursor)

参数

参数方向约束说明
pCursor输出非空调用方存储
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无 — 初始化不失败

范例已编译验证

http/connection_cursor · 迭代 · 观察

	xrtHttpConnectionCursorInit(&Cursor);

xrtHttpConnectionNext函数

跨重复 Connection 字段行按线路顺序迭代连接选项;首次发布前完整验证所有字段,选项借用原字段值。

xhttpnext xrtHttpConnectionNext(const xhttpfield* pFields, size_t iCount, xhttpfieldtokencursor* pCursor, xstrview* pOption)

参数

参数方向约束说明
pFields输入借用数组字段数组
iCount输入—条目数
pCursor输入/输出已初始化游标(输入在结束前不变)
pOption输出非空接收选项(借用字段值)
返回值
返回含义失败时状态
XHTTP_NEXT_ITEM发布一个选项—
XHTTP_NEXT_END正常结束并清空输出不设错
XHTTP_NEXT_ERROR参数/游标/字段语法错误游标不变
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • xrt.http 域错误 — Connection 字段值语法非法

范例已编译验证

http/connection_cursor · 迭代 · 观察

	while ( xrtHttpConnectionNext(Fields, 2u, &Cursor, &Option) ==
		XHTTP_NEXT_ITEM ) {

xrtHttpConnectionCount函数

完整验证并统计全部重复 Connection 字段中的非空选项。

bool xrtHttpConnectionCount(const xhttpfield* pFields, size_t iCount, size_t* pOptionCount)

参数

参数方向约束说明
pFields输入借用数组字段数组
iCount输入—条目数
pOptionCount输出非空、可未对齐接收合计
返回值
返回含义失败时状态
true合计已写出—
false任一字段非法计数不变
错误
  • xrt.http 域错误 — Connection 字段值语法非法

范例已编译验证

http/connection · 统计 · 观察

	if ( !xrtHttpConnectionCount(
		Fields, 2u, &iCount
	) || (iCount != 2u) ||

xrtHttpConnectionFind函数

在全部重复 Connection 字段中查找大小写不敏感的连接选项;先验证所有值再返回。

xhttpnext xrtHttpConnectionFind(const xhttpfield* pFields, size_t iCount, xstrview Option)

参数

参数方向约束说明
pFields输入借用数组字段数组
iCount输入—条目数
Option输入借用查找选项
返回值
返回含义失败时状态
XHTTP_NEXT_ITEM找到—
XHTTP_NEXT_END未找到(不设错)—
XHTTP_NEXT_ERROR字段值非法xrt.http 域错误
错误
  • xrt.http 域错误 — Connection 字段值语法非法

范例已编译验证

http/connection · 查找 · 观察

	xrtHttpConnectionFind(
		Fields, 2u, XRT_STR_LITERAL("te")
	) != XHTTP_NEXT_ITEM ) {

xrtHttpConnectionPersistence函数

按 RFC 9112 判断 HTTP/1 连接能否在当前响应后继续复用。HTTP/1.0 只有显式允许、含 keep-alive 且满足代理方向限制才持久。

xhttpconnectionstatus xrtHttpConnectionPersistence(xhttpversion Version, const xhttpfield* pFields, size_t iCount, uint32 iFlags)

参数

参数方向约束说明
Version输入HTTP 版本1.0 或 1.1
pFields输入借用数组Connection 字段
iCount输入—条目数
iFlags输入XHTTP_CONNECTION_*RESPONSE/PROXY/ALLOW_HTTP10_KEEP_ALIVE
返回值
返回含义失败时状态
XHTTP_CONNECTION_PERSIST可复用(close 不存在且版本策略满足)—
XHTTP_CONNECTION_CLOSEclose 存在或版本默认关闭—
XHTTP_CONNECTION_ERROR非法版本/标志/字段XERR_ARGUMENT 或 xrt.http 域错误
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • xrt.http 域错误 — Connection 字段值语法非法
  • 注:只判断版本与字段,不替代分帧完整性检查

范例已编译验证

http/connection · 持久性 · 观察

	Status = xrtHttpConnectionPersistence(
		XHTTP_VERSION_1_1, Fields, 2u, 0
	);

常量索引常量

以下常量在本页所属头文件中定义,语义见公共头注释。

常量说明
XHTTP_CONNECTION_ALLOW_HTTP10_KEEP_ALIVE见头文件注释
XHTTP_CONNECTION_CLOSE见头文件注释
XHTTP_CONNECTION_ERROR见头文件注释
XHTTP_CONNECTION_PERSIST见头文件注释
XHTTP_CONNECTION_PROXY见头文件注释
XHTTP_CONNECTION_RESPONSE见头文件注释