日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Nginx >内容正文

Nginx

Nginx源码阅读(ngx_http_process_request_line)

發布時間:2024/2/28 Nginx 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx源码阅读(ngx_http_process_request_line) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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; // 設置當前連接的超時標志位為1ngx_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; // 設置當前連接的超時標志位為1ngx_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_STATEr->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;} }


---------------------?
作者:hz5034?
來源:CSDN?
原文:https://blog.csdn.net/hz5034/article/details/81055155?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

總結

以上是生活随笔為你收集整理的Nginx源码阅读(ngx_http_process_request_line)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。