[PATCH] Cache: re-fetch responses cached with invalid HTTP header

Maxim Dounin mdounin at mdounin.ru
Mon Jul 13 20:10:55 UTC 2015


Hello!

On Fri, Jul 10, 2015 at 03:09:58PM -0700, Piotr Sikora wrote:

> # HG changeset patch
> # User Piotr Sikora <piotr at cloudflare.com>
> # Date 1436566103 25200
> #      Fri Jul 10 15:08:23 2015 -0700
> # Node ID 596ce484f8b5519df8803754f093e37b26806699
> # Parent  dcae651b2a0cbd3de2f1fd5cf5b8c72627db94fd
> Cache: re-fetch responses cached with invalid HTTP header.
> 
> Previously, such responses would be read into the buffer, fail,
> then nginx would connect to the upstream to fetch new response,
> but that response would be read into the same buffer, after the
> invalid response, leading to a persistent failure state.
> 
> This patch resets buffer, so that the new response can be used.
> 
> Signed-off-by: Piotr Sikora <piotr at cloudflare.com>
> 
> diff -r dcae651b2a0c -r 596ce484f8b5 src/http/ngx_http_upstream.c
> --- a/src/http/ngx_http_upstream.c	Tue Jul 07 16:38:49 2015 +0300
> +++ b/src/http/ngx_http_upstream.c	Fri Jul 10 15:08:23 2015 -0700
> @@ -843,6 +843,20 @@
>              return rc;
>          }
>  
> +        u->cache_status = NGX_HTTP_CACHE_MISS;
> +
> +        /* fall through */
> +
> +    case NGX_DECLINED:
> +
> +        if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
> +            u->buffer.start = NULL;
> +
> +        } else {
> +            u->buffer.pos = u->buffer.start + c->header_start;
> +            u->buffer.last = u->buffer.pos;
> +        }
> +
>          break;
>  
>      case NGX_HTTP_CACHE_STALE:

This change doesn't looks sufficient to properly handle the 
problem.  At least I see duplicate headers in a first response 
when the code is triggered:

$ curl -i http://127.0.0.1:8080/
HTTP/1.1 200 OK
Server: nginx/1.9.3
Date: Mon, 13 Jul 2015 20:03:10 GMT
Content-Type: text/html
Content-Length: 1047
Connection: keep-alive
Last-Modified: Mon, 13 Feb 2012 01:20:52 GMT
ETag: "4f386574-417"
Last-Modified: Mon, 13 Feb 2012 01:20:52 GMT
ETag: "4f386574-417"
Accept-Ranges: bytes

I haven't digged into details, but likely it's because headers 
from a cached invalid response were already pushed to 
r->headers_out.

It might be better idea to actually implement what's already 
marked as TODO in ngx_http_upstream_cache_send().

    /* TODO: delete file */

-- 
Maxim Dounin
http://nginx.org/



More information about the nginx-devel mailing list