[PATCH] HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance
Damien Tournoud
damien at platform.sh
Mon Jun 8 23:08:30 UTC 2015
# HG changeset patch
# User Damien Tournoud <damien at platform.sh>
# Date 1433803821 -7200
# Tue Jun 09 00:50:21 2015 +0200
# Node ID 04fab8a5fbac9a350c7552ac81569a5deb641240
# Parent 1729d8d3eb3acbb79b1b0c1d60b411aacc4f8461
HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance.
Nginx, when used as a proxy cache, doesn't have any practical
ways to issue a `Age:` header, signaling to downstream clients
the age of objects that it serves from the cache.
This patch adds a $upstream_cache_age variable, that can be
used to issue such a header like:
add_header Age "$upstream_cache_age";
The header is based on `r->cache->date`, so it gets reset with
revalidations, which I think is a reasonable behavior.
In other to make the variable useful, I had to where it is set
in `ngx_http_upstream_send_response()` (in the MISS path),
so that it is set before sending the headers.
diff -r 1729d8d3eb3a -r 04fab8a5fbac src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c Mon Jun 08 23:13:56 2015 +0300
+++ b/src/http/ngx_http_upstream.c Tue Jun 09 00:50:21 2015 +0200
@@ -23,6 +23,8 @@
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_upstream_cache_age(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
#endif
static void ngx_http_upstream_init_request(ngx_http_request_t *r);
@@ -393,6 +395,10 @@
ngx_http_upstream_cache_etag, 0,
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+ { ngx_string("upstream_cache_age"), NULL,
+ ngx_http_upstream_cache_age, 0,
+ NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+
#endif
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
@@ -2647,6 +2653,15 @@
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
+#if (NGX_HTTP_CACHE)
+ time_t now;
+ now = ngx_time();
+
+ if (r->cache) {
+ r->cache->date = now;
+ }
+#endif
+
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
@@ -2787,9 +2802,7 @@
}
if (u->cacheable) {
- time_t now, valid;
-
- now = ngx_time();
+ time_t valid;
valid = r->cache->valid_sec;
@@ -2802,7 +2815,6 @@
}
if (valid) {
- r->cache->date = now;
r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
if (u->headers_in.status_n == NGX_HTTP_OK
@@ -5248,6 +5260,39 @@
return NGX_OK;
}
+
+static ngx_int_t
+ngx_http_upstream_cache_age(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+ time_t now;
+
+ now = ngx_time();
+
+ if (r->upstream == NULL
+ || r->upstream->cacheable == 0
+ || r->cache->date > now)
+ {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->len = ngx_sprintf(p, "%T", now - r->cache->date) - p;
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = p;
+
+ return NGX_OK;
+}
+
#endif
More information about the nginx-devel
mailing list