[PATCH] Upstream: avoid closing connection when no client body needed

Justin Li jli.justinli at gmail.com
Mon Mar 7 18:24:26 UTC 2016


Apologies, I referenced a git commit hash in the first sentence, the
corresponding mercurial commit is 5746:35990c69.

On Mon, Mar 7, 2016 at 1:16 PM, Justin Li <jli.justinli at gmail.com> wrote:

> # 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) {
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20160307/f0777eb6/attachment.html>


More information about the nginx-devel mailing list