版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hz5034/article/details/81055155
ngx_http_process_request_line()
static void
ngx_http_process_request_line(ngx_event_t *rev)
{
ssize_t n;
ngx_int_t rc, rv;
ngx_str_t host;
ngx_connection_t *c;
ngx_http_request_t *r;
c = rev->data; // 当前事件对应的连接
r = c->data; // 当前连接对应的请求
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http process request line");
// 若当前读事件已经超时
if (rev->timedout) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
c->timedout = 1; // 设置当前连接的超时标志位为1
ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
return;
}
// NGX_AGAIN表示接收缓冲区header_in中没有未解析的数据
rc = NGX_AGAIN;
for ( ;; ) {
// 若header_in中没有未解析的数据
if (rc == NGX_AGAIN) {
// 把内核套接字缓冲区的数据复制到header_in中
n = ngx_http_read_request_header(r);
// NGX_AGAIN表示若需要继续接收数据,NGX_ERROR表示客户端关闭连接或连接错误
if (n == NGX_AGAIN || n == NGX_ERROR) {
return;
}
}
// 若header_in中有未解析的数据,用状态机解析数据
rc = ngx_http_parse_request_line(r, r->header_in);
// 若请求行被正确解析
if (rc == NGX_OK) {
/* the request line has been parsed successfully */
r->request_line.len = r->request_end - r->request_start;
r->request_line.data = r->request_start;
r->request_length = r->header_in->pos - r->request_start;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http request line: \"%V\"", &r->request_line);
r->method_name.len = r->method_end - r->request_start + 1;
r->method_name.data = r->request_line.data;
if (r->http_protocol.data) {
r->http_protocol.len = r->request_end - r->http_protocol.data;
}
if (ngx_http_process_request_uri(r) != NGX_OK) {
return;
}
if (r->host_start && r->host_end) {
host.len = r->host_end - r->host_start;
host.data = r->host_start;
rc = ngx_http_validate_host(&host, r->pool, 0);
if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent invalid host in request line");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
if (rc == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
return;
}
r->headers_in.server = host;
}
if (r->http_version < NGX_HTTP_VERSION_10) {
if (r->headers_in.server.len == 0
&& ngx_http_set_virtual_server(r, &r->headers_in.server)
== NGX_ERROR)
{
return;
}
ngx_http_process_request(r);
return;
}
// 初始化链表,为接收http请求头做好准备
if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
sizeof(ngx_table_elt_t))
!= NGX_OK)
{
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
c->log->action = "reading client request headers";
// 修改当前连接的读事件的回调函数为ngx_http_process_request_headers()并调用该函数
rev->handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev);
return;
}
// 若ngx_http_parse_request_line()返回错误
if (rc != NGX_AGAIN) {
/* there was error while a request line parsing */
ngx_log_error(NGX_LOG_INFO, c->log, 0,
ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
/* NGX_AGAIN: a request line parsing is still incomplete */
// 若ngx_http_parse_request_line()返回NGX_AGAIN,需要判断是缓冲区大小不够,还是已读数据不够
// 若缓冲区已经用尽
if (r->header_in->pos == r->header_in->end) {
// 分配另一块大缓冲区并拷贝之前的数据
rv = ngx_http_alloc_large_header_buffer(r, 1);
if (rv == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
// 若大缓冲区仍然装不下整个请求行
if (rv == NGX_DECLINED) {
r->request_line.len = r->header_in->end - r->request_start;
r->request_line.data = r->request_start;
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent too long URI");
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
return;
}
}
}
}
ngx_http_read_request_header()
static ssize_t
ngx_http_read_request_header(ngx_http_request_t *r)
{
ssize_t n;
ngx_event_t *rev;
ngx_connection_t *c;
ngx_http_core_srv_conf_t *cscf;
c = r->connection; // 当前请求对应的连接
rev = c->read; // 当前连接对应的读事件
n = r->header_in->last - r->header_in->pos;
// 若当前请求的接收缓冲区header_in中有未解析的数据,直接返回
if (n > 0) {
return n;
}
// 若当前读事件已就绪
if (rev->ready) {
// 循环调用recv()将内核套接字缓冲区中的数据复制到header_in中
n = c->recv(c, r->header_in->last,
r->header_in->end - r->header_in->last);
} else {
n = NGX_AGAIN;
}
if (n == NGX_AGAIN) {
if (!rev->timer_set) {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
// 将读事件加入到定时器中
ngx_add_timer(rev, cscf->client_header_timeout);
}
// 将读事件加入到epoll中
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
}
return NGX_AGAIN;
}
// 若客户端关闭连接
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client prematurely closed connection");
}
// 若客户端关闭连接或连接错误
if (n == 0 || n == NGX_ERROR) {
c->error = 1;
c->log->action = "reading client request headers";
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
}
r->header_in->last += n;
return n;
}
ngx_http_process_request_headers()
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) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
c->timedout = 1; // 设置当前连接的超时标志位为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) {
// 分配另一块大缓冲区并拷贝之前的数据
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;
}
}
// 把内核套接字缓冲区的数据复制到header_in中
n = ngx_http_read_request_header(r);
// NGX_AGAIN表示若需要继续接收数据,NGX_ERROR表示客户端关闭连接或连接错误
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);
// 若header_in中有未解析的数据,用状态机解析数据
rc = ngx_http_parse_header_line(r, r->header_in,
cscf->underscores_in_headers);
// 返回NGX_OK,表示解析出了一行请求头
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;
}
/* a header line has been parsed successfully */
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;
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);
}
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;
}
// 返回NGX_HTTP_PARSE_HEADER_DONE,表示解析出了整个请求头
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
/* a whole header has been parsed successfully */
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;
// 设置请求状态为NGX_HTTP_PROCESS_REQUEST_STATE
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
/* ngx_http_process_request_header() {
...
ngx_http_set_virtual_server() {
...
ngx_http_find_virtual_server()
...
}
}
ngx_http_process_request_header()主要做了两个方面的事情:
一是调用ngx_http_find_virtual_server()查找虚拟服务器配置;
二是对一些请求头做一些协议的检查 */
rc = ngx_http_process_request_header(r);
if (rc != NGX_OK) {
return;
}
// 处理http请求
ngx_http_process_request(r);
return;
}
// 返回NGX_AGAIN,表示需要继续接收数据
if (rc == NGX_AGAIN) {
/* a header line parsing is still not complete */
continue;
}
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
// 返回NGX_HTTP_PARSE_INVALID_HEADER,表示请求头解析过程中遇到错误
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent invalid header line");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
}