Opened 11 years ago

Closed 10 years ago

#428 closed defect (fixed)

SPDY and Proxy Cache prematurely closes connections

Reported by: Phil Sweeney Owned by: Valentin V. Bartenev
Priority: major Milestone:
Component: nginx-core Version:
Keywords: spdy proxy cache Cc:
uname -a: Linux myserver 3.8.0-31-generic #46~precise1-Ubuntu SMP Wed Sep 11 18:21:16 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.5.6
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/ --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_spdy_module --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --with-ipv6


As originally reported via mailing list/forum (a while ago):,233497,241193#msg-241193

When SPDY and proxy cache are both being used, nginx will prematurely close the connection to avoid sending the body to the client. However with SPDY, there could be other items still to send, so this causes empty responses. In my case, css/js/images come back empty to the browser occasionally.

Debug logs have been provided to Valentin V. Bartenev, who stated in April:

"Well, from what I've examined from your debug logs, it looks like a known feature of caching mechanism, that closes connection to prevent sending body to a client, while the whole response is receiving from upstream. It's not a big deal in http, but turns into serious issue with spdy."

"The problem appears when the whole page is requested from upstream for caching purposes, but the client should not get its body (i.e. 304 response, or HEAD request)."

Didn't originally file a ticket here because Valentin hoped that rewrites going on at the time for the upstream code might fix this, but looks like it did not.

Change History (11)

comment:1 by Valentin V. Bartenev, 11 years ago

Owner: set to Valentin V. Bartenev
Status: newassigned

comment:2 by Valentin V. Bartenev, 10 years ago

This patch should fix the problem:

  • src/http/ngx_http_upstream.c

    diff -r 01e2a5bcdd8f src/http/ngx_http_upstream.c
    a b static void  
    6666static void
    6767    ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
    6868    ngx_uint_t do_write);
     69static ngx_int_t ngx_http_upstream_output_filter(ngx_http_request_t *r,
     70    ngx_chain_t *in);
    6971static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
    7072static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
    7173    ssize_t bytes);
    22172219    c = r->connection;
    2219     if (r->header_only) {
    2221         if (u->cacheable || u->store) {
    2223             if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
    2224                 ngx_connection_error(c, ngx_socket_errno,
    2225                                      ngx_shutdown_socket_n " failed");
    2226             }
    2228             r->read_event_handler = ngx_http_request_empty_handler;
    2229             r->write_event_handler = ngx_http_request_empty_handler;
    2230             c->error = 1;
    2232         } else {
    2233             ngx_http_upstream_finalize_request(r, u, rc);
    2234             return;
    2235         }
     2221    if (r->header_only && !(u->cacheable || u->store)) {
     2222        ngx_http_upstream_finalize_request(r, u, rc);
     2223        return;
    22362224    }
    22382226    if (r->request_body && r->request_body->temp_file) {
    23852373    p = u->pipe;
    2387     p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter;
     2375    p->output_filter =
     2376        (ngx_event_pipe_output_filter_pt) ngx_http_upstream_output_filter;
    23882378    p->output_ctx = r;
    23892379    p->tag = u->output.tag;
    23902380    p->bufs = u->conf->bufs;
    28432833        if (do_write) {
    28452835            if (u->out_bufs || u->busy_bufs) {
    2846                 rc = ngx_http_output_filter(r, u->out_bufs);
     2836                rc = ngx_http_upstream_output_filter(r, u->out_bufs);
    28482838                if (rc == NGX_ERROR) {
    28492839                    ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
    29452935static ngx_int_t
     2936ngx_http_upstream_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
     2939    if (!r->header_only) {
     2940        return ngx_http_output_filter(r, in);
     2941    }
     2943    while (in) {
     2944        in->buf->pos = in->buf->last;
     2945        in = in->next;
     2946    }
     2948    return NGX_OK;
     2952static ngx_int_t
    29462953ngx_http_upstream_non_buffered_filter_init(void *data)
    29482955    return NGX_OK;

Feel free to use it.

comment:3 by Phil Sweeney, 10 years ago

Thanks for that. I have tried it against 1.5.10 and it does appear to solve the issue!

Do you expect to apply this to mainline or does it require further work before that?

in reply to:  3 comment:4 by Valentin V. Bartenev, 10 years ago

Replying to Phil Sweeney <>:

Do you expect to apply this to mainline or does it require further work before that?

Yes, it needs more work. But not because it does something wrong, the patch is correct and shouldn't introduce any bugs. Just the way it solves the problem hasn't been liked by colleagues.

comment:5 by Ba Duong, 10 years ago

This bug makes me 3 days to investigate and search for solution to use SPDY with proxy cache.
The issue occurs if use

proxy_cache_bypass $no_cache;

or cached items deleted on server while use F5 in browsers. Only the first request is response (GET 304 status) and error with subsequent requests.
No problem if I remove SPDY.

I tested the patch of Valentin V. Bartenev on 1.5.10 and it work for me.

Version 0, edited 10 years ago by Ba Duong (next)

comment:6 by sedaj2@…, 10 years ago


it this problem fixed in 1.5.13?

in reply to:  6 comment:7 by Valentin V. Bartenev, 10 years ago

Replying to

it this problem fixed in 1.5.13?

No. The patch above is still relevant.

comment:8 by Harry Tuttle, 10 years ago


is the vuln and the patch valid for the stable 1.4.7 too?


in reply to:  8 comment:9 by Valentin V. Bartenev, 10 years ago

The issue and the patch valid for 1.4.x branch too.

comment:10 by pavel stano, 10 years ago

Patch work also for 1.6.
If it is not yet fixed information should be in documentation or somewhere.

I encountered also second problem with this issue. With limit_conn it looks like connections are not decreased when they are prematurely closed. So you can see in log that connections are limited on spdy but they are not over limit.

comment:11 by Maxim Dounin, 10 years ago

Resolution: fixed
Status: assignedclosed

Fixed by 35990c69b3ac.

Note: See TracTickets for help on using tickets.