# HG changeset patch # User Maxim Dounin # Date 1721320779 -10800 # Node ID 8cdab3d89c44c26a91562eac5d421a727e80489e # Parent f209bf590e849f1ca0021906687e954e8878243d Upstream: using the "Age" header when caching responses. As long as the "Age" header is present and not ignored, it is now respected when caching responses per "Cache-Control: max-age", reducing cache validity time. diff -r f209bf590e84 -r 8cdab3d89c44 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu Jul 18 19:39:29 2024 +0300 +++ b/src/http/ngx_http_upstream.c Thu Jul 18 19:39:39 2024 +0300 @@ -136,6 +136,8 @@ ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_age(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t @@ -293,6 +295,10 @@ ngx_http_upstream_copy_multi_header_lines, offsetof(ngx_http_headers_out_t, link), 0 }, + { ngx_string("Age"), + ngx_http_upstream_process_age, 0, + ngx_http_upstream_copy_header_line, 0, 0 }, + { ngx_string("X-Accel-Expires"), ngx_http_upstream_process_accel_expires, 0, ngx_http_upstream_copy_header_line, 0, 0 }, @@ -475,6 +481,7 @@ { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL }, { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE }, { ngx_string("Vary"), NGX_HTTP_UPSTREAM_IGN_VARY }, + { ngx_string("Age"), NGX_HTTP_UPSTREAM_IGN_AGE }, { ngx_null_string, 0 } }; @@ -4939,13 +4946,14 @@ return NGX_OK; } - if (n == 0) { + if (n <= u->headers_in.age_n) { u->headers_in.no_cache = 1; return NGX_OK; } - r->cache->valid_sec = ngx_time() + n; + r->cache->valid_sec = ngx_time() + n - u->headers_in.age_n; u->headers_in.expired = 0; + u->headers_in.max_age = 1; } extensions: @@ -5109,6 +5117,7 @@ r->cache->valid_sec = ngx_time() + n; u->headers_in.no_cache = 0; u->headers_in.expired = 0; + u->headers_in.max_age = 0; return NGX_OK; } } @@ -5122,6 +5131,7 @@ r->cache->valid_sec = n; u->headers_in.no_cache = 0; u->headers_in.expired = 0; + u->headers_in.max_age = 0; } } #endif @@ -5373,6 +5383,61 @@ static ngx_int_t +ngx_http_upstream_process_age(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + + if (u->headers_in.age) { + ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, + "upstream sent duplicate header line: \"%V: %V\", " + "previous value: \"%V: %V\", ignored", + &h->key, &h->value, + &u->headers_in.age->key, + &u->headers_in.age->value); + h->hash = 0; + return NGX_OK; + } + + u->headers_in.age = h; + h->next = NULL; + +#if (NGX_HTTP_CACHE) + { + ngx_int_t n; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_AGE) { + return NGX_OK; + } + + if (r->cache == NULL || !u->cacheable) { + return NGX_OK; + } + + n = ngx_atoi(h->value.data, h->value.len); + + if (n != NGX_ERROR) { + u->headers_in.age_n = n; + + if (u->headers_in.max_age) { + if (n >= r->cache->valid_sec - ngx_time()) { + u->headers_in.no_cache = 1; + return NGX_OK; + } + + r->cache->valid_sec -= n; + } + } + } +#endif + + return NGX_OK; +} + + +static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { diff -r f209bf590e84 -r 8cdab3d89c44 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Thu Jul 18 19:39:29 2024 +0300 +++ b/src/http/ngx_http_upstream.h Thu Jul 18 19:39:39 2024 +0300 @@ -54,6 +54,7 @@ #define NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING 0x00000080 #define NGX_HTTP_UPSTREAM_IGN_XA_CHARSET 0x00000100 #define NGX_HTTP_UPSTREAM_IGN_VARY 0x00000200 +#define NGX_HTTP_UPSTREAM_IGN_AGE 0x00000400 typedef struct { @@ -287,14 +288,17 @@ ngx_table_elt_t *cache_control; ngx_table_elt_t *set_cookie; + ngx_table_elt_t *age; off_t content_length_n; time_t last_modified_time; + time_t age_n; unsigned connection_close:1; unsigned chunked:1; unsigned no_cache:1; unsigned expired:1; + unsigned max_age:1; } ngx_http_upstream_headers_in_t;