diff src/http/ngx_http_request_body.c @ 326:9fc4ab6673f9 NGINX_0_6_7

nginx 0.6.7 *) Change: now the paths specified in the "include", "auth_basic_user_file", "perl_modules", "ssl_certificate", "ssl_certificate_key", and "ssl_client_certificate" directives are relative to directory of nginx configuration file nginx.conf, but not to nginx prefix directory. *) Change: the --sysconfdir=PATH option in configure was canceled. *) Change: the special make target "upgrade1" was defined for online upgrade of 0.1.x versions. *) Feature: the "server_name" and "valid_referers" directives support regular expressions. *) Feature: the "server" directive in the "upstream" context supports the "backup" parameter. *) Feature: the ngx_http_perl_module supports the $r->discard_request_body. *) Feature: the "add_header Last-Modified ..." directive changes the "Last-Modified" response header line. *) Bugfix: if an response different than 200 was returned to an request with body and connection went to the keep-alive state after the request, then nginx returned 400 for the next request. *) Bugfix: a segmentation fault occurred in worker process if invalid address was set in the "auth_http" directive. *) Bugfix: now nginx uses default listen backlog value 511 on all platforms except FreeBSD. Thanks to Jiang Hong. *) Bugfix: a worker process may got caught in an endless loop, if an "server" inside "upstream" block was marked as "down"; bug appeared in 0.6.6. *) Bugfix: now Solaris sendfilev() is not used to transfer the client request body to FastCGI-server via the unix domain socket.
author Igor Sysoev <http://sysoev.ru>
date Wed, 15 Aug 2007 00:00:00 +0400
parents fc223117327f
children 5e3b425174f6
line wrap: on
line diff
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -14,8 +14,8 @@ static void ngx_http_read_client_request
 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
 static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r,
     ngx_chain_t *body);
-static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
+static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
 
 
 /*
@@ -425,7 +425,7 @@ ngx_http_write_request_body(ngx_http_req
 
 
 ngx_int_t
-ngx_http_discard_body(ngx_http_request_t *r)
+ngx_http_discard_request_body(ngx_http_request_t *r)
 {
     ssize_t       size;
     ngx_event_t  *rev;
@@ -442,12 +442,12 @@ ngx_http_discard_body(ngx_http_request_t
         ngx_del_timer(rev);
     }
 
-    r->discard_body = 1;
-
     if (r->headers_in.content_length_n <= 0) {
         return NGX_OK;
     }
 
+    r->discard_body = 1;
+
     size = r->header_in->last - r->header_in->pos;
 
     if (size) {
@@ -461,38 +461,87 @@ ngx_http_discard_body(ngx_http_request_t
         }
     }
 
-    r->read_event_handler = ngx_http_read_discarded_body_handler;
+    r->read_event_handler = ngx_http_read_discarded_request_body_handler;
 
     if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    return ngx_http_read_discarded_body(r);
+    (void) ngx_http_read_discarded_request_body(r);
+
+    return NGX_OK;
 }
 
 
 static void
-ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
+ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r)
 {
-    ngx_int_t  rc;
+    ngx_int_t                  rc;
+    ngx_msec_t                 timer;
+    ngx_event_t               *rev;
+    ngx_connection_t          *c;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    c = r->connection;
+    rev = c->read;
 
-    rc = ngx_http_read_discarded_body(r);
+    if (rev->timedout) {
+        c->timedout = 1;
+        c->error = 1;
+        ngx_http_finalize_request(r, 0);
+        return;
+    }
 
-    if (rc == NGX_AGAIN) {
-        if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
-            ngx_http_finalize_request(r, rc);
+    if (r->lingering_time) {
+        timer = r->lingering_time - ngx_time();
+
+        if (timer <= 0) {
+            r->discard_body = 0;
+            ngx_http_finalize_request(r, 0);
             return;
         }
+
+    } else {
+        timer = 0;
+    }
+
+    rc = ngx_http_read_discarded_request_body(r);
+
+    if (rc == NGX_OK) {
+
+        r->discard_body = 0;
+
+        if (r->done) {
+            ngx_http_finalize_request(r, 0);
+        }
+
+        return;
     }
 
-    if (rc != NGX_OK) {
+    /* rc == NGX_AGAIN */
+
+    if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
         ngx_http_finalize_request(r, rc);
+        return;
+    }
+
+    if (timer) {
+
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        timer *= 1000;
+
+        if (timer > clcf->lingering_timeout) {
+            timer = clcf->lingering_timeout;
+        }
+
+        ngx_add_timer(rev, timer);
     }
 }
 
 
 static ngx_int_t
-ngx_http_read_discarded_body(ngx_http_request_t *r)
+ngx_http_read_discarded_request_body(ngx_http_request_t *r)
 {
     size_t   size;
     ssize_t  n;
@@ -501,33 +550,30 @@ ngx_http_read_discarded_body(ngx_http_re
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http read discarded body");
 
-    if (r->headers_in.content_length_n == 0) {
-        return NGX_OK;
-    }
+    do {
+        if (r->headers_in.content_length_n == 0) {
+            r->read_event_handler = ngx_http_block_reading;
+            return NGX_OK;
+        }
 
-    size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ?
-                NGX_HTTP_DISCARD_BUFFER_SIZE:
-                (size_t) r->headers_in.content_length_n;
+        size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ?
+                   NGX_HTTP_DISCARD_BUFFER_SIZE:
+                   (size_t) r->headers_in.content_length_n;
 
-    n = r->connection->recv(r->connection, buffer, size);
-
-    if (n == NGX_ERROR) {
-
-        r->connection->error = 1;
+        n = r->connection->recv(r->connection, buffer, size);
 
-        /*
-         * if a client request body is discarded then we already set
-         * some HTTP response code for client and we can ignore the error
-         */
-
-        return NGX_OK;
-    }
+        if (n == NGX_ERROR) {
+            r->connection->error = 1;
+            return NGX_OK;
+        }
 
-    if (n == NGX_AGAIN) {
-        return NGX_AGAIN;
-    }
+        if (n == NGX_AGAIN) {
+            return NGX_AGAIN;
+        }
 
-    r->headers_in.content_length_n -= n;
+        r->headers_in.content_length_n -= n;
 
-    return NGX_OK;
+    } while (r->connection->read->ready);
+
+    return NGX_AGAIN;
 }