HTTP 请求的接收 -- ngx_http_wait_request_handler

2015-10-03 22:18:49   最后更新: 2015-10-03 22:18:49   访问数量:991




对于活跃的 HTTP 连接,在执行连接建立回调函数 ngx_http_init_connection 的过程中会执行 ngx_http_wait_request_handler 回调函数,负责 HTTP 请求的接收与 HTTP 请求描述结构的创建和初始化

 

// static void ngx_http_wait_request_handler(ngx_event_t *rev) // http 请求接收 {{{ static void ngx_http_wait_request_handler(ngx_event_t *rev) { u_char *p; size_t size; ssize_t n; ngx_buf_t *b; ngx_connection_t *c; ngx_http_connection_t *hc; ngx_http_core_srv_conf_t *cscf; c = rev->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler"); // 连接超时 if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_http_close_connection(c); return; } // 连接已关闭 if (c->close) { ngx_http_close_connection(c); return; } hc = c->data; cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); size = cscf->client_header_buffer_size; // 创建并初始化缓冲结构 b = c->buffer; if (b == NULL) { b = ngx_create_temp_buf(c->pool, size); if (b == NULL) { ngx_http_close_connection(c); return; } c->buffer = b; } else if (b->start == NULL) { b->start = ngx_palloc(c->pool, size); if (b->start == NULL) { ngx_http_close_connection(c); return; } b->pos = b->start; b->last = b->start; b->end = b->last + size; } // ngx_unix_recv // 调用 recv 从 TCP 流上读取数据 n = c->recv(c, b->last, size); // 需要重新加入队列 if (n == NGX_AGAIN) { if (!rev->timer_set) { ngx_add_timer(rev, c->listening->post_accept_timeout); ngx_reusable_connection(c, 1); } if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); return; } /* * We are trying to not hold c->buffer's memory for an idle connection. */ if (ngx_pfree(c->pool, b->start) == NGX_OK) { b->start = NULL; } return; } if (n == NGX_ERROR) { ngx_http_close_connection(c); return; } if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); ngx_http_close_connection(c); return; } b->last += n; if (hc->proxy_protocol) { hc->proxy_protocol = 0; p = ngx_proxy_protocol_parse(c, b->pos, b->last); if (p == NULL) { ngx_http_close_connection(c); return; } b->pos = p; if (b->pos == b->last) { c->log->action = "waiting for request"; b->pos = b->start; b->last = b->start; ngx_post_event(rev, &ngx_posted_events); return; } } c->log->action = "reading client request line"; // 从连接池中删除连接 ngx_reusable_connection(c, 0); // 创建 HTTP 请求描述结构 c->data = ngx_http_create_request(c); if (c->data == NULL) { ngx_http_close_connection(c); return; } // 请求处理回调函数 rev->handler = ngx_http_process_request_line; // 解析 HTTP 请求行 ngx_http_process_request_line(rev); } // }}}

 

 

在这个函数中首先创建并初始化了一段缓冲区,并调用 ngx_unix_recv 函数从 TCP 流上将数据读取到 缓冲区中

如果需要重新监听,则把事件重新加入到定时器、把连接重新添加到连接池并退出

否则在这以后,先后调用

  1. ngx_reusable_connection -- 删除连接池中的该连接
  2. ngx_http_create_request -- 创建并初始化 HTTP 请求描述结构
  3. ngx_http_process_request_line -- 解析 HTTP 请求

 

 

 

// struct ngx_http_request_s // HTTP 请求描述结构 {{{ struct ngx_http_request_s { uint32_t signature; /* "HTTP" */ // 请求对应的连接结构 ngx_connection_t *connection; // HTTP 模块上下文 void **ctx; // main 配置 void **main_conf; // server 配置 void **srv_conf; // local 配置 void **loc_conf; // 事件读写回调函数 ngx_http_event_handler_pt read_event_handler; ngx_http_event_handler_pt write_event_handler; #if (NGX_HTTP_CACHE) ngx_http_cache_t *cache; #endif ngx_http_upstream_t *upstream; ngx_array_t *upstream_states; /* of ngx_http_upstream_state_t */ // 内存池 ngx_pool_t *pool; // 保存一些消息体的内容 ngx_buf_t *header_in; // 请求头部描述结构 ngx_http_headers_in_t headers_in; // 响应头部描述结构 ngx_http_headers_out_t headers_out; // 请求体描述结构 ngx_http_request_body_t *request_body; // 请求相关时间戳 time_t lingering_time; time_t start_sec; ngx_msec_t start_msec; ngx_uint_t method; // HTTP 版本 ngx_uint_t http_version; // 请求串 ngx_str_t request_line; // URI ngx_str_t uri; // 参数 ngx_str_t args; // 额外信息 ngx_str_t exten; ngx_str_t unparsed_uri; ngx_str_t method_name; ngx_str_t http_protocol; // 上次还没发完的 buf ngx_chain_t *out; // 当前 request 链中最上面的 request ngx_http_request_t *main; // 当前 request 的父 request ngx_http_request_t *parent; // 缓存父 request 数据(也就是将要发送数据的request) ngx_http_postponed_request_t *postponed; // 保存子请求的 post request,也就是保存了需要被发送的 request ngx_http_post_subrequest_t *post_subrequest; // 所有需要处理的 request 链表,也就是说它即包含子请求也包含父请求 ngx_http_posted_request_t *posted_requests; // 请求处理阶段 ngx_int_t phase_handler; // 生成内容的处理函数 ngx_http_handler_pt content_handler; ngx_uint_t access_code; // 所有变量 ngx_http_variable_value_t *variables; #if (NGX_PCRE) ngx_uint_t ncaptures; int *captures; u_char *captures_data; #endif // 发送限制速率 size_t limit_rate; size_t limit_rate_after; /* used to learn the Apache compatible response length without a header */ // 请求头大小 size_t header_size; // 请求长度 off_t request_length; // 状态 ngx_uint_t err_status; // http 连接结构 ngx_http_connection_t *http_connection; #if (NGX_HTTP_SPDY) ngx_http_spdy_stream_t *spdy_stream; #endif // log 回调 ngx_http_log_handler_pt log_handler; ngx_http_cleanup_t *cleanup; unsigned subrequests:8; unsigned count:8; unsigned blocked:8; unsigned aio:1; unsigned http_state:4; /* URI with "/." and on Win32 with "//" */ unsigned complex_uri:1; /* URI with "%" */ unsigned quoted_uri:1; /* URI with "+" */ unsigned plus_in_uri:1; /* URI with " " */ unsigned space_in_uri:1; // 是否有效 unsigned invalid_header:1; unsigned add_uri_to_alias:1; unsigned valid_location:1; unsigned valid_unparsed_uri:1; unsigned uri_changed:1; unsigned uri_changes:4; unsigned request_body_in_single_buf:1; unsigned request_body_in_file_only:1; unsigned request_body_in_persistent_file:1; unsigned request_body_in_clean_file:1; unsigned request_body_file_group_access:1; unsigned request_body_file_log_level:3; unsigned subrequest_in_memory:1; unsigned waited:1; #if (NGX_HTTP_CACHE) unsigned cached:1; #endif #if (NGX_HTTP_GZIP) unsigned gzip_tested:1; unsigned gzip_ok:1; unsigned gzip_vary:1; #endif unsigned proxy:1; unsigned bypass_cache:1; unsigned no_cache:1; /* * instead of using the request context data in * ngx_http_limit_conn_module and ngx_http_limit_req_module * we use the single bits in the request structure */ unsigned limit_conn_set:1; unsigned limit_req_set:1; #if 0 unsigned cacheable:1; #endif unsigned pipeline:1; unsigned chunked:1; // 只返回 HEADER unsigned header_only:1; unsigned keepalive:1; unsigned lingering_close:1; unsigned discard_body:1; unsigned internal:1; unsigned error_page:1; unsigned filter_finalize:1; unsigned post_action:1; unsigned request_complete:1; unsigned request_output:1; unsigned header_sent:1; unsigned expect_tested:1; unsigned root_tested:1; unsigned done:1; unsigned logged:1; unsigned buffered:4; unsigned main_filter_need_in_memory:1; unsigned filter_need_in_memory:1; unsigned filter_need_temporary:1; unsigned allow_ranges:1; unsigned single_range:1; unsigned disable_not_modified:1; #if (NGX_STAT_STUB) unsigned stat_reading:1; unsigned stat_writing:1; #endif /* used to parse HTTP headers */ ngx_uint_t state; ngx_uint_t header_hash; ngx_uint_t lowcase_index; u_char lowcase_header[NGX_HTTP_LC_HEADER_LEN]; u_char *header_name_start; u_char *header_name_end; u_char *header_start; u_char *header_end; /* * a memory that can be reused after parsing a request line * via ngx_http_ephemeral_t */ u_char *uri_start; u_char *uri_end; u_char *uri_ext; u_char *args_start; u_char *request_start; u_char *request_end; u_char *method_end; u_char *schema_start; u_char *schema_end; u_char *host_start; u_char *host_end; u_char *port_start; u_char *port_end; unsigned http_minor:16; unsigned http_major:16; } // }}};

 

 

这个结构描述了一个 HTTP 请求的全部信息,包括 URI、请求头部、响应头部、请求体等内容

 

其中请求头信息保存在请求头描述结构中:

// struct ngx_http_headers_in_t // 请求头结构 {{{ typedef struct { // 请求头链表,保存所有头信息 ngx_list_t headers; ngx_table_elt_t *host; ngx_table_elt_t *connection; ngx_table_elt_t *if_modified_since; ngx_table_elt_t *if_unmodified_since; ngx_table_elt_t *if_match; ngx_table_elt_t *if_none_match; ngx_table_elt_t *user_agent; ngx_table_elt_t *referer; ngx_table_elt_t *content_length; ngx_table_elt_t *content_type; ngx_table_elt_t *range; ngx_table_elt_t *if_range; ngx_table_elt_t *transfer_encoding; ngx_table_elt_t *expect; ngx_table_elt_t *upgrade; #if (NGX_HTTP_GZIP) ngx_table_elt_t *accept_encoding; ngx_table_elt_t *via; #endif ngx_table_elt_t *authorization; ngx_table_elt_t *keep_alive; #if (NGX_HTTP_X_FORWARDED_FOR) ngx_array_t x_forwarded_for; #endif #if (NGX_HTTP_REALIP) ngx_table_elt_t *x_real_ip; #endif #if (NGX_HTTP_HEADERS) ngx_table_elt_t *accept; ngx_table_elt_t *accept_language; #endif #if (NGX_HTTP_DAV) ngx_table_elt_t *depth; ngx_table_elt_t *destination; ngx_table_elt_t *overwrite; ngx_table_elt_t *date; #endif ngx_str_t user; ngx_str_t passwd; ngx_array_t cookies; ngx_str_t server; off_t content_length_n; time_t keep_alive_n; unsigned connection_type:2; unsigned chunked:1; unsigned msie:1; unsigned msie6:1; unsigned opera:1; unsigned gecko:1; unsigned chrome:1; unsigned safari:1; unsigned konqueror:1; } ngx_http_headers_in_t; // }}}

 

 

响应头信息保存在响应头描述结构中:

// struct ngx_http_headers_out_t // 响应头描述结构 {{{ typedef struct { ngx_list_t headers; ngx_uint_t status; ngx_str_t status_line; ngx_table_elt_t *server; ngx_table_elt_t *date; ngx_table_elt_t *content_length; ngx_table_elt_t *content_encoding; ngx_table_elt_t *location; ngx_table_elt_t *refresh; ngx_table_elt_t *last_modified; ngx_table_elt_t *content_range; ngx_table_elt_t *accept_ranges; ngx_table_elt_t *www_authenticate; ngx_table_elt_t *expires; ngx_table_elt_t *etag; ngx_str_t *override_charset; size_t content_type_len; ngx_str_t content_type; ngx_str_t charset; u_char *content_type_lowcase; ngx_uint_t content_type_hash; ngx_array_t cache_control; off_t content_length_n; time_t date_time; time_t last_modified_time; } ngx_http_headers_out_t; // }}}

 

 

// ngx_http_request_t * ngx_http_create_request(ngx_connection_t *c) // 创建 HTTP 请求结构并初始化 {{{ ngx_http_request_t * ngx_http_create_request(ngx_connection_t *c) { ngx_pool_t *pool; ngx_time_t *tp; ngx_http_request_t *r; ngx_http_log_ctx_t *ctx; ngx_http_connection_t *hc; ngx_http_core_srv_conf_t *cscf; ngx_http_core_loc_conf_t *clcf; ngx_http_core_main_conf_t *cmcf; c->requests++; hc = c->data; cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); pool = ngx_create_pool(cscf->request_pool_size, c->log); if (pool == NULL) { return NULL; } r = ngx_pcalloc(pool, sizeof(ngx_http_request_t)); if (r == NULL) { ngx_destroy_pool(pool); return NULL; } r->pool = pool; r->http_connection = hc; r->signature = NGX_HTTP_MODULE; r->connection = c; r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; r->read_event_handler = ngx_http_block_reading; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_http_set_connection_log(r->connection, clcf->error_log); r->header_in = hc->nbusy ? hc->busy[0] : c->buffer; if (ngx_list_init(&r->headers_out.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { ngx_destroy_pool(r->pool); return NULL; } r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { ngx_destroy_pool(r->pool); return NULL; } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts * sizeof(ngx_http_variable_value_t)); if (r->variables == NULL) { ngx_destroy_pool(r->pool); return NULL; } #if (NGX_HTTP_SSL) if (c->ssl) { r->main_filter_need_in_memory = 1; } #endif r->main = r; r->count = 1; tp = ngx_timeofday(); r->start_sec = tp->sec; r->start_msec = tp->msec; r->method = NGX_HTTP_UNKNOWN; r->http_version = NGX_HTTP_VERSION_10; r->headers_in.content_length_n = -1; r->headers_in.keep_alive_n = -1; r->headers_out.content_length_n = -1; r->headers_out.last_modified_time = -1; r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1; r->http_state = NGX_HTTP_READING_REQUEST_STATE; ctx = c->log->data; ctx->request = r; ctx->current_request = r; r->log_handler = ngx_http_log_error_handler; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); r->stat_reading = 1; (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif return r; } // }}}

 

 






读书笔记      nginx      源码阅读      源码      ngx_http_wait_request_handler     


京ICP备15018585号