[PATCH] Upstream: fix the cache duration calculation

Florent Le Coz florent.lecoz at smartjog.com
Fri Nov 15 15:35:09 UTC 2013


Hi,

On 11/15/2013 01:44 PM, Maxim Dounin wrote:
[…]
 >
 > Perfectly correct solution would be to store a bit (likely in
 > u->headers_in) to indicate that valid_sec was set based on
 > X-Accel-Expires and shouldn't be overwritten.
 >

Since there are, in nginx, three headers that can modify the value of 
valid_sec (Expires, Cache-Control and Expires), I think it would be 
cleaner to define a priority for each of these headers and to use that 
priority to decide if we modify or not the valid_sec value.

That’s what I’ve done in the attached patch.
When setting the value of valid_sec, each header writes its own priority 
in valid_sec_prio.
When processing an other header, instead of checking if the valid_sec is 
already set, we check if the headers’ priority is higher than the one 
set, before setting (or not) the value found in the header being processed.

I’ve set the priorities as: X-Accel-Expires > Cache-Control > Expires.
I’m not sure about what the priority of X-Accel-Expires should be (but 
the last two are well defined in the RFC as you correctly pointed in a 
previous message).

 > I'm not sure it worth the effort though.

I personally think it’s much better to have a well-defined priority 
between headers modifying the same value, but well…

Regards,

-- 
Florent Le Coz
Smartjog


-------------- next part --------------
# HG changeset patch
# User Florent Le Coz <florent.lecoz at smartjog.com>
# Date 1384527955 0
# Node ID c26efc188ac84a8b8f2bb4478efb795635a3498d
# Parent  cbb9a6c7493c3c01323fbc4a61be4a9f0af55ef2
Upstream: implement a priority for headers modifying the cache behaviour

Instead of setting the cache duration (or disabling it) based on the order
in which the headers (X-Accel-Expires, Expires, Cache-Control) are received,
each of these header now has a priority that we use to determine which
header should be trusted.

diff -r cbb9a6c7493c -r c26efc188ac8 src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c	Mon Nov 11 18:49:35 2013 +0400
+++ b/src/http/ngx_http_upstream.c	Fri Nov 15 15:05:55 2013 +0000
@@ -3599,7 +3599,7 @@ ngx_http_upstream_process_cache_control(
         return NGX_OK;
     }
 
-    if (r->cache->valid_sec != 0) {
+    if (u->headers_in.valid_sec_prio >= NGX_HTTP_UPSTREAM_CACHE_CONTROL_H_P) {
         return NGX_OK;
     }
 
@@ -3642,6 +3642,7 @@ ngx_http_upstream_process_cache_control(
     }
 
     r->cache->valid_sec = ngx_time() + n;
+    u->headers_in.valid_sec_prio = NGX_HTTP_UPSTREAM_CACHE_CONTROL_H_P;
     }
 #endif
 
@@ -3674,6 +3675,10 @@ ngx_http_upstream_process_expires(ngx_ht
         return NGX_OK;
     }
 
+    if (u->headers_in.valid_sec_prio >= NGX_HTTP_UPSTREAM_EXPIRES_H_P) {
+        return NGX_OK;
+    }
+
     expires = ngx_http_parse_time(h->value.data, h->value.len);
 
     if (expires == NGX_ERROR || expires < ngx_time()) {
@@ -3682,6 +3687,7 @@ ngx_http_upstream_process_expires(ngx_ht
     }
 
     r->cache->valid_sec = expires;
+    u->headers_in.valid_sec_prio = NGX_HTTP_UPSTREAM_EXPIRES_H_P;
     }
 #endif
 
@@ -3728,6 +3734,7 @@ ngx_http_upstream_process_accel_expires(
 
         default:
             r->cache->valid_sec = ngx_time() + n;
+            u->headers_in.valid_sec_prio = NGX_HTTP_UPSTREAM_XA_EXPIRES_H_P;
             return NGX_OK;
         }
     }
@@ -3739,6 +3746,7 @@ ngx_http_upstream_process_accel_expires(
 
     if (n != NGX_ERROR) {
         r->cache->valid_sec = n;
+        u->headers_in.valid_sec_prio = NGX_HTTP_UPSTREAM_XA_EXPIRES_H_P;
     }
     }
 #endif
diff -r cbb9a6c7493c -r c26efc188ac8 src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h	Mon Nov 11 18:49:35 2013 +0400
+++ b/src/http/ngx_http_upstream.h	Fri Nov 15 15:05:55 2013 +0000
@@ -105,6 +105,10 @@ typedef struct {
 #define NGX_HTTP_UPSTREAM_DOWN          0x0010
 #define NGX_HTTP_UPSTREAM_BACKUP        0x0020
 
+/* Headers priority to control the cache behaviour */
+#define NGX_HTTP_UPSTREAM_EXPIRES_H_P         1
+#define NGX_HTTP_UPSTREAM_CACHE_CONTROL_H_P   2
+#define NGX_HTTP_UPSTREAM_XA_EXPIRES_H_P      3
 
 struct ngx_http_upstream_srv_conf_s {
     ngx_http_upstream_peer_t         peer;
@@ -245,6 +249,13 @@ typedef struct {
 
     unsigned                         connection_close:1;
     unsigned                         chunked:1;
+#if (NGX_HTTP_CACHE)
+    /* Defines the priority (see NGX_HTTP_UPSTREAM_*_H_P) of the
+     ngx_http_cache_t.valid_sec value currently set.  It is used to decide
+     if a new header should overwrite this value due to the priority of this
+     header being higher than the one currently set. */
+    unsigned                         valid_sec_prio:2;
+#endif
 } ngx_http_upstream_headers_in_t;


More information about the nginx-devel mailing list