Understanding "proxy_ignore_client_abort" functionality

Hi,
I’m trying to understand how “proxy_ignore_client_abort” should affect
connection to upstream server once client closes the connection, since
it
seems to behave different than i’m expecting.

I’m using the proxy module, with buffering on and
proxy_ignore_client_abort
on as well (proxy_store off).
For boring and not related reasons, once i start a connection to the
upstream server i don’t want to abort it, even if the client aborted the
connection.

However, even with “proxy_ignore_client_abort” on, once the client
closes
the connection i still see that the upstream connection is closed by
nginx.

I’ve run the scenario with a debugger and i see why this happens. This
is
the flow:

  1. At first, in “ngx_http_upstream_init_request”, if
    “proxy_ignore_client_abort” is on, nginx will not check for FIN/RST from
    client:

//-------------------------------------------------------------------------------------------------
if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
r->read_event_handler =
ngx_http_upstream_rd_check_broken_connection;
r->write_event_handler =
ngx_http_upstream_wr_check_broken_connection;
}
//-------------------------------------------------------------------------------------------------

  1. Later on, when reading the body from upstream and writing to
    downstream,
    if client closed the connection the flag “p->downstream_error” is set to

  2. And the part that surprised me - in
    “ngx_http_upstream_process_request”,
    if “downstream_error” flag is set, we also close the connection to
    upstream,
    regardless of the “proxy_ignore_client_abort” config:

//-------------------------------------------------------------------------------------------------
if (p->downstream_error) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
“http upstream downstream error”);

    if (!u->cacheable && !u->store && u->peer.connection) {
        ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
    }
}

//-------------------------------------------------------------------------------------------------

I’d expect the “proxy_ignore_client_abort” flag to be checked in the
“if” in
#3 as well (=don’t close upstream connection if the flag is true).

My first thought was that if the file should not be stored or cached -
there
is no reason to continue the connection to upstream, so that this is by
design. However if that’s the case then proxy_ignore_client_abort is
redundant.

Can you please shed some light on this? is this a bug? is it the desired
behavior? (if so, please explain the reason behind it).

I’m using Nginx ver 1.4.1 (though if i didn’t miss anything it should be
the
same in the latest version).

My location config (simplified) is:

    location ~ "^/fetch/(.*)" {
        proxy_pass http://$1;
        proxy_buffering on;
        proxy_buffers 10 1024k;
        proxy_ignore_client_abort on;
        proxy_max_temp_file_size 0;
        proxy_http_version 1.1;
    }

Thanks in advance,
Shmulik B

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,253026,253026#msg-253026

Hello!

On Tue, Sep 02, 2014 at 12:57:15PM -0400, shmulik wrote:

Hi,
I’m trying to understand how “proxy_ignore_client_abort” should affect
connection to upstream server once client closes the connection, since it
seems to behave different than i’m expecting.

[…]

        ngx_http_upstream_finalize_request(r, u, NGX_ERROR);

redundant.
The proxy_ignore_client_abort flag specifies whether nginx will
monitor possible connection close while waiting for an upstream
server response. If an error occurs while sending a response, the
connection will be closed regardless of the flag, much like if
there where no nginx at all.

Switching proxy_ignore_client_abort to on may be needed in the
following cases I’m aware of:

  • you need to maintain compatibility with clients that half-close
    connections after sending a request;

  • your backend doesn’t check if a connection is closed while
    generating a response (and hence closing the connection by nginx
    will not abort the request processing on the backend), and at the
    same time you want nginx to maintain limit_conn numbers mostly
    matching actual resources used on the backend;

  • your backend does check if a connection is closed, but you don’t
    want this to happen as you code can’t really cope with it.


Maxim D.
http://nginx.org/

Thank you very much for the clarification.

So if i understand correctly, the only way to achieve my original goal,
without modifying the code is to use “proxy_store” - which is actually
for
saving the content to disk, but as a side effect will keep the
connection to
upstream going even if the client closed it.

Is there another alternative i’m missing?

Thanks,
Shmulik B

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,253026,253032#msg-253032