ngx_http_process_request_headers函数解析

ngx_http_process_request_headers函数被ngx_http_process_request_line函数调用,将请求头逐个放到r->headers_in.headers结构体中。由于不确定请求中一共有多少个header,所以这个函数主要功能也是在for(;;){}循环中完成,一下所有的代码都是在上述循环内部的。主要代码和解析如下:

判断是否超时,如果超时,报错并结束请求。

    if (rev->timedout) {        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;    }

ngx_http_parse_header_line函数解析请求行,如果返回NGX_OK表示成功的解析出来一个header,如果返回NGX_HTTP_PARSE_HEADER_DONE表示所有的header都解析完了,如果返回NGX_AGAIN表示尚有header没有解析完,剩下的返回值说明出错了。

        rc = ngx_http_parse_header_line(r, r->header_in,                                        cscf->underscores_in_headers);        if (rc == NGX_OK) {            r->request_length += r->header_in->pos - r->header_name_start;            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;            }

r->headers_in.headers是一个ngx_list_t结构体,向其添加元素的顺序是先通过ngx_list_push函数返回一个元素,实际上在ngx_list_push中完成了开辟内存的工作,之后再对返回的元素进行赋值。

            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;

r->header_name_end和r->header_name_start两个变量貌似就是专门为了指向每个头的key的开始和结束,其他地方没看到被使用过

            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‘;            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;            }            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);            }

针对某些头,可能又一些处理函数,比如说User-Agent头的处理函数会提取浏览器相关的一些信息

            hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,                               h->lowcase_key, h->key.len);            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);

在一个头全都操作完成之后需要继续解析下一个(如果还有的话)。

            continue;        }

如果所有的header都解析完了,在经过一些简单的判断(ngx_http_process_request_header函数中完成)之后,就进入了正式的请求处理逻辑

    if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
            "http header done");
        r->request_length += r->header_in->pos - r->header_name_start;
        r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
        rc = ngx_http_process_request_header(r);
        if (rc != NGX_OK) {
            return;
        }
        ngx_http_process_request(r);
        return;
    }
时间: 2024-10-18 07:18:34

ngx_http_process_request_headers函数解析的相关文章

ngx_http_process_request_line函数解析

处理请求行,一般的http请求过程中,ngx_http_process_request_line函数被ngx_http_wait_request_handler调用,并且在ngx_http_wait_request_handler中被设置为读事件的回调函数.在连接被accept之后,有数据到达之后会执行ngx_http_create_request函数,之后再有读事件被触发时被调用的回调函数就是ngx_http_process_request_line.主要代码和解析如下. 判断是否超时,如果超

AngularJS指令中的compile与link函数解析

AngularJS指令中的compile与link函数解析 通常大家在使用ng中的指令的时候,用的链接函数最多的是link属性,下面这篇文章将告诉大家complie,pre-link,post-link的用法与区别. 原文地址 angularjs里的指令非常神奇,允许你创建非常语义化以及高度重用的组件,可以理解为web components的先驱者. 网上已经有很多介绍怎么使用指令的文章以及相关书籍,相互比较的话,很少有介绍compile与link的区别,更别说pre-link与post-lin

iOS 基础函数解析 - Foundation Functions Reference

Foundation Functions Reference Framework Foundation/Foundation.h Declared in NSBundle.h NSByteOrder.h NSDecimal.h NSException.h NSObjCRuntime.h NSObject.h NSPathUtilities.h NSRange.h NSZone.h Overview This chapter describes the functions and function

thread.join函数,java多线程中的join函数解析

join函数的作用,是让当前线程等待,直到调用join()的 线程结束或者等到一段时间,我们来看以下代码 1 package mian; 2 3 4 public class simpleplela { 5 static void threadMessage(String message) { 6 String threadName = 7 Thread.currentThread().getName(); 8 9 System.out.println(threadName+" "+m

socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题

Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数据拷贝到发送缓存中发送并得到确认后再返回.但由于发送缓存的存在,表现为:如果发送缓存大小比请求发送的大小要大,那么send函数立即返回,同时向网络中发送数据;否则,send向网络发送缓存中不能容纳的那部分数据,并等待对端确认后再返回(接收端只要将数据收到接收缓存中,就会确认,并不一定要等待应用程序调

BulkLoop例程の初始化函数and重复调度函数の解析

//----------------------------------------------------------------------------- // File: bulkloop.c // Contents: Hooks required to implement USB peripheral function. // // $Archive: /USB/Examples/FX2LP/bulkloop/bulkloop.c $ // $Date: 3/23/05 2:55p $

C++虚函数解析(转载)

虚函数详解第一篇:对象内存模型浅析 C++中的虚函数的内部实现机制到底是怎样的呢? 鉴于涉及到的内容有点多,我将分三篇文章来介绍. 第一篇:对象内存模型浅析,这里我将对对象的内存模型进行简单的实验和总结. 第二篇:继承对象的构造和析构浅析,这里我将对存在继承关系的对象的构造和析构进行简单的实验和总结. 第三篇:虚函数的内部机制浅析,这里我将对虚函数内部的实现机制进行实验总结. 我使用的编译器是VS2008,有不足或者不准确的地方,欢迎大家拍砖(我个人非常迫切的希望得到大家的指正),我会及时修正相

PHP json_decode 函数解析 json 结果为 NULL 的解决方法

在做网站 CMS 模块时,对于模块内容 content 字段,保存的是 json 格式的字符串,所以在后台进行模块内容的编辑操作 ( 取出保存的数据 ) 时,需要用到 json_decode() 函数. 但是在解析的时候,使用 json_decode() 函数解析的结果一直是 NULL,没有出现希望解析成的数组.下面是问题和分析: 1. 当输出 json 字符串时,代码和页面的显示内容分别是: echo $content = $res[0]['con']['content']; 只需要考虑 $c

用函数解析类似于php.ini的配置文件

配置文件可以写成类似于php.ini文件的格式,用parse_ini_file函数解析. 1 > 配置文件格式 [database]host=localhostuser=tianyu 2> 进行解析 <?php    var_dump(parse_ini_file('./test.ini',true));?> 3> 打印结果: array (size=1)   'database' =>      array (size=2)       'host' => st