ngx_http_parse_request函数是Nginx解析HTTP请求的核心,基于状态机逐字节解析请求行与头部,零拷贝提取字段,严格遵循RFC 7230,拒绝非法字符与容错,错误时直接返回400。

HTTP请求解析是Nginx处理客户端连接的核心环节,而 ngx_http_parse_request 函数正是这一过程的入口与主干。它不依赖外部库,完全基于状态机(state machine)逐字节解析原始 HTTP 请求行和头部,兼顾性能、健壮性与协议兼容性。理解其设计逻辑,是深入 Nginx 请求生命周期、调试协议异常、甚至定制解析行为的关键。
状态机驱动:用整数变量管理解析进度
Nginx 不用正则或分词器,而是用一个整型变量 r->state 记录当前解析所处阶段(如 sw_start、sw_method、sw_uri 等)。每个状态对应一段紧凑的 switch 分支,对当前字节做最小化判断(是否空格、是否 CR/LF、是否可打印 ASCII),并决定是否推进状态、保存字段起止位置、或触发错误。
- 状态迁移只依赖当前字节和当前状态,无回溯、无缓存预读,内存友好
- 所有字段(method、uri、http version、header name/value)均以指针+长度方式记录(
ngx_str_t),避免拷贝 - 非法字符、超长行、缺失空格等场景在状态跳转中直接捕获,返回
NGX_HTTP_PARSE_INVALID_REQUEST
请求行解析:三段式校验与零拷贝提取
函数首先解析形如 GET /path HTTP/1.1 的请求行,严格按 RFC 7230 要求验证格式:
-
Method:仅接受大写字母组成的标准方法(GET/HEAD/POST…),长度限制在
NGX_HTTP_MAX_METHOD_NAME(默认 64)内 - URI:允许 URL 编码字符,但拒绝控制字符、空字节;不自动解码,交由后续模块处理
-
Version:必须为
HTTP/1.0或HTTP/1.1(大小写敏感),其余版本视为非法
解析完成后,r->method、r->uri、r->http_version 等字段直接指向原始缓冲区中的相应子串,真正零拷贝。
请求头解析:边读边建链表,支持多行与重复字段
进入头部解析后,状态机转入 sw_header_first_name 等状态,逐字节识别 header name 和 value:
- Header name 以冒号结束,自动跳过前导空格;value 允许跨行(LWS:linear white space),即换行后缩进视为续行
- 每个完整 header 被构造成
ngx_table_elt_t结构体,插入r->headers_in.headers链表 - 同名 header(如多个
Cookie)默认保留全部,不合并(除非模块显式调用ngx_list_push后再合并) - 遇到空行(
\r\n\r\n或\n\n)即判定头部结束,返回NGX_OK
错误与边界处理:静默失败与可控终止
状态机对异常极为敏感,但错误处理策略务实:
- 超长请求行(>
NGX_MAX_MEM_SIZE)或头部(>NGX_HTTP_LARGE_HEADER_BUFFER)直接返回 400 - 遇到不可见控制字符(除 SP、HT、CR、LF 外)立即中断,防止协议混淆或安全绕过
- 不尝试“容错修复”,如错误版本字符串
HTTP/1.x或 method 小写,一律拒收——这是 Nginx 坚持协议严格性的体现 - 整个解析过程可被中断(如读事件暂不可用),
r->state和已解析偏移量被保留,下次继续
掌握 ngx_http_parse_request 的状态流转与字段提取逻辑,等于握住了 Nginx HTTP 解析层的源代码钥匙。它不炫技,但每一行都在为高性能与协议正确性服务。










