[PATCH] Make ngx_http_upstream provide a way to expose errors after sending out the response header

agentzh agentzh at gmail.com
Sun Apr 7 23:25:11 UTC 2013


Hello!

Here attaches the upstream_truncation V4 patch. Changes since V3 are

* set u->length to -1 in u->input_filter_init in ngx_uwsgi and
ngx_scgi because they do not set u->pipe->length (like ngx_proxy) but
set u->length (via ngx_http_upstream) which causes false positive for
response data truncation.

Maybe a better fix is to copy most of the logic in
ngx_http_proxy_filter_init and ngx_http_proxy_copy_filter to ngx_uwsgi
and ngx_scgi but I'm afraid it may be out of the scope of this patch.

Thanks!
-agentzh

diff --exclude '*~' --exclude '*.swp' -urp
nginx-1.2.7/src/http/modules/ngx_http_scgi_module.c
nginx-1.2.7-patched/src/http/modules/ngx_http_scgi_module.c
--- nginx-1.2.7/src/http/modules/ngx_http_scgi_module.c 2013-02-09
19:08:42.000000000 -0800
+++ nginx-1.2.7-patched/src/http/modules/ngx_http_scgi_module.c
2013-04-07 12:09:55.900492634 -0700
@@ -39,6 +39,7 @@ static ngx_int_t ngx_http_scgi_process_s
 static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
 static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
 static void ngx_http_scgi_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
+static ngx_int_t ngx_http_scgi_input_filter_init(void *data);

 static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf);
 static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
@@ -446,6 +447,8 @@ ngx_http_scgi_handler(ngx_http_request_t
     u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
     u->pipe->input_ctx = r;

+    u->input_filter_init = ngx_http_scgi_input_filter_init;
+
     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -1046,6 +1049,17 @@ ngx_http_scgi_finalize_request(ngx_http_
 }


+static ngx_int_t
+ngx_http_scgi_input_filter_init(void *data)
+{
+    ngx_http_request_t    *r = data;
+
+    r->upstream->length = -1;
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
 {
diff --exclude '*~' --exclude '*.swp' -urp
nginx-1.2.7/src/http/modules/ngx_http_uwsgi_module.c
nginx-1.2.7-patched/src/http/modules/ngx_http_uwsgi_module.c
--- nginx-1.2.7/src/http/modules/ngx_http_uwsgi_module.c 2013-02-09
19:08:42.000000000 -0800
+++ nginx-1.2.7-patched/src/http/modules/ngx_http_uwsgi_module.c
2013-04-07 11:58:24.546915778 -0700
@@ -46,6 +46,7 @@ static ngx_int_t ngx_http_uwsgi_process_
 static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
 static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
     ngx_int_t rc);
+static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);

 static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
 static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
@@ -479,6 +480,8 @@ ngx_http_uwsgi_handler(ngx_http_request_
     u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
     u->pipe->input_ctx = r;

+    u->input_filter_init = ngx_http_uwsgi_input_filter_init;
+
     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -1086,6 +1089,17 @@ ngx_http_uwsgi_finalize_request(ngx_http
 }


+static ngx_int_t
+ngx_http_uwsgi_input_filter_init(void *data)
+{
+    ngx_http_request_t    *r = data;
+
+    r->upstream->length = -1;
+
+    return NGX_OK;
+}
+
+
 static void *
 ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
 {
diff --exclude '*~' --exclude '*.swp' -urp
nginx-1.2.7/src/http/ngx_http_upstream.c
nginx-1.2.7-patched/src/http/ngx_http_upstream.c
--- nginx-1.2.7/src/http/ngx_http_upstream.c 2013-02-11 06:39:49.000000000 -0800
+++ nginx-1.2.7-patched/src/http/ngx_http_upstream.c 2013-04-06
17:16:54.444520038 -0700
@@ -2399,7 +2399,7 @@ ngx_http_upstream_process_non_buffered_u

     if (c->read->timedout) {
         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
-        ngx_http_upstream_finalize_request(r, u, 0);
+        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
         return;
     }

@@ -2446,13 +2446,20 @@ ngx_http_upstream_process_non_buffered_r
             if (u->busy_bufs == NULL) {

                 if (u->length == 0
-                    || upstream->read->eof
-                    || upstream->read->error)
+                    || (upstream->read->eof
+                        && u->length == -1
+                        && u->pipe
+                        && u->pipe->length == -1))
                 {
                     ngx_http_upstream_finalize_request(r, u, 0);
                     return;
                 }

+                if (upstream->read->eof || upstream->read->error) {
+                    ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_BAD_GATEWAY);
+                    return;
+                }
+
                 b->pos = b->start;
                 b->last = b->start;
             }
@@ -2720,7 +2727,9 @@ ngx_http_upstream_process_request(ngx_ht

 #endif

-        if (p->upstream_done || p->upstream_eof || p->upstream_error) {
+        if (p->upstream_done
+            || (p->upstream_eof && u->length == -1 && p->length == -1))
+        {
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                            "http upstream exit: %p", p->out);
 #if 0
@@ -2729,6 +2738,14 @@ ngx_http_upstream_process_request(ngx_ht
             ngx_http_upstream_finalize_request(r, u, 0);
             return;
         }
+
+        if (p->upstream_eof || p->upstream_error) {
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "http upstream exit: %p", p->out);
+
+            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
+            return;
+       }
     }

     if (p->downstream_error) {
@@ -3087,9 +3104,9 @@ ngx_http_upstream_finalize_request(ngx_h

     if (u->header_sent
         && rc != NGX_HTTP_REQUEST_TIME_OUT
-        && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
+        && rc >= NGX_HTTP_SPECIAL_RESPONSE)
     {
-        rc = 0;
+        rc = NGX_ERROR;
     }

     if (rc == NGX_DECLINED) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nginx-1.2.7-upstream_truncation_v4.patch
Type: application/octet-stream
Size: 5564 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130407/8ddcb028/attachment.obj>


More information about the nginx-devel mailing list