编程技术分享平台

网站首页 > 技术教程 正文

Nginx之http模块是如何解析http请求的,6个步骤一目了然-02

xnh888 2024-09-08 10:53:08 技术教程 33 ℃ 0 评论

解析http请求:

在解析http请求之前,我们先来复习下http请求包含的各个部分及每个部分的协议格式。

一个http请求一般由 请求行、请求头、请求体、响应行、响应头、响应体 这6个部分组成。

我们就以 local.com/index为例:

1)请求行基本格式:

GET /index HTTP/1.1


2)请求头基本格式:

Host: local.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36

3)响应体基本格式:

// 这里比较多 先省略


4)响应行基本格式:

HTTP/1.1 200 OK


5)响应头基本格式:

Content-length: 34
Content-type: application/json
Date: Tue, 09 Nov 2021 08:29:33 GMT


6)响应体基本格式:

// 这里比较多 先省略


了解了HTTP请求的基本格式,我们就可以来看请求是如何解析的。

上面说过是从ngx_http_init_connection方法开始处理的。

// 文件名 ngx_http_request.c
void
ngx_http_init_connection(ngx_connection_t *c)
{
    ngx_event_t  *rev;
    rev = c->read;
    rev->handler = ngx_http_wait_request_handler;
    ngx_add_timer(rev, cscf->client_header_timeout);
}


可以看到这里将读事件的回调方法设置成了 ngx_http_wait_request_handler。也就是说建立连接后并没有立刻初始化请求,而是在链接对应的套接字有数据的时候才开始分配。用人话将就是只有当用户发来请求内容时才真正分配内存资源,以达到减少内存资源的浪费。

当我们追到ngx_http_wait_request_handler里的时候发现,这里将读事件回调函数设置为ngx_http_process_request_line方法

// 文件名 ngx_http_request.c
static void
ngx_http_wait_request_handler(ngx_event_t *rev)
{
    rev->handler = ngx_http_process_request_line;
    ngx_http_process_request_line(rev);
}

那么这里为什么多加一行设置成回调?

这是因为http请求的url长度不确定性,内核套接字缓存区未必能接收下整个请求行,因此将读事件的回调方法置为ngx_http_process_request_line。后续epoll事件将调用该方法,直到完整解析请求行。


请求行解析完了就轮到请求头了。那请求头也一样,长度不确定。同理也需要设置回调方法ngx_http_process_request_header(可以看到,读取请求头依然用的是ngx_http_read_request_header方法),

然后调用ngx_http_parse_header_line方法对请求头进行解析,每解析一个请求头就将其放入ngx_http_request_t结构体的headers_in中,并以链表的形式保存。

到此,Nginx已经获取请求行与请求头的全部信息,然后调用ngx_http_process_request_header方法对请求头做简单验证后,就可正式进入请求的处理阶段。


那么Nginx到底是如何处理请求,如何响应的呢?我们明天继续。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表