Skip to content

Commit

Permalink
Upstream: fixed X-Accel-Expires/Cache-Control/Expires handling.
Browse files Browse the repository at this point in the history
Previously, if caching was disabled due to Expires in the past, nginx
failed to cache the response even if it was cacheable as per subsequently
parsed Cache-Control header (ticket #964).

Similarly, if caching was disabled due to Expires in the past,
"Cache-Control: no-cache" or "Cache-Control: max-age=0", caching was not
used if it was cacheable as per subsequently parsed X-Accel-Expires header.

Fix is to avoid disabling caching immediately after parsing Expires in
the past or Cache-Control, but rather set flags which are later checked by
ngx_http_upstream_process_headers() (and cleared by "Cache-Control: max-age"
and X-Accel-Expires).

Additionally, now X-Accel-Expires does not prevent parsing of cache control
extensions, notably stale-while-revalidate and stale-if-error.  This
ensures that order of the X-Accel-Expires and Cache-Control headers is not
important.

Prodded by Vadim Fedorenko and Yugo Horie.
  • Loading branch information
mdounin committed Jun 6, 2022
1 parent bfc5b35 commit 8df3ad1
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
29 changes: 22 additions & 7 deletions src/http/ngx_http_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -2702,6 +2702,10 @@ ngx_http_upstream_intercept_errors(ngx_http_request_t *r,

if (r->cache) {

if (u->headers_in.no_cache || u->headers_in.expired) {
u->cacheable = 0;
}

if (u->cacheable) {
time_t valid;

Expand Down Expand Up @@ -2796,6 +2800,10 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)

umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

if (u->headers_in.no_cache || u->headers_in.expired) {
u->cacheable = 0;
}

if (u->headers_in.x_accel_redirect
&& !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
{
Expand Down Expand Up @@ -4791,18 +4799,18 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
return NGX_OK;
}

if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
return NGX_OK;
}

start = h->value.data;
last = start + h->value.len;

if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
goto extensions;
}

if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL
|| ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL
|| ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL)
{
u->cacheable = 0;
u->headers_in.no_cache = 1;
return NGX_OK;
}

Expand Down Expand Up @@ -4832,13 +4840,16 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
}

if (n == 0) {
u->cacheable = 0;
u->headers_in.no_cache = 1;
return NGX_OK;
}

r->cache->valid_sec = ngx_time() + n;
u->headers_in.expired = 0;
}

extensions:

p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=",
23 - 1);

Expand Down Expand Up @@ -4932,7 +4943,7 @@ ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
expires = ngx_parse_http_time(h->value.data, h->value.len);

if (expires == NGX_ERROR || expires < ngx_time()) {
u->cacheable = 0;
u->headers_in.expired = 1;
return NGX_OK;
}

Expand Down Expand Up @@ -4996,6 +5007,8 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,

default:
r->cache->valid_sec = ngx_time() + n;
u->headers_in.no_cache = 0;
u->headers_in.expired = 0;
return NGX_OK;
}
}
Expand All @@ -5007,6 +5020,8 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,

if (n != NGX_ERROR) {
r->cache->valid_sec = n;
u->headers_in.no_cache = 0;
u->headers_in.expired = 0;
}
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/http/ngx_http_upstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ typedef struct {

unsigned connection_close:1;
unsigned chunked:1;
unsigned no_cache:1;
unsigned expired:1;
} ngx_http_upstream_headers_in_t;


Expand Down

0 comments on commit 8df3ad1

Please sign in to comment.