31.Nginx HTTP之请求头解析函数ngx_http_parse_header_line

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, 表明请求头为空, 且遇到了结束的换行符
       
### 解决从上游服务器读取HTTP响应头部时出现问题的方法 当从上游服务器读取HTTP响应头部时遇到问题,通常是因为响应头过大超出了配置的缓冲区大小。为了有效解决问题并确保系统的稳定性和性能,可以采取以下措施: #### 调整 `proxy_buffer_size` 参数 建议设置较大的 `proxy_buffer_size` 来适应可能更大的响应头部。推荐值为 64KB 或者 128KB[^3]。 ```nginx http { ... proxy_buffer_size 128k; } ``` 这一步骤能够防止因响应头部过长而导致错误日志中出现类似 “upstream sent too big header while reading response header”的警告信息。 #### 获取实际响应头大小 通过Nginx变量 `$upstream_bytes_received` 和 `$upstream_response_length` 可以监控每次请求的实际传输量以及整个响应长度,从而更好地理解当前配置是否合理。 ```nginx location /test { set $debug_info "$upstream_bytes_received - $upstream_response_length"; add_header X-Upstream-Info $debug_info always; } ``` 此方法有助于诊断具体场景下的流量情况,并据此调整参数设定。 #### 错误处理机制优化 对于未能成功解析或接收到完整的响应头部的情况,在代码逻辑上应该有相应的异常捕获与重试策略。例如在检测到空行标志着头部结束之后立即调用函数处理响应体;如果发生读取失败,则记录详细的错误信息以便排查原因[^1]。 ```c if (u->state->header_in == line.data) { // 头部结束,处理响应体 ngx_http_upstream_process_body(r); return NGX_OK; } else { // 记录错误日志 ngx_log_error(NGX_LOG_ERR, log, 0, "Failed to parse headers"); } ``` 以上措施综合应用可以帮助有效地应对来自上游服务端返回的大尺寸HTTP响应头部带来的挑战。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值