]> git.kaiwu.me - nginx.git/commitdiff
Upstream: p->downstream_error instead of closing connection.
authorMaxim Dounin <mdounin@mdounin.ru>
Fri, 4 Jul 2014 16:47:16 +0000 (20:47 +0400)
committerMaxim Dounin <mdounin@mdounin.ru>
Fri, 4 Jul 2014 16:47:16 +0000 (20:47 +0400)
Previously, nginx closed client connection in cases when a response body
from upstream was needed to be cached or stored but shouldn't be sent to
the client.  While this is normal for HTTP, it is unacceptable for SPDY.

Fix is to use instead the p->downstream_error flag to prevent nginx from
sending anything downstream.  To make this work, the event pipe code was
modified to properly cache empty responses with the flag set.

src/event/ngx_event_pipe.c
src/http/ngx_http_upstream.c

index eed807d61b82d3c02734c7683559cd3e9f27a104..64fb07bde4207b681d4abd54476fd9bfd36c1f50 100644 (file)
@@ -439,7 +439,11 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
         }
     }
 
-    if (p->cacheable && p->in) {
+    if (p->cacheable && (p->in || p->buf_to_file)) {
+
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                       "pipe write chain");
+
         if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
             return NGX_ABORT;
         }
@@ -515,15 +519,6 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
                 p->in = NULL;
             }
 
-            if (p->cacheable && p->buf_to_file) {
-                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                               "pipe write chain");
-
-                if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
-                    return NGX_ABORT;
-                }
-            }
-
             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
                            "pipe write downstream done");
 
index 20722ac3f44d9814520a5dba9a5ec208f558afe8..012969170a6340081e2b59e739b30902273bd7ee 100644 (file)
@@ -2357,21 +2357,17 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
     if (r->header_only) {
 
-        if (u->cacheable || u->store) {
-
-            if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
-                ngx_connection_error(c, ngx_socket_errno,
-                                     ngx_shutdown_socket_n " failed");
-            }
-
-            r->read_event_handler = ngx_http_request_empty_handler;
-            r->write_event_handler = ngx_http_request_empty_handler;
-            c->error = 1;
+        if (!u->buffering) {
+            ngx_http_upstream_finalize_request(r, u, rc);
+            return;
+        }
 
-        } else {
+        if (!u->cacheable && !u->store) {
             ngx_http_upstream_finalize_request(r, u, rc);
             return;
         }
+
+        u->pipe->downstream_error = 1;
     }
 
     if (r->request_body && r->request_body->temp_file) {