模块契约HTTP 协议底座
线程
解析、编码与字段表 API 为无共享状态的纯函数或单拥有者对象,可任意线程并发调用(不同对象间);同一对象(连接、字段表)由使用它的执行流独占。
模块边界
| 模块 | 裁剪宏 | 作用 |
|---|---|---|
http | XRT_MODULE_HTTP | token、字段、方法、状态和 Content-Length |
http_param | XRT_MODULE_HTTP_PARAM | 参数与 quoted-string 语法 |
http_param_host | XRT_MODULE_HTTP_PARAM_HOST | 参数解码后的无分配 Host 验证 |
http_expect | XRT_MODULE_HTTP_EXPECT | Expect 字段 |
http_upgrade | XRT_MODULE_HTTP_UPGRADE | Upgrade 字段与写出 |
http_te | XRT_MODULE_HTTP_TE | TE 与 transfer-coding 参数 |
http_connection | XRT_MODULE_HTTP_CONNECTION | Connection 选项与持久连接 |
http_trailer | XRT_MODULE_HTTP_TRAILER | Trailer 声明和尾字段约束 |
http_encoding | XRT_MODULE_HTTP_ENCODING | Accept-Encoding 与 Content-Encoding |
http_decode | XRT_MODULE_HTTP_DECODE | 流式 gzip/deflate 自动解码 |
http_host | XRT_MODULE_HTTP_HOST | Host authority |
http_target | XRT_MODULE_HTTP_TARGET | 四种 request-target |
http1_head | XRT_MODULE_HTTP1_HEAD | 起始行、Header 解析与写入 |
http1_net | XRT_MODULE_HTTP1_NET | TCP 块链 Header 解析与余量保留 |
http1_tls | XRT_MODULE_HTTP1_TLS | TLS 明文块链增量 Header 解析 |
http1_body | XRT_MODULE_HTTP1_BODY | 正文计划、chunked 和 trailer |
http1_message | XRT_MODULE_HTTP1_MESSAGE | 连续内存完整消息便利层 |
http_decode 才依赖 Inflate,http1_net 才依赖网络块链,http1_tls 才依赖 TLS Stream。 只启用连续内存 HTTP/1 解析不会带入压缩、网络、TLS 或 WebSocket。
借用模型
xhttpfield、xhttp1head、xhttp1message 和所有语法游标都借用调用方输入。 解析器不复制字段名称和值,输入缓冲和字段描述符数组必须覆盖借用视图的使用期。
请求方法同时以原始 xhttp1head.Method 视图和 xhttp1head.MethodCode 枚举发布。 xrtHttpMethodParse 按大小写敏感规则识别 GET、HEAD、POST、PUT、DELETE、CONNECT、 OPTIONS、TRACE 和 PATCH;合法但未内置的方法返回 XHTTP_METHOD_OTHER,非法 token 返回 XHTTP_METHOD_INVALID。每个非零枚举值占用独立 bit,既可以作为实际方法直接 比较,也可以通过位或组合成路由方法集合。XHTTP_METHOD_CRUD 覆盖 GET、POST、PUT、 PATCH 和 DELETE,XHTTP_METHOD_ANY 覆盖全部内置方法及 OTHER;应用仍应保留原始 视图处理具体的扩展方法。
字段描述符允许位于合法的未对齐存储。实现使用安全加载,不要求调用方为了协议 解析调整缓冲布局。
XRT 不再提供动态 Header 容器。需要拥有、修改或索引 Header 的框架应在 xhttp 中建立对象模型;快速路径可以直接使用栈数组或应用自己的存储。
Host 语法
xrtHttpHostParse 保留 Host、可选端口和 IP-literal 分类,任意长度十进制端口在 协议层仍然合法,只有可放入 uint16 的值才带 XHTTP_AUTHORITY_PORT_VALUE。 xrtHttpIpv4Valid 与 xrtHttpIpv6Valid 是无错误副作用的纯谓词,公开同一套严格 IP 文本规则,扩展协议无需复制 Host 内部解析器。
xrtHttpParamHostValid 直接消费 xhttpparam 的语义值。quoted-pair 会在验证时 流式解码,任意长度 reg-name 与 IPvFuture 不进入固定缓冲,也不申请堆内存。
Header 解析
xrtHttp1RequestParse 和 xrtHttp1ResponseParse 接受从消息首字节开始的累计输入:
XHTTP1_MORE:输入尚未包含完整 Header;XHTTP1_FIELDS:Header 完整,但字段描述符容量不足,FieldCount给出需求;XHTTP1_READY:解析完成;XHTTP1_ERROR:协议、限额或参数错误。
解析器只接受 CRLF,拒绝 obs-fold、裸 LF、非法字段名、控制字符、冲突的 Content-Length、歧义 Transfer-Encoding 和非法 Upgrade。xhttp1errorinfo 提供稳定错误码、消息相对偏移和行号。
xhttp1limits 分别限制 Header 总长度、起始行、单字段行和字段数量。默认值面向 公网输入,服务端应按路由策略进一步收紧,而不是无上限增长接收缓冲。
网络热路径使用 xrtHttp1RequestParseBuffer、xrtHttp1ResponseParseBuffer 直接扫描 xnetbuf。只有完整 Header 跨块时才连续化实际 Header 前缀,函数不消费输入,Upgrade 后的余量 保持原位。TLS 对应入口是 xrtHttp1RequestParseTls、xrtHttp1ResponseParseTls;输入不足时它们 通过 xrtTlsStreamReadMore 请求下一段受限明文,Header 完成后仍由调用方消费 Head.Bytes。
正文计划
Header 完成后必须调用:
xrtHttp1RequestBodyPlan处理请求;xrtHttp1ResponseBodyPlan处理响应,并传入原请求方法。
xhttp1bodyplan 的模式是唯一分帧结论:
XHTTP1_BODY_NONE:没有正文;XHTTP1_BODY_FIXED:Content-Length 定长;XHTTP1_BODY_CHUNKED:分块编码;XHTTP1_BODY_CLOSE:由可靠 EOF 定界;XHTTP1_BODY_TUNNEL:CONNECT 或 101 后的字节不再属于 HTTP。
响应计划覆盖 HEAD、成功 CONNECT、1xx、204 和 304。调用方不应仅凭 Content-Length 判断响应正文。
流式接收
xrtHttp1BodyInit 创建无分配 reader。xrtHttp1BodyRead 每次返回一个借用正文 片段、容量请求或终态,并通过 Consumed 精确说明已消费线路字节。
xrtHttp1BodyLimitsInit 的 MaxBody 默认为 UINT64_MAX,因为底层 reader 不拥有、 聚合或分配正文。服务端、代理以及任何会持有正文的上层必须在接收前按路由和内存预算 设置有限上限,不能把该协议层默认值直接作为公网接收策略。
对于 chunked,reader 会验证 chunk-size、扩展语法、CRLF、last-chunk 和 trailer, 并严格拒绝 chunk-size 与分号或 CRLF 之间的空白,避免端点对报文边界产生分歧。 正文视图不包含分块元数据。Received 是应用正文长度,WireBytes 是正文区实际 线路长度。
当返回 XHTTP1_BODY_FIELDS 时,TrailerCount 给出所需描述符数量。调用 xrtHttp1BodyTrailers 绑定足够存储后,用同一输入继续解析,不会丢失进度。
close-delimited 模式只有在传输层给出可靠 EOF 时才传入 bEnd = true。超时、取消、 RST 和普通 EOF 不能混为同一种上层状态。
gzip 自动解码
xrtHttpDecodeCreate 直接读取解析后的字段数组。把 xrtHttp1BodyRead 发布的每个 正文片段交给 xrtHttpDecodeWrite,并只在 body reader 完成时设置 bFinal。
identity 和显式原样回退路径不复制输入。gzip/deflate 路径按 Content-Encoding 逆序流式解码,验证 gzip Header、CRC、ISIZE 和压缩流终态。每个中间层与最终 输出都受同一明文硬限额约束。
详见 HTTP 正文解码。
原始写出
xrtHttp1RequestWrite 和 xrtHttp1ResponseWrite 不添加 Host、Date、Server 或其他 策略字段。空输出用于精确测量,容量不足不会产生半个 Header。
高性能发送建议:
1. 在连接或协程栈上的小缓冲中写 Header; 2. 用 xrtNetStreamSendVec 一次提交 Header 与小正文; 3. 大正文用 xrtNetStreamSendRef、SendRefs、SendTake 或 SendBuffer; 4. chunked 正文只用 xrtHttp1ChunkLineWrite 生成短前缀,数据本身保持引用发送; 5. XNET_RESULT_AGAIN 时等待 writable/drain,不绕过网络队列硬上限。
这条路径只构造必需的线路字节,不创建请求、响应、字典或正文对象。
报文长度
xhttp1head.Bytes:起始行、Header 和最终空行的线路长度;xhttp1bodyplan.Length:定长正文长度,仅在FIXED模式有效;xhttp1body.Received:已经发布的应用正文长度;xhttp1body.WireBytes:已经消费的正文线路长度;xhttp1message.Wire.Size:连续输入中第一条完整消息的线路总长度;xhttp1message.BodyBytes:移除 chunked 元数据后的正文长度。
chunked 和 close-delimited 消息在完成前不存在可提前得知的总线路长度。
TLS 与 Upgrade
HTTP 不拥有 TLS。http1_tls 只是块链适配器,不创建连接或安全策略;证书验证、SNI、会话恢复和 ALPN 仍属于通用 TLS 模块。它按需连续化实际 Header,不增加连接级固定缓冲。
xrtHttpUpgrade*、xrtHttpConnection* 和 WebSocket 握手函数共同完成 Upgrade 验证。101 后的剩余字节必须原样交给新协议,不能继续送入 HTTP body reader。
完整消息便利层
xrtHttp1RequestMessageParse 和 xrtHttp1ResponseMessageParse 适合已经连续驻留在 内存中的报文、测试和协议网关。它们仍只借用输入,不持有堆对象。
固定长度或 close-delimited 正文可由 xrtHttp1MessageBodyView 直接查看;chunked 正文使用 xrtHttp1MessageBodyCopy 去除分帧。真正的网络热路径应优先使用流式 body reader,避免等待和复制整个消息。
扩展库边界
客户端池、重定向、重试、缓存、认证、Cookie、MIME、Multipart、FormData、SSE、 服务器路由和中间件属于独立发布的 xhttp 扩展;它们不参与 XRT 核心构建、单头包或 兼容性承诺。
xhttp1status类型
HTTP/1 解析返回值区分数据不足、字段描述符不足和真正的协议错误。
| 值 | 语义 |
|---|---|
XHTTP1_ERROR | 失败 |
XHTTP1_MORE | 需要更多输入 |
XHTTP1_READY | 就绪 |
XHTTP1_FIELDS | 已启用字段解析 |
xhttpkind类型
起始行决定消息方向,调用方不需要依赖启发式自动识别。
| 值 | 语义 |
|---|---|
XHTTP_REQUEST | 请求方向 |
XHTTP_RESPONSE | 响应方向 |
xhttp1flag类型
Header 只描述线上的显式语义,完整消息体计划由上层结合请求方法计算。
| 值 | 语义 |
|---|---|
XHTTP1_KEEP_ALIVE | keep-alive |
XHTTP1_CONNECTION_CLOSE | close |
XHTTP1_UPGRADE | Upgrade |
XHTTP1_CONTENT_LENGTH | Content-Length |
XHTTP1_CHUNKED | chunked |
XHTTP1_TRANSFER_ENCODING | TRANSFERENCODING |
XHTTP1_TRANSFER_OTHER | 未知传输编码 |
xhttp1error类型
HTTP/1 解析与封包使用稳定错误码,Offset 和 Line 提供精确协议位置。
| 值 | 语义 |
|---|---|
XHTTP1_ERROR_ARGUMENT | 参数非法 |
XHTTP1_ERROR_HEAD_INCOMPLETE | HeadIncomplete失败 |
XHTTP1_ERROR_HEAD_TOO_LARGE | HeadTooLarge失败 |
XHTTP1_ERROR_START_LINE_TOO_LARGE | 失败 |
XHTTP1_ERROR_FIELD_LINE_TOO_LARGE | 失败 |
XHTTP1_ERROR_TOO_MANY_FIELDS | TOOMANY字段 |
XHTTP1_ERROR_LINE_END | 失败 |
XHTTP1_ERROR_START_LINE | 失败 |
XHTTP1_ERROR_METHOD | 失败 |
XHTTP1_ERROR_TARGET | 失败 |
XHTTP1_ERROR_VERSION | 失败 |
XHTTP1_ERROR_STATUS | 失败 |
XHTTP1_ERROR_REASON | 失败 |
XHTTP1_ERROR_FIELD_NAME | FIELD名称 |
XHTTP1_ERROR_FIELD_VALUE | FIELD值非法 |
XHTTP1_ERROR_CONTENT_LENGTH | 失败 |
XHTTP1_ERROR_CONFLICTING_CONTENT_LENGTH | 失败 |
XHTTP1_ERROR_TRANSFER_LENGTH | 失败 |
XHTTP1_ERROR_TRANSFER_ENCODING | 失败 |
XHTTP1_ERROR_UNSUPPORTED_TRANSFER_ENCODING | 不支持TRANSFERENCODING |
XHTTP1_ERROR_CONNECTION | 失败 |
XHTTP1_ERROR_OUTPUT_SIZE | 输出失败尺寸 |
XHTTP1_ERROR_REQUEST_TRANSFER_ENCODING | 失败 |
XHTTP1_ERROR_BODY_TOO_LARGE | 失败 |
XHTTP1_ERROR_BODY_INCOMPLETE | 失败 |
XHTTP1_ERROR_CHUNK_LINE_TOO_LARGE | 失败 |
XHTTP1_ERROR_CHUNK_SIZE | CHUNK尺寸 |
XHTTP1_ERROR_CHUNK_EXTENSION | 失败 |
XHTTP1_ERROR_CHUNK_TERMINATOR | 失败 |
XHTTP1_ERROR_TRAILER_TOO_LARGE | 失败 |
XHTTP1_ERROR_TRAILER_LINE_TOO_LARGE | 失败 |
XHTTP1_ERROR_TOO_MANY_TRAILERS | 失败 |
XHTTP1_ERROR_FORBIDDEN_TRAILER | 失败 |
XHTTP1_ERROR_UPGRADE | 升级语法非法 |
xhttp1limits类型
默认限额面向公网协议输入,调用方可以按服务端路由或客户端策略收紧。
| 字段 | 类型 | 语义 |
|---|---|---|
MaxHead | size_t | MaxHead |
MaxStartLine | size_t | MaxStartLine |
MaxFieldLine | size_t | MaxFieldLine |
MaxFields | size_t | MaxFields |
xhttp1errorinfo类型
解析错误位置从消息首字节开始计数,Line 从一开始计数。
| 字段 | 类型 | 语义 |
|---|---|---|
Code | xhttp1error | 错误码 |
Offset | size_t | 偏移量 |
Line | size_t | 行号 |
xhttp1transfercoding类型
Transfer Coding 名称和原样参数都借用字段值,Parameters 不含首个分号。
| 字段 | 类型 | 语义 |
|---|---|---|
Name | xstrview | 名称 |
Parameters | xstrview | Parameters |
xhttp1head类型
Head 只借用输入和字段数组;输入与数组必须覆盖 Head 的使用期。 FIELDS 状态下 FieldCount 是需要的描述符数量,其余字段已经可读取。
| 字段 | 类型 | 语义 |
|---|---|---|
Kind | xhttpkind | 错误种类 |
Version | xhttpversion | 结构版本 |
Flags | uint32 | 标志位 |
Status | uint16 | 状态输出 |
ContentLength | uint64 | ContentLength |
Bytes | size_t | Bytes |
Method | xstrview | 方法 |
Target | xstrview | 目标视图 |
Reason | xstrview | 原因文本 |
Fields | xhttpfield* | Fields |
FieldCount | size_t | FieldCount |
FieldCapacity | size_t | FieldCapacity |
MethodCode | xhttpmethod | MethodCode |
xhttp1bodymode类型
Body Plan 明确区分无正文、定长、分块、关闭定界和升级后的非 HTTP 字节。
| 值 | 语义 |
|---|---|
XHTTP1_BODY_NONE | 无 |
XHTTP1_BODY_FIXED | FIXED |
XHTTP1_BODY_CHUNKED | CHUNKED |
XHTTP1_BODY_CLOSE | CLOSE |
XHTTP1_BODY_TUNNEL | 升级后的非 HTTP 字节流 |
xhttp1bodystatus类型
Body Reader 每次只发布一个借用数据片段或一个终态。
| 值 | 语义 |
|---|---|
XHTTP1_BODY_ERROR | 失败 |
XHTTP1_BODY_MORE | 需要更多输入 |
XHTTP1_BODY_DATA | 数据损坏 |
XHTTP1_BODY_DONE | 完成 |
XHTTP1_BODY_FIELDS | 字段体形态 |
xhttp1bodyplan类型
Body Plan 是 Header 事实结合请求方法和响应状态后的唯一分帧结论。
| 字段 | 类型 | 语义 |
|---|---|---|
Mode | xhttp1bodymode | 模式 |
Length | uint64 | 长度 |
xhttp1bodylimits类型
流式正文不预分配内存;限额约束累计正文、chunk 行和 trailer 区。
| 字段 | 类型 | 语义 |
|---|---|---|
MaxBody | uint64 | MaxBody |
MaxChunkLine | size_t | MaxChunkLine |
MaxTrailer | size_t | MaxTrailer |
MaxTrailerLine | size_t | MaxTrailerLine |
MaxTrailers | size_t | MaxTrailers |
xhttp1body类型
Body Reader 由调用方持有且不分配内存;Trailers 借用完成调用中的输入。 公开计数可用于进度与诊断,其余状态只能由本模块推进。
| 字段 | 类型 | 语义 |
|---|---|---|
Mode | xhttp1bodymode | 模式 |
Remaining | uint64 | Remaining |
Received | uint64 | Received |
WireBytes | uint64 | WireBytes |
Trailers | xhttpfield* | Trailers |
TrailerCount | size_t | TrailerCount |
TrailerCapacity | size_t | TrailerCapacity |
Limits | xhttp1bodylimits | Limits |
ChunkSize | uint64 | ChunkSize |
ChunkLineBytes | size_t | ChunkLineBytes |
State | uint32 | 状态 |
xhttp1message类型
完整消息便利层借用连续输入、Header 和 trailer 描述符,不持有堆内存。 Wire 只覆盖第一条完整消息,BodyBytes 是移除 chunked 分帧后的正文长度。
| 字段 | 类型 | 语义 |
|---|---|---|
Head | xhttp1head | 头指针 |
Plan | xhttp1bodyplan | Plan |
Limits | xhttp1bodylimits | Limits |
Wire | xbytesview | Wire |
Trailers | xhttpfield* | Trailers |
TrailerCount | size_t | TrailerCount |
TrailerCapacity | size_t | TrailerCapacity |
BodyBytes | size_t | BodyBytes |
xrtHttp1TargetValid函数
验证非空 request-target 不含空白、控制字符或 fragment。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Target | 输入 | 借用 | 目标文本 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 合法 | — |
false | 非法 | 纯谓词 |
- 无 — 纯谓词
xrtHttp1LimitsInit函数
初始化适合公网输入的限额:8 KiB 起始行、64 KiB Header、100 字段。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pLimits | 输出 | 非空、可未对齐 | 接收限额(解析前复制) |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 无 | 纯初始化 | — |
- 无
xrtHttp1HeadInit函数
初始化借用调用方字段数组的空 Head。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pHead | 输出 | 非空 | 接收 Head |
pFields | 输入 | 借用存储 | 字段描述符数组 |
iCapacity | 输入 | — | 数组容量 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 无 | 纯初始化 | — |
- 无
xrtHttp1RequestParse函数
严格增量解析 HTTP/1.0 或 HTTP/1.1 请求 Header。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Input | 输入 | 借用 | 当前累积字节 |
pHead | 输入/输出 | 已初始化 | Head(成功后 Bytes 为消费量) |
pLimits | 输入 | 允许空 | 空 = LimitsInit 默认 |
pError | 输出 | 可空 | 接收错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_READY | 完整消息就绪 | — |
XHTTP1_FIELDS | 头部就绪(还差消息体) | — |
XHTTP1_MORE | 需要更多输入 | — |
XHTTP1_ERROR | 失败 | — |
xrt.http1域错误 — 起始行/Header 语法或超限
范例已编译验证
http/http1 · 请求解析 · 观察
if ( xrtHttp1RequestParse(
Input, &Head, NULL, NULL
) != XHTTP1_READY ) {
xrtHttp1ResponseParse函数
严格增量解析 HTTP/1.0 或 HTTP/1.1 响应 Header。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Input | 输入 | 借用 | 当前累积字节 |
pHead | 输入/输出 | 已初始化 | Head |
pLimits | 输入 | 允许空 | 限额 |
pError | 输出 | 可空 | 错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_READY | 完整消息就绪 | — |
XHTTP1_FIELDS | 头部就绪(还差消息体) | — |
XHTTP1_MORE | 需要更多输入 | 不设错误 |
XHTTP1_ERROR | 解析失败 | xrt.http 域错误 |
xrt.http1域错误
范例已编译验证
http1_body · 观察
if ( xrtHttp1ResponseParse(
(xbytesview){ Message, sizeof(Message) - 1u },
&Head, NULL, NULL
) != XHTTP1_READY ) {
xrtHttp1TransferCodingNext函数
严格迭代一个 Transfer-Encoding 字段值,Offset 初始为零。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Value | 输入 | 借用 | 字段值 |
pOffset | 输入/输出 | 初始零 | 游标 |
pCoding | 输出 | 非空 | 接收编码条目 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP_NEXT_ITEM | 已产出一项 | — |
XHTTP_NEXT_END | 遍历结束 | 不设错误 |
XHTTP_NEXT_ERROR | 解析失败 | xrt.http 域错误 |
xrt.http1域错误
范例已编译验证
head_tour · 观察
if ( ((Next = xrtHttp1TransferCodingNext(
pField->Value, &iOffset, &Coding)) != XHTTP_NEXT_ITEM) ||
(Coding.Name.Size != 4u) ||
(memcmp(Coding.Name.Data, "gzip", 4u) != 0) ||
(xrtHttp1TransferCodingNext(pField->Value, &iOffset,
&Coding) != XHTTP_NEXT_ITEM) ||
(Coding.Name.Size != 7u) ||
(memcmp(Coding.Name.Data, "chunked", 7u) != 0) ||
(xrtHttp1TransferCodingNext(pField->Value, &iOffset,
&Coding) != XHTTP_NEXT_END) ) {
xrtHttp1Field函数
返回第一个同名 Header,未找到返回空指针。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pHead | 输入 | 非空 | 已解析 Head |
Name | 输入 | 借用 | 查找名称 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 非空 | 借用字段地址 | — |
NULL | 未找到 | 不设错 |
- 无 — 未找到是查询结果
范例已编译验证
http1/head_tour · 字段 · 观察
((pField = xrtHttp1Field(&Head,
XRT_STR_LITERAL("host"))) == NULL) ||
xrtHttp1RequestWrite函数
校验并写入完整请求 Header;不自动添加 Host 等策略字段。空输出查长度;容量不足不写半个报文。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Method | 输入 | 借用 | 方法 |
Target | 输入 | 借用 | 目标 |
Version | 输入 | — | HTTP 版本 |
pFields | 输入 | 借用数组 | 字段 |
iFieldCount | 输入 | — | 字段数 |
pOutput | 输出 | 可空、不得与输入重叠 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 完整报文已写出 | — |
false | 校验失败或容量不足 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法xrt.http1域错误 — 方法/目标非法XERR_RANGE— 容量不足
xrtHttp1ResponseWrite函数
校验并写入完整响应 Header;不自动添加 Content-Length 或连接策略。Reason 允许为空。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Version | 输入 | — | HTTP 版本 |
iStatus | 输入 | 100–999 | 状态码 |
Reason | 输入 | 可空 | 原因短语 |
pFields | 输入 | 借用数组 | 字段 |
iFieldCount | 输入 | — | 字段数 |
pOutput | 输出 | 可空 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 完整报文已写出 | — |
false | 校验失败或容量不足 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_RANGE— 状态越界或容量不足
范例已编译验证
http/http1 · 写出 · 观察
if ( !xrtHttp1ResponseWrite(
XHTTP_VERSION_1_1, 200, XRT_STR_LITERAL("OK"),
ResponseFields, 2, Response, sizeof(Response), &iSize
) ) {
xrtHttp1BodyLimitsInit函数
初始化无正文预设上限的流式 Body 限额;上层可按路由收紧。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pLimits | 输出 | 非空、可未对齐 | 接收限额(Init 时复制) |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 无 | 纯初始化 | — |
- 无
xrtHttp1RequestBodyPlan函数
按 RFC 9112 请求分帧优先级生成 Body Plan。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pHead | 输入 | 非空、已完整解析 | 请求 Head |
pPlan | 输出 | 非空 | 接收分帧计划 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 计划已生成 | — |
false | 分帧字段矛盾(如 TE+CL 并存) | 输出不变 |
xrt.http1域错误 — Transfer-Encoding/Content-Length 冲突
范例已编译验证
http1/head_tour · 分帧 · 观察
if ( !xrtHttp1RequestBodyPlan(&Head, &Plan) ||
(Plan.Mode != XHTTP1_BODY_CHUNKED) ) {
xrtHttp1ResponseBodyPlan函数
按请求方法与响应状态生成 Body Plan;HEAD 和 CONNECT 必须传入原请求方法。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pHead | 输入 | 非空、已完整解析 | 响应 Head |
RequestMethod | 输入 | 借用 | 原请求方法 |
pPlan | 输出 | 非空 | 接收分帧计划 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 计划已生成 | — |
false | 分帧字段矛盾 | 输出不变 |
xrt.http1域错误
范例已编译验证
if ( !xrtHttp1ResponseBodyPlan(
&Head, XRT_STR_LITERAL("GET"), &Plan
) ) {
xrtHttp1BodyInit函数
初始化无分配 Body Reader;trailer 描述符可为空并在 FIELDS 后重新绑定。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pBody | 输出 | 非空 | 接收 Reader |
pPlan | 输入 | 已生成 | 分帧计划 |
pTrailers | 输入 | 可空 | trailer 描述符存储 |
iTrailerCapacity | 输入 | — | trailer 容量 |
pLimits | 输入 | 允许空 | 空 = BodyLimitsInit |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | Reader 已就绪 | — |
false | 参数错误 | XERR_ARGUMENT |
XERR_ARGUMENT— 指针为空或视图非法
范例已编译验证
if ( !xrtHttp1BodyInit(
&Body, &Plan, Trailers, 4, &Limits
) ) {
xrtHttp1BodyTrailers函数
在 FIELDS 状态后替换 trailer 描述符存储,不重置正文解码进度。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pBody | 输入/输出 | 非空 | Reader |
pTrailers | 输入 | 非空 | 新存储 |
iCapacity | 输入 | — | 容量 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 已重绑 | — |
false | 状态非 FIELDS 或参数错误 | 进度不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_STATE— 当前状态不可重绑
xrtHttp1TrailersParse函数
严格解析从第一行开始并由空行结束的 trailer 区;所有字段均借用 Input。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Input | 输入 | 借用 | trailer 区字节 |
pFields | 输出 | 借用存储 | 接收字段 |
iCapacity | 输入 | — | 字段容量 |
pLimits | 输入 | 允许空 | 限额 |
pBytes | 输出 | 可空 | 消费字节数 |
pCount | 输出 | 可空 | 字段数 |
pError | 输出 | 可空 | 错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_READY | 完整消息就绪 | — |
XHTTP1_FIELDS | 头部就绪(还差消息体) | — |
XHTTP1_MORE | 需要更多输入 | 不设错误 |
XHTTP1_ERROR | 解析失败 | xrt.http 域错误 |
xrt.http1域错误 — 字段名非法或超限
范例已编译验证
http1/head_tour · trailer · 观察
if ( (xrtHttp1TrailersParse(
(xbytesview) { (const uint8*)sTrailer,
sizeof(sTrailer) - 1u },
Trailers, 4u, &BodyLimits, &iBytes, &iCount,
&Error) != XHTTP1_READY) ||
(iCount != 1u) ||
(Trailers[0].Value.Size != 1u) ) {
xrtHttp1ChunkLineWrite函数
写入十六进制 chunk-size 行;只写 size 行,正文可向量发送零复制。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
iSize | 输入 | — | chunk 数据长度 |
Extensions | 输入 | 空或以分号起始 | 扩展后缀 |
pOutput | 输出 | 可空 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 已写出 | — |
false | 容量不足或扩展非法 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_RANGE— 容量不足
范例已编译验证
http1/head_tour · 分块 · 观察
if ( !xrtHttp1ChunkLineWrite(5u, XRT_STR_LITERAL(""), arrLine,
sizeof(arrLine), &iSize) ||
(iSize != 3u) ||
(memcmp(arrLine, "5\r\n", 3u) != 0) ||
!xrtHttp1ChunkLineWrite(5u, XRT_STR_LITERAL(";x"),
arrLine, sizeof(arrLine), &iSize) ||
(iSize != 5u) ||
(memcmp(arrLine, "5;x\r\n", 5u) != 0) ) {
xrtHttp1ChunkWrite函数
把一段非空正文封装为完整 chunk;空正文是成功空操作,不结束消息。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Data | 输入 | 借用 | 非空正文段 |
pOutput | 输出 | 可空 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 完整 chunk 已写出 | — |
false | 空正文配非空操作以外错误 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_RANGE— 容量不足
范例已编译验证
http/http1_body · 分块 · 观察
if ( !xrtHttp1ChunkWrite(
(xbytesview){ (cbytes)"hello", 5 },
Output, sizeof(Output), &iChunk
) || !xrtHttp1ChunkEndWrite(
Trailers, 1, Output + iChunk,
sizeof(Output) - iChunk, &iEnd
) ) {
xrtHttp1ChunkEndWrite函数
写入 last-chunk、可选 trailer 和最终空行;调用方须确认字段定义明确允许 trailer。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pTrailers | 输入 | 允许空 | trailer 字段 |
iTrailerCount | 输入 | — | 条目数 |
pOutput | 输出 | 可空 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 结束序列已写出 | — |
false | 容量不足 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_RANGE
xrtHttp1BodyRead函数
推进正文状态机;Consumed 是本次可移除的线缆字节,Data 仅 DATA 状态有效。定长/分块正文过早结束返回协议错误。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pBody | 输入/输出 | 已初始化 | Reader |
Input | 输入 | 借用 | 当前线缆字节 |
bEnd | 输入 | — | 可靠传输已结束 |
pConsumed | 输出 | 可空 | 本次消费量 |
pData | 输出 | 可空 | 接收明文段(借用输入) |
pError | 输出 | 可空 | 错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_BODY_DATA | 一段明文已发布 | — |
XHTTP1_BODY_FIELDS | 进入 trailer 解析 | — |
XHTTP1_BODY_DONE | 正文与 trailer 完整消费 | — |
XHTTP1_BODY_ERROR | 协议错误或过早结束 | xrt.http1 域错误 |
xrt.http1域错误 — 截断、超限或非法 chunk
范例已编译验证
xhttp1bodystatus Status = xrtHttp1BodyRead(
&Body,
(xbytesview){ Message + iOffset, sizeof(Message) - 1u - iOffset },
false, &iConsumed, &Data, NULL
);
xrtHttp1BodyDone函数
判断 Reader 是否已经完整消费 HTTP 正文与 trailer。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pBody | 输入 | 允许空 | Reader |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 已完整消费 | — |
false | 未完成、失败或参数非法 | 纯查询 |
- 无 — 纯查询
xrtHttp1MessageInit函数
初始化借用调用方 Header 与 trailer 描述符数组的空完整消息。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pMessage | 输出 | 非空 | 接收消息 |
pFields | 输入 | 借用存储 | Header 数组 |
iFieldCapacity | 输入 | — | Header 容量 |
pTrailers | 输入 | 借用存储 | trailer 数组 |
iTrailerCapacity | 输入 | — | trailer 容量 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 无 | 纯初始化 | — |
- 无
xrtHttp1RequestMessageParse函数
扫描第一条完整请求;bEnd 表示可靠 EOF,拒绝被截断的 Header 或正文。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Input | 输入 | 借用 | 消息字节 |
bEnd | 输入 | — | 输入即全部字节 |
pMessage | 输出 | 已初始化 | 接收完整消息 |
pHeadLimits | 输入 | 允许空 | Head 限额 |
pBodyLimits | 输入 | 允许空 | Body 限额 |
pError | 输出 | 可空 | 错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_READY | 完整消息就绪 | — |
XHTTP1_FIELDS | 头部就绪(还差消息体) | — |
XHTTP1_MORE | 需要更多输入 | — |
XHTTP1_ERROR | 失败 | — |
xrt.http1域错误 — 截断(bEnd 下 MORE 升级为错误)或协议错误
范例已编译验证
if ( (xrtHttp1RequestMessageParse(
(xbytesview) { (const uint8*)sFixed,
sizeof(sFixed) - 1u },
true, &Message, &Limits, &BodyLimits,
&Error) != XHTTP1_READY) ||
((View = xrtHttp1MessageBodyView(&Message)).Size != 2u) ||
(memcmp(View.Data, "ok", 2u) != 0) ) {
xrtHttp1ResponseMessageParse函数
扫描第一条完整响应;RequestMethod 用于 HEAD、CONNECT 和普通响应分帧。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
Input | 输入 | 借用 | 消息字节 |
bEnd | 输入 | — | 输入即全部字节 |
RequestMethod | 输入 | 借用 | 原请求方法 |
pMessage | 输出 | 已初始化 | 接收完整消息 |
pHeadLimits | 输入 | 允许空 | Head 限额 |
pBodyLimits | 输入 | 允许空 | Body 限额 |
pError | 输出 | 可空 | 错误位置 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
XHTTP1_READY | 完整消息就绪 | — |
XHTTP1_FIELDS | 头部就绪(还差消息体) | — |
XHTTP1_MORE | 需要更多输入 | 不设错误 |
XHTTP1_ERROR | 解析失败 | xrt.http 域错误 |
xrt.http1域错误
范例已编译验证
http/http1_message · 完整解析 · 观察
if ( xrtHttp1ResponseMessageParse(
(xbytesview){ Wire, sizeof(Wire) - 1u }, false,
XRT_STR_LITERAL("GET"),
&Message, NULL, NULL, NULL
) != XHTTP1_READY ) {
xrtHttp1MessageBodyView函数
返回无需移除 chunked 分帧时的借用正文;chunked 或空正文返回空视图。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pMessage | 输入 | 非空 | 完整消息 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
| 非空 | 借用正文视图 | — |
| 空视图 | chunked/空正文(应改用 BodyCopy) | 纯查询 |
- 无 — 纯查询
xrtHttp1MessageBodyCopy函数
把正文复制到连续输出并移除 chunked 分帧;空输出可精确查询所需长度。
参数
| 参数 | 方向 | 约束 | 说明 |
|---|---|---|---|
pMessage | 输入 | 非空 | 完整消息 |
pOutput | 输出 | 可空 | 空+零容量 = 查长度 |
iCapacity | 输入 | — | 容量 |
pSize | 输出 | 可空 | 长度 |
| 返回 | 含义 | 失败时状态 |
|---|---|---|
true | 已复制(含去分帧) | — |
false | 容量不足或超限 | 输出不变 |
XERR_ARGUMENT— 指针为空或视图非法XERR_RANGE— 容量不足或正文超限
范例已编译验证
if ( !xrtHttp1MessageBodyCopy(
&Message, Body, sizeof(Body), &iSize
) ) {
常量索引常量
以下常量在本页所属头文件中定义,语义见公共头注释。
| 常量 | 说明 |
|---|---|
| XHTTP1_BODY_CHUNKED | 见头文件注释 |
| XHTTP1_BODY_CLOSE | 见头文件注释 |
| XHTTP1_BODY_DATA | 见头文件注释 |
| XHTTP1_BODY_DONE | 见头文件注释 |
| XHTTP1_BODY_ERROR | 见头文件注释 |
| XHTTP1_BODY_FIELDS | 见头文件注释 |
| XHTTP1_BODY_FIXED | 见头文件注释 |
| XHTTP1_BODY_MORE | 见头文件注释 |
| XHTTP1_BODY_NONE | 见头文件注释 |
| XHTTP1_BODY_TUNNEL | 见头文件注释 |
| XHTTP1_CHUNKED | 见头文件注释 |
| XHTTP1_CONNECTION_CLOSE | 见头文件注释 |
| XHTTP1_CONTENT_LENGTH | 见头文件注释 |
| XHTTP1_ERROR | 见头文件注释 |
| XHTTP1_ERROR_ARGUMENT | 见头文件注释 |
| XHTTP1_ERROR_BODY_INCOMPLETE | 见头文件注释 |
| XHTTP1_ERROR_BODY_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_CHUNK_EXTENSION | 见头文件注释 |
| XHTTP1_ERROR_CHUNK_LINE_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_CHUNK_SIZE | 见头文件注释 |
| XHTTP1_ERROR_CHUNK_TERMINATOR | 见头文件注释 |
| XHTTP1_ERROR_CONFLICTING_CONTENT_LENGTH | 见头文件注释 |
| XHTTP1_ERROR_CONNECTION | 见头文件注释 |
| XHTTP1_ERROR_CONTENT_LENGTH | 见头文件注释 |
| XHTTP1_ERROR_FIELD_LINE_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_FIELD_NAME | 见头文件注释 |
| XHTTP1_ERROR_FIELD_VALUE | 见头文件注释 |
| XHTTP1_ERROR_FORBIDDEN_TRAILER | 见头文件注释 |
| XHTTP1_ERROR_HEAD_INCOMPLETE | 见头文件注释 |
| XHTTP1_ERROR_HEAD_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_LINE_END | 见头文件注释 |
| XHTTP1_ERROR_METHOD | 见头文件注释 |
| XHTTP1_ERROR_OUTPUT_SIZE | 见头文件注释 |
| XHTTP1_ERROR_REASON | 见头文件注释 |
| XHTTP1_ERROR_REQUEST_TRANSFER_ENCODING | 见头文件注释 |
| XHTTP1_ERROR_START_LINE | 见头文件注释 |
| XHTTP1_ERROR_START_LINE_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_STATUS | 见头文件注释 |
| XHTTP1_ERROR_TARGET | 见头文件注释 |
| XHTTP1_ERROR_TOO_MANY_FIELDS | 见头文件注释 |
| XHTTP1_ERROR_TOO_MANY_TRAILERS | 见头文件注释 |
| XHTTP1_ERROR_TRAILER_LINE_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_TRAILER_TOO_LARGE | 见头文件注释 |
| XHTTP1_ERROR_TRANSFER_ENCODING | 见头文件注释 |
| XHTTP1_ERROR_TRANSFER_LENGTH | 见头文件注释 |
| XHTTP1_ERROR_UNSUPPORTED_TRANSFER_ENCODING | 见头文件注释 |
| XHTTP1_ERROR_UPGRADE | 见头文件注释 |
| XHTTP1_ERROR_VERSION | 见头文件注释 |
| XHTTP1_FIELDS | 见头文件注释 |
| XHTTP1_KEEP_ALIVE | 见头文件注释 |
| XHTTP1_MORE | 见头文件注释 |
| XHTTP1_READY | 见头文件注释 |
| XHTTP1_TRANSFER_ENCODING | 见头文件注释 |
| XHTTP1_TRANSFER_OTHER | 见头文件注释 |
| XHTTP1_UPGRADE | 见头文件注释 |
| XHTTP_REQUEST | 见头文件注释 |
| XHTTP_RESPONSE | 见头文件注释 |