HTTP 请求行正确处理完成后,针对 HTTP/1.0 及以上版本紧接着要做的就是请求 HEADER 的处理与解析了
/**
 * 用于处理http的header数据
 * 请求头:
 * Host: localhost
 * User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
 * Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
 * Accept-Language: zh-cn,zh;q=0.5
 * Accept-Encoding: gzip, deflate
 *copy from https://techlog.cn/article/list
/*
用于处理http的header数据
    GET /sample.jsp HTTP/1.1
 * 请求头:
 * Host: localhost
 * User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
 * Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
 * Accept-Language: zh-cn,zh;q=0.5
 * Accept-Encoding: gzip, deflate
*/ //解析上面的GET /sample.jsp HTTP/1.1以外的配置
ngx_http_parse_request_line解析请求行, ngx_http_process_request_headers(ngx_http_parse_header_line)解析头部行(请求头部) 
接收包体ngx_http_read_client_request_body
static void
ngx_http_process_request_headers(ngx_event_t *rev)
{
    u_char                     *p;
    size_t                      len;
    ssize_t                     n;
    ngx_int_t                   rc, rv;
    ngx_table_elt_t            *h;
    ngx_connection_t           *c;
    ngx_http_header_t          *hh;
    ngx_http_request_t         *r;
    ngx_http_core_srv_conf_t   *cscf;
    ngx_http_core_main_conf_t  *cmcf;
    c = rev->data;
    r = c->data;
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                   "http process request header line");
    if (rev->timedout) {//如果tcp连接建立后,等了client_header_timeout秒一直没有收到客户端的数据包过来,则关闭连接
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        c->timedout = 1;
        ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
        return;
    }
    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
    rc = NGX_AGAIN;
    for ( ;; ) {
        if (rc == NGX_AGAIN) {
            if (r->header_in->pos == r->header_in->end) {
//说明header_in空间已经用完了,无法继续存储recv的数据,则重新分配大空间-------buf太小,则扩大buf */
                rv = ngx_http_alloc_large_header_buffer(r, 0);
                if (rv == NGX_ERROR) {
                    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                    return;
                }
                if (rv == NGX_DECLINED) {
                    p = r->header_name_start;
                    r->lingering_close = 1;
                    if (p == NULL) {
                        ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                      "client sent too large request");
                        ngx_http_finalize_request(r,
                                            NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
                        return;
                    }
                    len = r->header_in->end - p;
                    if (len > NGX_MAX_ERROR_STR - 300) {
                        len = NGX_MAX_ERROR_STR - 300;
                    }
                    ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                "client sent too long header line: \"%*s...\"",
                                len, r->header_name_start);
                    ngx_http_finalize_request(r,
                                            NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
                    return;
                }
            }
            //这里至少读一次----------读取请求数据 调用方法:os/ngx_recv.c文件夹中的 ngx_unix_recv */
            n = ngx_http_read_request_header(r); //说明内存中的数据还没有读完,需要读完后继续解析
            if (n == NGX_AGAIN || n == NGX_ERROR) {  
                return;
            }
        }
        /* the host header could change the server configuration context */
        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
/* 处理HTTP请求头数据/* 处理HTTP请求头数据 **/
        rc = ngx_http_parse_header_line(r, r->header_in,
                                        cscf->underscores_in_headers);
 /* 处理成功,则继续解析下一个http header数据 */
        if (rc == NGX_OK) {
            r->request_length += r->header_in->pos - r->header_name_start; //request_length增加一行字符长度
            if (r->invalid_header && cscf->ignore_invalid_headers) {
                /* there was error while a header line parsing */
                ngx_log_error(NGX_LOG_INFO, c->log, 0,
                              "client sent invalid header line: \"%*s\"",
                              r->header_end - r->header_name_start,
                              r->header_name_start);
                continue;
            }
            /* a header line has been parsed successfully */
            /* 解析的头不会KEY:VALUE存入到headers_in中 */
            h = ngx_list_push(&r->headers_in.headers);
            if (h == NULL) {
                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                return;
            }
            h->hash = r->header_hash;
            //拷贝name:value中的name到key中,name后面的冒号被用\0替换了
            h->key.len = r->header_name_end - r->header_name_start;
            h->key.data = r->header_name_start;
            h->key.data[h->key.len] = '\0';
            
            //拷贝name:value中的value到value中,value后的换行符被用\0替换了
            h->value.len = r->header_end - r->header_start;
            h->value.data = r->header_start;
            h->value.data[h->value.len] = '\0';
            h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
            if (h->lowcase_key == NULL) {
                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                return;
            }
             //拷贝name:value中的name到key中,包括name后面的冒号
            if (h->key.len == r->lowcase_index) {
                ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
            } else {
                ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
            }
            //见ngx_http_headers_in  //检查解析到的头部key:value中的对应ngx_http_header_t结构,即ngx_http_headers_in中的成员
            hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
                               h->lowcase_key, h->key.len); 
            
            //从ngx_http_headers_in找到与name匹配的字符串,然后只需对应的handler,一般就是把解析出的name:value中的value存放到headers_in成员的headers链表中
            
            //参考ngx_http_headers_in,通过该数组中的回调hander来存储解析到的请求行name:value中的value到headers_in的响应成员中,见ngx_http_process_request_headers
            if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
                return;
            }
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "http header: \"%V: %V\"",
                           &h->key, &h->value); //如果打开调试开关,则name:value可以存到error.log中
            continue; //继续解析下一行
        }
 如果HTTP的header全部处理完*
        if (rc == NGX_HTTP_PARSE_HEADER_DONE) {//如果HTTP的header全部处理
            /* a whole header has been parsed successfully */
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                           "http header done");
            /*
                请求行
                头部行
                空行(这里是\r\n)
                内容
               */
            r->request_length += r->header_in->pos - r->header_name_start;//把空行的\r\n加上
            r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
/* 检查解析后的request header是否符合要求,如果不符合要求,返回NGX_ERROR */
            rc = ngx_http_process_request_header(r);
            if (rc != NGX_OK) {
                return;
            }
/* 请求行和请求头处理完成后,调用ngx_http_process_request,处理HTTP请求body以及响应 */
            ngx_http_process_request(r);
            return;
        }
        if (rc == NGX_AGAIN) {//返回NGX_AGAIN时,表示还需要接收到更多的字符流才能继续解析
            /* a header line parsing is still not complete */
            continue;
        }
        /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
        /*
            当调用ngx_http_parse_header_line方法解析字符串构成的HTTP时,是有可能遇到非法的或者Nginx当前版本不支持的HTTP头部的,
            这时该方法会返回错误,于是调用ngx_http_finalize_request方法,向客户端发送NGX_ HTTP BAD_REQUEST宏对应的400错误码响应。
          */
        ngx_log_error(NGX_LOG_INFO, c->log, 0,
                      "client sent invalid header line: \"%*s\\r...\"",
                      r->header_end - r->header_name_start,
                      r->header_name_start);
        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
        return;
    }
}当 ngx_http_parse_header_line 函数返回 NGX_HTTP_PARSE_HEADER_DONE 意味着所有的 HEADER 指令已经全部解析完成随后就要进入正式的请求处理阶段 ngx_http_process_request 了然而,在进入 ngx_http_process_request 之前,nginx 首先调用 ngx_http_process_request_header 对 HEADER 进行了校验,比如对那些使用 http/1.1 协议但是却没有发送Host头的请求,nginx 给这些请求返回 400 错误。还有 nginx 现在的版本并不支持 chunked 格式的输入,如果某些请求申明自己使用了 chunked 格式的输入(请求带有值为 chunked 的 transfer_encoding 头部),ngx给这些请求返回 错误等等code 411
    http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子
    
    
    










