模块契约HTTP 正文解码

线程

解码与分块 API 为无共享状态的纯函数,可任意线程并发调用。

模式

  • XHTTP_DECODE_IDENTITY:没有内容编码或只有 identity,输入视图直接交给回调;
  • XHTTP_DECODE_CONTENT:按线路声明的逆序执行 gzip 或 HTTP deflate 解码;
  • XHTTP_DECODE_RAW:仅在显式设置 XHTTP_DECODE_ALLOW_RAW 后,对未知编码原样交付。

默认策略严格拒绝未知编码,避免调用方把未解码字节误当作明文。代理、缓存或需要 保留扩展编码的程序可以选择原样回退,并通过 xrtHttpDecodeMode 保留元数据。

限额

OutputLimit 同时限制每个中间解码层和最终明文,防止嵌套压缩绕过膨胀限制。 GzipHeaderLimit 限制可选 gzip Header,MaxCodings 限制嵌套层数。默认最多四层, 实现硬上限为 XHTTP_CONTENT_CODINGS_MAX。

解码器不保存正文。输出视图只在回调期间有效,回调必须在返回前消费或复制数据。 xrtHttpDecodeReset 会复用已经分配的 Inflate 滑动窗口,适合连接池和长连接逐消息 处理,不需要为每个响应重新分配 32 KiB 窗口。

输出回调返回 false 会把当前解码器置为失败终态;本次输入与输出计数不会发布,后续 写入返回状态错误。调用方处理完自己的回调错误后,可以显式调用 xrtHttpDecodeReset 开始下一条消息。字段描述符和配置允许未对齐存储,多层创建的每个 OOM 点都保证释放 已经建立的解码层。

HTTP/1 的报文边界仍由 xrtHttp1BodyRead 决定。只有该 reader 返回最终完成状态时, 最后一次 xrtHttpDecodeWrite 才传入 bFinal = true;解码器随后会验证压缩流结束、 gzip CRC 与长度 trailer。

模块边界

模块裁剪宏作用
httpXRT_MODULE_HTTPtoken、字段、方法、状态和 Content-Length
http_paramXRT_MODULE_HTTP_PARAM参数与 quoted-string 语法
http_param_hostXRT_MODULE_HTTP_PARAM_HOST参数解码后的无分配 Host 验证
http_expectXRT_MODULE_HTTP_EXPECTExpect 字段
http_upgradeXRT_MODULE_HTTP_UPGRADEUpgrade 字段与写出
http_teXRT_MODULE_HTTP_TETE 与 transfer-coding 参数
http_connectionXRT_MODULE_HTTP_CONNECTIONConnection 选项与持久连接
http_trailerXRT_MODULE_HTTP_TRAILERTrailer 声明和尾字段约束
http_encodingXRT_MODULE_HTTP_ENCODINGAccept-Encoding 与 Content-Encoding
http_decodeXRT_MODULE_HTTP_DECODE流式 gzip/deflate 自动解码
http_hostXRT_MODULE_HTTP_HOSTHost authority
http_targetXRT_MODULE_HTTP_TARGET四种 request-target
http1_headXRT_MODULE_HTTP1_HEAD起始行、Header 解析与写入
http1_netXRT_MODULE_HTTP1_NETTCP 块链 Header 解析与余量保留
http1_tlsXRT_MODULE_HTTP1_TLSTLS 明文块链增量 Header 解析
http1_bodyXRT_MODULE_HTTP1_BODY正文计划、chunked 和 trailer
http1_messageXRT_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 核心构建、单头包或 兼容性承诺。

xhttpdecodemode类型

解码模式明确区分无编码、成功接管的内置编码和显式允许的原样回退。

值语义
XHTTP_DECODE_IDENTITY无变换
XHTTP_DECODE_CONTENT按内容编码解码
XHTTP_DECODE_RAW允许透传原始字节
typedef enum xhttpdecodemode { XHTTP_DECODE_IDENTITY = 0, XHTTP_DECODE_CONTENT, XHTTP_DECODE_RAW } xhttpdecodemode;

xhttpdecodeflag类型

默认拒绝未知编码;调用方可显式选择保留整个原始表示。

值语义
XHTTP_DECODE_ALLOW_RAW允许透传原始字节
typedef enum xhttpdecodeflag { XHTTP_DECODE_ALLOW_RAW = UINT32_C(0x00000001)

xhttpdecodeerror类型

错误码覆盖配置、Content-Encoding、状态和输出边界。

值语义
XHTTP_DECODE_ERROR_ARGUMENT参数非法
XHTTP_DECODE_ERROR_CONFIG配置非法
XHTTP_DECODE_ERROR_CONTENT_ENCODING失败
XHTTP_DECODE_ERROR_UNSUPPORTED不支持
XHTTP_DECODE_ERROR_STATE状态非法
XHTTP_DECODE_ERROR_LIMIT超限
XHTTP_DECODE_ERROR_OUTPUT输出回调失败
typedef enum xhttpdecodeerror { XHTTP_DECODE_ERROR_ARGUMENT = 1, XHTTP_DECODE_ERROR_CONFIG, XHTTP_DECODE_ERROR_CONTENT_ENCODING, XHTTP_DECODE_ERROR_UNSUPPORTED, XHTTP_DECODE_ERROR_STATE, XHTTP_DECODE_ERROR_LIMIT, XHTTP_DECODE_ERROR_OUTPUT } xhttpdecodeerror;

xhttpdecodeconfig类型

每个解码层和最终明文都受同一个硬限额约束。

字段类型语义
OutputLimituint64OutputLimit
GzipHeaderLimituint32GzipHeaderLimit
MaxCodingsuint32MaxCodings
Flagsuint32标志位
typedef struct xhttpdecodeconfig { uint64 OutputLimit; uint32 GzipHeaderLimit; uint32 MaxCodings; uint32 Flags; } xhttpdecodeconfig;

xhttpdecode类型

HTTP 解码器拥有并复用底层 Inflate 状态。 不透明句柄或别名;生命周期与所有权见各使用方 API 节。

typedef struct xhttpdecode xhttpdecode;

xhttpdecodeoutputproc类型

输出视图只在回调期间有效,返回 false 会终止当前解码器。 回调类型;参数与返回语义见签名及各使用方 API 节。

typedef bool(*xhttpdecodeoutputproc)(xbytesview Data, ptr pData)
配置与生命周期

xrtHttpDecodeConfigInit函数

初始化兼容配置:最多四层、64 KiB gzip Header、明文长度不设上限。

void xrtHttpDecodeConfigInit(xhttpdecodeconfig* pConfig)

参数

参数方向约束说明
pConfig输出非空接收兼容配置
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无

范例已编译验证

http/decode_tour · 配置 · 观察

	xrtHttpDecodeConfigInit(&Compat);

xrtHttpDecodeConfigInitSafe函数

初始化面向不可信对端的安全配置;明文最多 16 MiB,更大正文需显式修改 OutputLimit。

void xrtHttpDecodeConfigInitSafe(xhttpdecodeconfig* pConfig)

参数

参数方向约束说明
pConfig输出非空接收安全配置
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无;无限明文须显式设 XHTTP_DECODE_OUTPUT_UNLIMITED

范例已编译验证

http/decode_tour · 配置 · 观察

	xrtHttpDecodeConfigInitSafe(&Safe);

xrtHttpDecodeCreate函数

根据全部 Header 创建解码器;字段和值只在本次调用期间借用。

xhttpdecode* xrtHttpDecodeCreate(const xhttpfield* pFields, size_t iCount, const xhttpdecodeconfig* pConfig)

参数

参数方向约束说明
pFields输入借用(仅调用期间)字段数组
iCount输入—条目数
pConfig输入允许空空 = 兼容配置
返回值
返回含义失败时状态
非空解码器(按 Content-Encoding/Content-Length 决定模式)—
NULLHeader 不一致或 OOMxrt.http 域错误
错误
  • xrt.http 域错误 — 编码组合非法或长度矛盾
  • XERR_MEMORY

范例已编译验证

http/decode · 创建 · 观察

	xhttpdecode* pDecode = xrtHttpDecodeCreate(Fields, 1, NULL);

xrtHttpDecodeReset函数

为下一条消息复位并复用已经分配的 Inflate 窗口。

bool xrtHttpDecodeReset(xhttpdecode* pDecode, const xhttpfield* pFields, size_t iCount, const xhttpdecodeconfig* pConfig)

参数

参数方向约束说明
pDecode输入/输出非空解码器
pFields输入借用新消息字段
iCount输入—条目数
pConfig输入允许空新配置
返回值
返回含义失败时状态
true已复位可处理下一条—
false前一条未完成或 Header 非法状态不变
错误
  • XERR_STATE — 前一条消息未终结
  • xrt.http 域错误

范例已编译验证

http/decode_tour · 复用 · 观察

	if ( !xrtHttpDecodeReset(pDecode, Fields, 1u, &Compat) ||
		(xrtHttpDecodeMode(pDecode) != XHTTP_DECODE_IDENTITY) ||
		!xrtHttpDecodeWrite(pDecode,
			(xbytesview) { arrGzip, 4u }, true,
			exampleOutput, (ptr)&Out) ||
		!xrtHttpDecodeDone(pDecode) ||
		(Out.iBytes != 4u) ||
		(xrtHttpDecodeInputSize(pDecode) != 4u) ) {

xrtHttpDecodeDestroy函数

销毁解码器;空指针是安全的空操作。

void xrtHttpDecodeDestroy(xhttpdecode* pDecode)

参数

参数方向约束说明
pDecode输入允许空空 = 空操作
返回值
返回含义失败时状态
无引用与窗口已释放—
错误
  • 无 — 销毁不失败

范例已编译验证

http/decode · 收尾 · 观察

	xrtHttpDecodeDestroy(pDecode);
流式解码与观测

xrtHttpDecodeWrite函数

同步消费完整输入片段;bFinal 表示正文已达协议边界。无编码和原样回退路径直接调用 Output,不复制输入。

bool xrtHttpDecodeWrite(xhttpdecode* pDecode, xbytesview Input, bool bFinal, xhttpdecodeoutputproc pOutput, ptr pData)

参数

参数方向约束说明
pDecode输入/输出非空解码器
Input输入借用本段线路字节
bFinal输入—末段标记
pOutput输入允许空明文回调;空 = 丢弃
pData输入任意值回调数据
返回值
返回含义失败时状态
true已消费(终段校验通过)—
false数据损坏、超限或回调中止进入失败终态
错误
  • xrt.http 域错误 — 压缩流损坏/截断
  • XERR_RANGE — 超 OutputLimit
  • XERR_CANCELLED — 回调中止

范例已编译验证

http/decode · 解码 · 观察

	bSuccess = xrtHttpDecodeWrite(
		pDecode,
		(xbytesview){ Gzip, sizeof(Gzip) },
		true,
		printBody,
		stdout
	) && xrtHttpDecodeDone(pDecode);

xrtHttpDecodeMode函数

返回当前消息的交付模式。

xhttpdecodemode xrtHttpDecodeMode(const xhttpdecode* pDecode)

参数

参数方向约束说明
pDecode输入允许空解码器
返回值
返回含义失败时状态
XHTTP_DECODE_*直通/identity/解码模式—
零值参数非法XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或视图非法

范例已编译验证

http/decode_tour · 自省 · 观察

	if ( (xrtHttpDecodeMode(pDecode) != XHTTP_DECODE_CONTENT) ||
		!xrtHttpDecodeWrite(pDecode,
			(xbytesview) { arrGzip, sizeof(arrGzip) }, true,
			exampleOutput, (ptr)&Out) ||
		!xrtHttpDecodeDone(pDecode) ||
		(Out.iBytes != 26u) ||
		(memcmp(Out.arrText, "identity-passthrough-check",
			26u) != 0) ||
		(xrtHttpDecodeInputSize(pDecode) != 46u) ||
		(xrtHttpDecodeOutputSize(pDecode) != 26u) ) {

xrtHttpDecodeDone函数

判断最终正文边界和全部压缩流 trailer 均已验证。

bool xrtHttpDecodeDone(const xhttpdecode* pDecode)

参数

参数方向约束说明
pDecode输入允许空解码器
返回值
返回含义失败时状态
true消息完整终结—
false未完成或失败终态纯查询
错误
  • 无 — 纯查询

范例已编译验证

http/decode · 完成 · 观察

	) && xrtHttpDecodeDone(pDecode);

xrtHttpDecodeInputSize函数

返回成功提交给当前消息的线路正文总字节数。

uint64 xrtHttpDecodeInputSize(const xhttpdecode* pDecode)

参数

参数方向约束说明
pDecode输入允许空解码器
返回值
返回含义失败时状态
>= 0线路字节数—
0无或参数非法XERR_ARGUMENT(非法时)
错误
  • XERR_ARGUMENT — 指针为空或视图非法

范例已编译验证

http/decode_tour · 自省 · 观察

		(xrtHttpDecodeInputSize(pDecode) != 46u) ||
		(xrtHttpDecodeOutputSize(pDecode) != 26u) ) {

xrtHttpDecodeOutputSize函数

返回已经被输出回调接受或明确丢弃的正文总字节数。

uint64 xrtHttpDecodeOutputSize(const xhttpdecode* pDecode)

参数

参数方向约束说明
pDecode输入允许空解码器
返回值
返回含义失败时状态
>= 0明文字节数(含丢弃)—
0无或参数非法XERR_ARGUMENT(非法时)
错误
  • XERR_ARGUMENT — 指针为空或视图非法

范例已编译验证

http/decode_tour · 自省 · 观察

		(xrtHttpDecodeOutputSize(pDecode) != 26u) ) {

常量索引常量

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

常量说明
XHTTP_DECODE_ALLOW_RAW见头文件注释
XHTTP_DECODE_CONTENT见头文件注释
XHTTP_DECODE_ERROR_ARGUMENT见头文件注释
XHTTP_DECODE_ERROR_CONFIG见头文件注释
XHTTP_DECODE_ERROR_CONTENT_ENCODING见头文件注释
XHTTP_DECODE_ERROR_LIMIT见头文件注释
XHTTP_DECODE_ERROR_OUTPUT见头文件注释
XHTTP_DECODE_ERROR_STATE见头文件注释
XHTTP_DECODE_ERROR_UNSUPPORTED见头文件注释
XHTTP_DECODE_IDENTITY见头文件注释
XHTTP_DECODE_OUTPUT_SAFE_DEFAULT见头文件注释
XHTTP_DECODE_OUTPUT_UNLIMITED见头文件注释
XHTTP_DECODE_RAW见头文件注释