模块契约HTTP 协议底座

线程

解析、编码与字段表 API 为无共享状态的纯函数或单拥有者对象,可任意线程并发调用(不同对象间);同一对象(连接、字段表)由使用它的执行流独占。

模块边界

模块裁剪宏作用
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 核心构建、单头包或 兼容性承诺。

xhttp1status类型

HTTP/1 解析返回值区分数据不足、字段描述符不足和真正的协议错误。

值语义
XHTTP1_ERROR失败
XHTTP1_MORE需要更多输入
XHTTP1_READY就绪
XHTTP1_FIELDS已启用字段解析
typedef enum xhttp1status { XHTTP1_ERROR = -1, XHTTP1_MORE = 0, XHTTP1_READY = 1, XHTTP1_FIELDS = 2 } xhttp1status;

xhttpkind类型

起始行决定消息方向,调用方不需要依赖启发式自动识别。

值语义
XHTTP_REQUEST请求方向
XHTTP_RESPONSE响应方向
typedef enum xhttpkind { XHTTP_REQUEST = 1, XHTTP_RESPONSE } xhttpkind;

xhttp1flag类型

Header 只描述线上的显式语义,完整消息体计划由上层结合请求方法计算。

值语义
XHTTP1_KEEP_ALIVEkeep-alive
XHTTP1_CONNECTION_CLOSEclose
XHTTP1_UPGRADEUpgrade
XHTTP1_CONTENT_LENGTHContent-Length
XHTTP1_CHUNKEDchunked
XHTTP1_TRANSFER_ENCODINGTRANSFERENCODING
XHTTP1_TRANSFER_OTHER未知传输编码
typedef enum xhttp1flag { XHTTP1_KEEP_ALIVE = UINT32_C(0x00000001), XHTTP1_CONNECTION_CLOSE = UINT32_C(0x00000002), XHTTP1_UPGRADE = UINT32_C(0x00000004), XHTTP1_CONTENT_LENGTH = UINT32_C(0x00000008), XHTTP1_CHUNKED = UINT32_C(0x00000010), XHTTP1_TRANSFER_ENCODING = UINT32_C(0x00000020), XHTTP1_TRANSFER_OTHER = UINT32_C(0x00000040)

xhttp1error类型

HTTP/1 解析与封包使用稳定错误码,Offset 和 Line 提供精确协议位置。

值语义
XHTTP1_ERROR_ARGUMENT参数非法
XHTTP1_ERROR_HEAD_INCOMPLETEHeadIncomplete失败
XHTTP1_ERROR_HEAD_TOO_LARGEHeadTooLarge失败
XHTTP1_ERROR_START_LINE_TOO_LARGE失败
XHTTP1_ERROR_FIELD_LINE_TOO_LARGE失败
XHTTP1_ERROR_TOO_MANY_FIELDSTOOMANY字段
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_NAMEFIELD名称
XHTTP1_ERROR_FIELD_VALUEFIELD值非法
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_SIZECHUNK尺寸
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升级语法非法
typedef enum xhttp1error { XHTTP1_ERROR_ARGUMENT = 1, XHTTP1_ERROR_HEAD_INCOMPLETE, XHTTP1_ERROR_HEAD_TOO_LARGE, XHTTP1_ERROR_START_LINE_TOO_LARGE, XHTTP1_ERROR_FIELD_LINE_TOO_LARGE, XHTTP1_ERROR_TOO_MANY_FIELDS, 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, XHTTP1_ERROR_FIELD_VALUE, XHTTP1_ERROR_CONTENT_LENGTH, XHTTP1_ERROR_CONFLICTING_CONTENT_LENGTH, XHTTP1_ERROR_TRANSFER_LENGTH, XHTTP1_ERROR_TRANSFER_ENCODING, XHTTP1_ERROR_UNSUPPORTED_TRANSFER_ENCODING, 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, 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 } xhttp1error;

xhttp1limits类型

默认限额面向公网协议输入,调用方可以按服务端路由或客户端策略收紧。

字段类型语义
MaxHeadsize_tMaxHead
MaxStartLinesize_tMaxStartLine
MaxFieldLinesize_tMaxFieldLine
MaxFieldssize_tMaxFields
typedef struct xhttp1limits { size_t MaxHead; size_t MaxStartLine; size_t MaxFieldLine; size_t MaxFields; } xhttp1limits;

xhttp1errorinfo类型

解析错误位置从消息首字节开始计数,Line 从一开始计数。

字段类型语义
Codexhttp1error错误码
Offsetsize_t偏移量
Linesize_t行号
typedef struct xhttp1errorinfo { xhttp1error Code; size_t Offset; size_t Line; } xhttp1errorinfo;

xhttp1transfercoding类型

Transfer Coding 名称和原样参数都借用字段值,Parameters 不含首个分号。

字段类型语义
Namexstrview名称
ParametersxstrviewParameters
typedef struct xhttp1transfercoding { xstrview Name; xstrview Parameters; } xhttp1transfercoding;

xhttp1head类型

Head 只借用输入和字段数组;输入与数组必须覆盖 Head 的使用期。 FIELDS 状态下 FieldCount 是需要的描述符数量,其余字段已经可读取。

字段类型语义
Kindxhttpkind错误种类
Versionxhttpversion结构版本
Flagsuint32标志位
Statusuint16状态输出
ContentLengthuint64ContentLength
Bytessize_tBytes
Methodxstrview方法
Targetxstrview目标视图
Reasonxstrview原因文本
Fieldsxhttpfield*Fields
FieldCountsize_tFieldCount
FieldCapacitysize_tFieldCapacity
MethodCodexhttpmethodMethodCode
typedef struct xhttp1head { xhttpkind Kind; xhttpversion Version; uint32 Flags; uint16 Status; uint64 ContentLength; size_t Bytes; xstrview Method; xstrview Target; xstrview Reason; xhttpfield* Fields; size_t FieldCount; size_t FieldCapacity; xhttpmethod MethodCode; } xhttp1head;

xhttp1bodymode类型

Body Plan 明确区分无正文、定长、分块、关闭定界和升级后的非 HTTP 字节。

值语义
XHTTP1_BODY_NONE无
XHTTP1_BODY_FIXEDFIXED
XHTTP1_BODY_CHUNKEDCHUNKED
XHTTP1_BODY_CLOSECLOSE
XHTTP1_BODY_TUNNEL升级后的非 HTTP 字节流
typedef enum xhttp1bodymode { XHTTP1_BODY_NONE = 0, XHTTP1_BODY_FIXED, XHTTP1_BODY_CHUNKED, XHTTP1_BODY_CLOSE, XHTTP1_BODY_TUNNEL } xhttp1bodymode;

xhttp1bodystatus类型

Body Reader 每次只发布一个借用数据片段或一个终态。

值语义
XHTTP1_BODY_ERROR失败
XHTTP1_BODY_MORE需要更多输入
XHTTP1_BODY_DATA数据损坏
XHTTP1_BODY_DONE完成
XHTTP1_BODY_FIELDS字段体形态
typedef enum xhttp1bodystatus { XHTTP1_BODY_ERROR = -1, XHTTP1_BODY_MORE = 0, XHTTP1_BODY_DATA = 1, XHTTP1_BODY_DONE = 2, XHTTP1_BODY_FIELDS = 3 } xhttp1bodystatus;

xhttp1bodyplan类型

Body Plan 是 Header 事实结合请求方法和响应状态后的唯一分帧结论。

字段类型语义
Modexhttp1bodymode模式
Lengthuint64长度
typedef struct xhttp1bodyplan { xhttp1bodymode Mode; uint64 Length; } xhttp1bodyplan;

xhttp1bodylimits类型

流式正文不预分配内存;限额约束累计正文、chunk 行和 trailer 区。

字段类型语义
MaxBodyuint64MaxBody
MaxChunkLinesize_tMaxChunkLine
MaxTrailersize_tMaxTrailer
MaxTrailerLinesize_tMaxTrailerLine
MaxTrailerssize_tMaxTrailers
typedef struct xhttp1bodylimits { uint64 MaxBody; size_t MaxChunkLine; size_t MaxTrailer; size_t MaxTrailerLine; size_t MaxTrailers; } xhttp1bodylimits;

xhttp1body类型

Body Reader 由调用方持有且不分配内存;Trailers 借用完成调用中的输入。 公开计数可用于进度与诊断,其余状态只能由本模块推进。

字段类型语义
Modexhttp1bodymode模式
Remaininguint64Remaining
Receiveduint64Received
WireBytesuint64WireBytes
Trailersxhttpfield*Trailers
TrailerCountsize_tTrailerCount
TrailerCapacitysize_tTrailerCapacity
Limitsxhttp1bodylimitsLimits
ChunkSizeuint64ChunkSize
ChunkLineBytessize_tChunkLineBytes
Stateuint32状态
typedef struct xhttp1body { xhttp1bodymode Mode; uint64 Remaining; uint64 Received; uint64 WireBytes; xhttpfield* Trailers; size_t TrailerCount; size_t TrailerCapacity; xhttp1bodylimits Limits; uint64 ChunkSize; size_t ChunkLineBytes; uint32 State; } xhttp1body;

xhttp1message类型

完整消息便利层借用连续输入、Header 和 trailer 描述符,不持有堆内存。 Wire 只覆盖第一条完整消息,BodyBytes 是移除 chunked 分帧后的正文长度。

字段类型语义
Headxhttp1head头指针
Planxhttp1bodyplanPlan
Limitsxhttp1bodylimitsLimits
WirexbytesviewWire
Trailersxhttpfield*Trailers
TrailerCountsize_tTrailerCount
TrailerCapacitysize_tTrailerCapacity
BodyBytessize_tBodyBytes
typedef struct xhttp1message { xhttp1head Head; xhttp1bodyplan Plan; xhttp1bodylimits Limits; xbytesview Wire; xhttpfield* Trailers; size_t TrailerCount; size_t TrailerCapacity; size_t BodyBytes; } xhttp1message;
HTTP/1 起始行与 Header

xrtHttp1TargetValid函数

验证非空 request-target 不含空白、控制字符或 fragment。

bool xrtHttp1TargetValid(xstrview Target)

参数

参数方向约束说明
Target输入借用目标文本
返回值
返回含义失败时状态
true合法—
false非法纯谓词
错误
  • 无 — 纯谓词

范例已编译验证

http1/head_tour · 目标 · 观察

		xrtHttp1TargetValid(XRT_STR_LITERAL("/a b")) ||

xrtHttp1LimitsInit函数

初始化适合公网输入的限额:8 KiB 起始行、64 KiB Header、100 字段。

void xrtHttp1LimitsInit(xhttp1limits* pLimits)

参数

参数方向约束说明
pLimits输出非空、可未对齐接收限额(解析前复制)
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无

范例已编译验证

http1/head_tour · 限额 · 观察

	xrtHttp1LimitsInit(&Limits);

xrtHttp1HeadInit函数

初始化借用调用方字段数组的空 Head。

void xrtHttp1HeadInit(xhttp1head* pHead, xhttpfield* pFields, size_t iCapacity)

参数

参数方向约束说明
pHead输出非空接收 Head
pFields输入借用存储字段描述符数组
iCapacity输入—数组容量
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无

范例已编译验证

http1/head_tour · 初始化 · 观察

	xrtHttp1HeadInit(&Head, Fields, 8);

xrtHttp1RequestParse函数

严格增量解析 HTTP/1.0 或 HTTP/1.1 请求 Header。

xhttp1status xrtHttp1RequestParse(xbytesview Input, xhttp1head* pHead, const xhttp1limits* pLimits, xhttp1errorinfo* pError)

参数

参数方向约束说明
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。

xhttp1status xrtHttp1ResponseParse(xbytesview Input, xhttp1head* pHead, const xhttp1limits* pLimits, xhttp1errorinfo* pError)

参数

参数方向约束说明
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 初始为零。

xhttpnext xrtHttp1TransferCodingNext(xstrview Value, size_t* pOffset, xhttp1transfercoding* pCoding)

参数

参数方向约束说明
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,未找到返回空指针。

const xhttpfield* xrtHttp1Field(const xhttp1head* pHead, xstrview Name)

参数

参数方向约束说明
pHead输入非空已解析 Head
Name输入借用查找名称
返回值
返回含义失败时状态
非空借用字段地址—
NULL未找到不设错
错误
  • 无 — 未找到是查询结果

范例已编译验证

http1/head_tour · 字段 · 观察

		((pField = xrtHttp1Field(&Head,
			XRT_STR_LITERAL("host"))) == NULL) ||

xrtHttp1RequestWrite函数

校验并写入完整请求 Header;不自动添加 Host 等策略字段。空输出查长度;容量不足不写半个报文。

bool xrtHttp1RequestWrite(xstrview Method, xstrview Target, xhttpversion Version, const xhttpfield* pFields, size_t iFieldCount, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
Method输入借用方法
Target输入借用目标
Version输入—HTTP 版本
pFields输入借用数组字段
iFieldCount输入—字段数
pOutput输出可空、不得与输入重叠空+零容量 = 查长度
iCapacity输入—容量
pSize输出可空长度
返回值
返回含义失败时状态
true完整报文已写出—
false校验失败或容量不足输出不变
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • xrt.http1 域错误 — 方法/目标非法
  • XERR_RANGE — 容量不足

范例已编译验证

upgrade · 观察

		) || !xrtHttp1RequestWrite(

xrtHttp1ResponseWrite函数

校验并写入完整响应 Header;不自动添加 Content-Length 或连接策略。Reason 允许为空。

bool xrtHttp1ResponseWrite(xhttpversion Version, uint16 iStatus, xstrview Reason, const xhttpfield* pFields, size_t iFieldCount, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
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
	) ) {
HTTP/1 正文分帧

xrtHttp1BodyLimitsInit函数

初始化无正文预设上限的流式 Body 限额;上层可按路由收紧。

void xrtHttp1BodyLimitsInit(xhttp1bodylimits* pLimits)

参数

参数方向约束说明
pLimits输出非空、可未对齐接收限额(Init 时复制)
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无

范例已编译验证

http/http1_body · 限额 · 观察

	xrtHttp1BodyLimitsInit(&Limits);

xrtHttp1RequestBodyPlan函数

按 RFC 9112 请求分帧优先级生成 Body Plan。

bool xrtHttp1RequestBodyPlan(const xhttp1head* pHead, xhttp1bodyplan* pPlan)

参数

参数方向约束说明
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 必须传入原请求方法。

bool xrtHttp1ResponseBodyPlan(const xhttp1head* pHead, xstrview RequestMethod, xhttp1bodyplan* pPlan)

参数

参数方向约束说明
pHead输入非空、已完整解析响应 Head
RequestMethod输入借用原请求方法
pPlan输出非空接收分帧计划
返回值
返回含义失败时状态
true计划已生成—
false分帧字段矛盾输出不变
错误
  • xrt.http1 域错误

范例已编译验证

http/http1_body · 响应分帧 · 观察

	if ( !xrtHttp1ResponseBodyPlan(
		&Head, XRT_STR_LITERAL("GET"), &Plan
	) ) {

xrtHttp1BodyInit函数

初始化无分配 Body Reader;trailer 描述符可为空并在 FIELDS 后重新绑定。

bool xrtHttp1BodyInit(xhttp1body* pBody, const xhttp1bodyplan* pPlan, xhttpfield* pTrailers, size_t iTrailerCapacity, const xhttp1bodylimits* pLimits)

参数

参数方向约束说明
pBody输出非空接收 Reader
pPlan输入已生成分帧计划
pTrailers输入可空trailer 描述符存储
iTrailerCapacity输入—trailer 容量
pLimits输入允许空空 = BodyLimitsInit
返回值
返回含义失败时状态
trueReader 已就绪—
false参数错误XERR_ARGUMENT
错误
  • XERR_ARGUMENT — 指针为空或视图非法

范例已编译验证

http/http1_body · Reader · 观察

	if ( !xrtHttp1BodyInit(
		&Body, &Plan, Trailers, 4, &Limits
	) ) {

xrtHttp1BodyTrailers函数

在 FIELDS 状态后替换 trailer 描述符存储,不重置正文解码进度。

bool xrtHttp1BodyTrailers(xhttp1body* pBody, xhttpfield* pTrailers, size_t iCapacity)

参数

参数方向约束说明
pBody输入/输出非空Reader
pTrailers输入非空新存储
iCapacity输入—容量
返回值
返回含义失败时状态
true已重绑—
false状态非 FIELDS 或参数错误进度不变
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • XERR_STATE — 当前状态不可重绑

范例已编译验证

http1/head_tour · trailer · 观察

			!xrtHttp1BodyTrailers(&Body, Trailers, 4u) ) {

xrtHttp1TrailersParse函数

严格解析从第一行开始并由空行结束的 trailer 区;所有字段均借用 Input。

xhttp1status xrtHttp1TrailersParse(xbytesview Input, xhttpfield* pFields, size_t iCapacity, const xhttp1bodylimits* pLimits, size_t* pBytes, size_t* pCount, xhttp1errorinfo* pError)

参数

参数方向约束说明
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 行,正文可向量发送零复制。

bool xrtHttp1ChunkLineWrite(uint64 iSize, xstrview Extensions, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
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;空正文是成功空操作,不结束消息。

bool xrtHttp1ChunkWrite(xbytesview Data, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
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。

bool xrtHttp1ChunkEndWrite(const xhttpfield* pTrailers, size_t iTrailerCount, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
pTrailers输入允许空trailer 字段
iTrailerCount输入—条目数
pOutput输出可空空+零容量 = 查长度
iCapacity输入—容量
pSize输出可空长度
返回值
返回含义失败时状态
true结束序列已写出—
false容量不足输出不变
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • XERR_RANGE

范例已编译验证

http/http1_body · 分块 · 观察

	) || !xrtHttp1ChunkEndWrite(

xrtHttp1BodyRead函数

推进正文状态机;Consumed 是本次可移除的线缆字节,Data 仅 DATA 状态有效。定长/分块正文过早结束返回协议错误。

xhttp1bodystatus xrtHttp1BodyRead(xhttp1body* pBody, xbytesview Input, bool bEnd, size_t* pConsumed, xbytesview* pData, xhttp1errorinfo* pError)

参数

参数方向约束说明
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

范例已编译验证

http/http1_body · 状态机 · 观察

		xhttp1bodystatus Status = xrtHttp1BodyRead(
			&Body,
			(xbytesview){ Message + iOffset, sizeof(Message) - 1u - iOffset },
			false, &iConsumed, &Data, NULL
		);

xrtHttp1BodyDone函数

判断 Reader 是否已经完整消费 HTTP 正文与 trailer。

bool xrtHttp1BodyDone(const xhttp1body* pBody)

参数

参数方向约束说明
pBody输入允许空Reader
返回值
返回含义失败时状态
true已完整消费—
false未完成、失败或参数非法纯查询
错误
  • 无 — 纯查询

范例已编译验证

http/http1_body · 完成 · 观察

	while ( !xrtHttp1BodyDone(&Body) ) {
HTTP/1 完整消息

xrtHttp1MessageInit函数

初始化借用调用方 Header 与 trailer 描述符数组的空完整消息。

void xrtHttp1MessageInit(xhttp1message* pMessage, xhttpfield* pFields, size_t iFieldCapacity, xhttpfield* pTrailers, size_t iTrailerCapacity)

参数

参数方向约束说明
pMessage输出非空接收消息
pFields输入借用存储Header 数组
iFieldCapacity输入—Header 容量
pTrailers输入借用存储trailer 数组
iTrailerCapacity输入—trailer 容量
返回值
返回含义失败时状态
无纯初始化—
错误
  • 无

范例已编译验证

http/http1_message · 初始化 · 观察

	xrtHttp1MessageInit(&Message, Fields, 8, Trailers, 4);

xrtHttp1RequestMessageParse函数

扫描第一条完整请求;bEnd 表示可靠 EOF,拒绝被截断的 Header 或正文。

xhttp1status xrtHttp1RequestMessageParse(xbytesview Input, bool bEnd, xhttp1message* pMessage, const xhttp1limits* pHeadLimits, const xhttp1bodylimits* pBodyLimits, xhttp1errorinfo* pError)

参数

参数方向约束说明
Input输入借用消息字节
bEnd输入—输入即全部字节
pMessage输出已初始化接收完整消息
pHeadLimits输入允许空Head 限额
pBodyLimits输入允许空Body 限额
pError输出可空错误位置
返回值
返回含义失败时状态
XHTTP1_READY完整消息就绪—
XHTTP1_FIELDS头部就绪(还差消息体)—
XHTTP1_MORE需要更多输入—
XHTTP1_ERROR失败—
错误
  • xrt.http1 域错误 — 截断(bEnd 下 MORE 升级为错误)或协议错误

范例已编译验证

http1/head_tour · 完整解析 · 观察

	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 和普通响应分帧。

xhttp1status xrtHttp1ResponseMessageParse(xbytesview Input, bool bEnd, xstrview RequestMethod, xhttp1message* pMessage, const xhttp1limits* pHeadLimits, const xhttp1bodylimits* pBodyLimits, xhttp1errorinfo* pError)

参数

参数方向约束说明
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 或空正文返回空视图。

xbytesview xrtHttp1MessageBodyView(const xhttp1message* pMessage)

参数

参数方向约束说明
pMessage输入非空完整消息
返回值
返回含义失败时状态
非空借用正文视图—
空视图chunked/空正文(应改用 BodyCopy)纯查询
错误
  • 无 — 纯查询

范例已编译验证

http1/head_tour · 正文 · 观察

		((View = xrtHttp1MessageBodyView(&Message)).Size != 2u) ||

xrtHttp1MessageBodyCopy函数

把正文复制到连续输出并移除 chunked 分帧;空输出可精确查询所需长度。

bool xrtHttp1MessageBodyCopy(const xhttp1message* pMessage, void* pOutput, size_t iCapacity, size_t* pSize)

参数

参数方向约束说明
pMessage输入非空完整消息
pOutput输出可空空+零容量 = 查长度
iCapacity输入—容量
pSize输出可空长度
返回值
返回含义失败时状态
true已复制(含去分帧)—
false容量不足或超限输出不变
错误
  • XERR_ARGUMENT — 指针为空或视图非法
  • XERR_RANGE — 容量不足或正文超限

范例已编译验证

http/http1_message · 正文 · 观察

	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见头文件注释