HTTP >= 1.0 的版本中,请求行后紧跟的就是请求头了,Nginx使用ngx_http_parse_header_line来对请求头进行解析。
/* 解析HTTP请求头
* param r: 待处理的HTTP请求r
* b: 存放请求头的缓冲区
* return : 解析完请求头的一行时返回NGX_OK;
* 解析完整个请求头时返回NGX_HTTP_PARSE_HEADER_DONE;
* 解析出错时返回NGX_HTTP_PARSE_INVALID_HEADER;
* 其他返回NGX_AGAIN, 表示需要读取新的请求头内容
*/
ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
{
/* HTTP请求头格式, 头部字段名不区分大小写, 值中可以包含空格:
* [头部字段名]:(空格..空格)[值](空格..空格)[回车符][换行符]
* ......
* [头部字段名]:(空格..空格)[值](空格..空格)[回车符][换行符]
* [回车符][换行符]
*/
u_char c, ch, *p;
enum {
sw_start = 0, // 初始状态
sw_name, // 解析请求头字段名
sw_space_before_value, // 解析请求头字段值前的空格
sw_value, // 解析请求头字段值
sw_space_after_value, // 解析请求头字段值后紧跟空格后的空格
sw_almost_done, // 解析标记请求头的行尾的换行符
sw_header_almost_done, // 解析标记请求头结束的换行符
sw_ignore_line, // 忽略请求头前的无用行
sw_done, // 解析完请求头的一行
sw_header_done // 解析完整个请求头
} state; // 枚举类型变量: 请求头解析状态
// 获取HTTP请求r的当前状态state
state = r->state;
// 获取缓冲区b中未解析的有效内容的起始位置p
p = b->pos;
while (p < b->last && state < sw_done) {
// p小于b->last, 表示缓冲区内仍要未解析的有效内容;
// state小于sw_done, 表示对于请求头的某一行仍未解析完毕
// 获取当前待解析的字符ch
ch = *p++;
switch (state) {
case sw_start:
// 当前状态为初始状态
switch (ch) {
case CR:
// 如果当前字符为\r, 表明请求头为空, 且遇到了标记请求头结束的回车符
// 置r->header_end为p-1, 记录请求头在缓冲区中的结束位置
r->header_end = p - 1;
// 置state为sw_header_almost_done, 表示解析标记请求头结束的换行符
state = sw_header_almost_done;
break;
case LF:
// 如果当前字符为\n, 表明请求头为空, 且遇到了结束的换行符