[nginx] svn commit: r5102 - trunk/src/http

vbart at nginx.com vbart at nginx.com
Thu Mar 7 17:21:51 UTC 2013


Author: vbart
Date: 2013-03-07 17:21:50 +0000 (Thu, 07 Mar 2013)
New Revision: 5102
URL: http://trac.nginx.org/nginx/changeset/5102/nginx

Log:
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.


Modified:
   trunk/src/http/ngx_http_request.c

Modified: trunk/src/http/ngx_http_request.c
===================================================================
--- trunk/src/http/ngx_http_request.c	2013-03-07 17:07:04 UTC (rev 5101)
+++ trunk/src/http/ngx_http_request.c	2013-03-07 17:21:50 UTC (rev 5102)
@@ -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 @@
     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 @@
 
 
 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 @@
 
     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_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_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
 
-        c->log->action = "reading client request line";
+        c->log->action = "waiting for request";
 
-        rev->handler = ngx_http_init_request;
-        ngx_http_init_request(rev);
+        rev->handler = ngx_http_wait_request_handler;
+        ngx_http_wait_request_handler(rev);
 
         return;
     }
@@ -620,12 +697,12 @@
 
         c->ssl->no_wait_shutdown = 1;
 
-        c->log->action = "reading client request line";
+        c->log->action = "waiting for request";
 
-        c->read->handler = ngx_http_init_request;
+        c->read->handler = ngx_http_wait_request_handler;
         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
 
-        ngx_http_init_request(c->read);
+        ngx_http_wait_request_handler(c->read);
 
         return;
     }



More information about the nginx-devel mailing list