[PATCH] Upstream: avoid closing connection when no client body needed
Justin Li
jli.justinli at gmail.com
Mon Mar 7 18:16:13 UTC 2016
# HG changeset patch
# User Justin Li <jli.justinli at gmail.com>
# Date 1457369412 18000
# Mon Mar 07 11:50:12 2016 -0500
# Node ID e84a844f3c2634488285fb9677d3254a032440a2
# Parent c5f81dcf97a79576138917501c9a6cc6f53ee930
Upstream: avoid closing connection when no client body needed
Despite 4a75e1a6, it was previously possible for the connection to be closed in
cases where a response body from the upstream should not be sent to the client.
This is due to the conditional in ngx_http_upstream_process_request that may
call ngx_http_upstream_finalize_request in certain cases.
Example configuration:
proxy_cache foo;
proxy_cache_bypass 1;
proxy_no_cache 1;
If a client sends If-None-Match, and the upstream server returns 200 with a
matching ETag, no body should be returned to the client. At the start of
ngx_http_upstream_send_response proxy_no_cache is not yet tested, thus cacheable
is still 1 and downstream_error is set.
However, by the time the downstream_error check is done in process_request,
proxy_no_cache has been tested and cacheable is set to 0. The client connection
is then closed, regardless of keepalive.
The fix is to avoid using the p->downstream_error flag, and instead repurpose
p->downstream_done to indicate the event pipe should be drained. Additionally,
a check is added for this flag in ngx_http_upstream_check_broken_connection to
prevent a 499 if the client validly closes the connection after receiving the
headers.
diff -r c5f81dcf97a7 -r e84a844f3c26 src/event/ngx_event_pipe.c
--- a/src/event/ngx_event_pipe.c Thu Mar 03 21:14:19 2016 +0300
+++ b/src/event/ngx_event_pipe.c Mon Mar 07 11:50:12 2016 -0500
@@ -502,7 +502,7 @@
flushed = 0;
for ( ;; ) {
- if (p->downstream_error) {
+ if (p->downstream_error || p->downstream_done) {
return ngx_event_pipe_drain_chains(p);
}
diff -r c5f81dcf97a7 -r e84a844f3c26 src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c Thu Mar 03 21:14:19 2016 +0300
+++ b/src/http/ngx_http_upstream.c Mon Mar 07 11:50:12 2016 -0500
@@ -1172,6 +1172,10 @@
}
#endif
+ if (u->pipe->downstream_done) {
+ return;
+ }
+
#if (NGX_HAVE_KQUEUE)
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -2697,7 +2701,7 @@
return;
}
- u->pipe->downstream_error = 1;
+ u->pipe->downstream_done = 1;
}
if (r->request_body && r->request_body->temp_file) {
More information about the nginx-devel
mailing list