|
@@ -0,0 +1,6091 @@
+# HG changeset patch
+# User Valentin Bartenev <vbart@nginx.com>
+# Date 1363008869 -14400
+# Node ID c42b6ba37f33ea3f1ae2d1e2c67a3f7d5c0f3d52
+# Parent e0553ed7d9097bba14c70bbe33f847721fffbcfa
+Create request object only after the first byte was received.
+
+Previously, we always created an object and logged 400 (Bad Request)
+in access log if a client closed connection without sending any data.
+Such a connection was counted as "reading".
+
+Since it's common for modern browsers to behave like this, it's no
+longer considered an error if a client closes connection without
+sending any data, and such a connection will be counted as "waiting".
+
+Now, we do not log 400 (Bad Request) and keep memory footprint as
+small as possible.
+
+diff -r e0553ed7d909 -r c42b6ba37f33 src/http/ngx_http_request.c
+--- a/src/http/ngx_http_request.c Tue Mar 05 14:36:20 2013 +0000
++++ b/src/http/ngx_http_request.c Mon Mar 11 17:34:29 2013 +0400
+@@ -10,6 +10,7 @@
+ #include <ngx_http.h>
+
+
++static void ngx_http_wait_request_handler(ngx_event_t *ev);
+ static void ngx_http_init_request(ngx_event_t *ev);
+ static void ngx_http_process_request_line(ngx_event_t *rev);
+ static void ngx_http_process_request_headers(ngx_event_t *rev);
+@@ -308,12 +309,12 @@ ngx_http_init_connection(ngx_connection_
+ c->log->connection = c->number;
+ c->log->handler = ngx_http_log_error;
+ c->log->data = ctx;
+- c->log->action = "reading client request line";
++ c->log->action = "waiting for request";
+
+ c->log_error = NGX_ERROR_INFO;
+
+ rev = c->read;
+- rev->handler = ngx_http_init_request;
++ rev->handler = ngx_http_wait_request_handler;
+ c->write->handler = ngx_http_empty_handler;
+
+ #if (NGX_HTTP_SSL)
+@@ -363,6 +364,99 @@ ngx_http_init_connection(ngx_connection_
+
+
+ static void
++ngx_http_wait_request_handler(ngx_event_t *rev)
++{
++ 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;
++ }
++
++ 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;
++ }
++
++ n = c->recv(c, b->last, size);
++
++ if (n == NGX_AGAIN) {
++
++ if (!rev->timer_set) {
++ ngx_add_timer(rev, c->listening->post_accept_timeout);
++ }
++
++ 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, ngx_socket_errno,
++ "client closed connection");
++ ngx_http_close_connection(c);
++ return;
++ }
++
++ b->last += n;
++
++ c->log->action = "reading client request line";
++
++ ngx_http_init_request(rev);
++}
++
++
++static void
+ ngx_http_init_request(ngx_event_t *rev)
+ {
+ ngx_pool_t *pool;
+@@ -377,13 +471,6 @@ ngx_http_init_request(ngx_event_t *rev)
+
+ c = rev->data;
+
+- if (rev->timedout) {
+- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
+-
+- ngx_http_close_connection(c);
+- return;
+- }
+-
+ c->requests++;
+
+ hc = c->data;
+@@ -425,16 +512,6 @@ ngx_http_init_request(ngx_event_t *rev)
+
+ ngx_http_set_connection_log(r->connection, clcf->error_log);
+
+- if (c->buffer == NULL) {
+- c->buffer = ngx_create_temp_buf(c->pool,
+- cscf->client_header_buffer_size);
+- if (c->buffer == NULL) {
+- ngx_destroy_pool(r->pool);
+- ngx_http_close_connection(c);
+- return;
+- }
+- }
+-
+ r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
+
+ if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
+@@ -592,10 +669,10 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
+
+- c->log->action = "reading client request line";
+-
+- rev->handler = ngx_http_init_request;
+- ngx_http_init_request(rev);
++ c->log->action = "waiting for request";
++
++ rev->handler = ngx_http_wait_request_handler;
++ ngx_http_wait_request_handler(rev);
+
+ return;
+ }
+@@ -620,12 +697,12 @@ ngx_http_ssl_handshake_handler(ngx_conne
+
+ c->ssl->no_wait_shutdown = 1;
+
+- c->log->action = "reading client request line";
+-
+- c->read->handler = ngx_http_init_request;
++ c->log->action = "waiting for request";
++
|