Expires: modified +1d?

Igor Sysoev is at rambler-co.ru
Thu May 15 15:26:16 MSD 2008


On Thu, May 15, 2008 at 03:23:20PM +0400, Igor Sysoev wrote:

> On Thu, May 15, 2008 at 10:26:36AM +0100, Phillip B Oldham wrote:
> 
> > Is it possible to set the expires header based on the modified time of a 
> > file? I know you can do this in lighttpd and apache, but I can't find 
> > any configuration examples for nginx.
> 
> Try the attached patch.
> 
> It allows
> 
>     expires modified +1d;

The patch itself.


-- 
Igor Sysoev
http://sysoev.ru/en/
-------------- next part --------------
Index: src/http/modules/ngx_http_headers_filter_module.c
===================================================================
--- src/http/modules/ngx_http_headers_filter_module.c	(revision 1326)
+++ src/http/modules/ngx_http_headers_filter_module.c	(working copy)
@@ -31,18 +31,20 @@
 };
 
 
+#define NGX_HTTP_EXPIRES_OFF       0
+#define NGX_HTTP_EXPIRES_EPOCH     1
+#define NGX_HTTP_EXPIRES_MAX       2
+#define NGX_HTTP_EXPIRES_ACCESS    3
+#define NGX_HTTP_EXPIRES_MODIFIED  4
+
+
 typedef struct {
-    time_t                   expires;
+    ngx_uint_t               expires;
+    time_t                   expires_time;
     ngx_array_t             *headers;
 } ngx_http_headers_conf_t;
 
 
-#define NGX_HTTP_EXPIRES_UNSET   -2147483647
-#define NGX_HTTP_EXPIRES_OFF     -2147483646
-#define NGX_HTTP_EXPIRES_EPOCH   -2147483645
-#define NGX_HTTP_EXPIRES_MAX     -2147483644
-
-
 static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r,
     ngx_http_headers_conf_t *conf);
 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r,
@@ -76,7 +78,7 @@
 
     { ngx_string("expires"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                        |NGX_CONF_TAKE1,
+                        |NGX_CONF_TAKE12,
       ngx_http_headers_expires,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -185,6 +187,7 @@
 ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
 {
     size_t            len;
+    time_t            since;
     ngx_uint_t        i;
     ngx_table_elt_t  *expires, *cc, **ccp;
 
@@ -266,7 +269,7 @@
         return NGX_ERROR;
     }
 
-    if (conf->expires == 0) {
+    if (conf->expires_time == 0) {
         ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
                    ngx_cached_http_time.len + 1);
 
@@ -276,9 +279,20 @@
         return NGX_OK;
     }
 
-    ngx_http_time(expires->value.data, ngx_time() + conf->expires);
+    if (conf->expires == NGX_HTTP_EXPIRES_MODIFIED) {
+        since = r->headers_out.last_modified_time;
 
-    if (conf->expires < 0) {
+        if (since == -1) {
+            since = ngx_time();
+        }
+
+    } else {
+        since = ngx_time();
+    }
+
+    ngx_http_time(expires->value.data, since + conf->expires_time);
+
+    if (conf->expires_time < 0) {
         cc->value.len = sizeof("no-cache") - 1;
         cc->value.data = (u_char *) "no-cache";
 
@@ -291,7 +305,8 @@
         return NGX_ERROR;
     }
 
-    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", conf->expires)
+    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
+                                since + conf->expires_time - ngx_time())
                     - cc->value.data;
 
     return NGX_OK;
@@ -413,9 +428,10 @@
      * set by ngx_pcalloc():
      *
      *     conf->headers = NULL;
+     *     conf->expires_time = 0;
      */
 
-    conf->expires = NGX_HTTP_EXPIRES_UNSET;
+    conf->expires = NGX_CONF_UNSET_UINT;
 
     return conf;
 }
@@ -427,9 +443,13 @@
     ngx_http_headers_conf_t *prev = parent;
     ngx_http_headers_conf_t *conf = child;
 
-    if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
-        conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ?
-                            NGX_HTTP_EXPIRES_OFF : prev->expires;
+    if (conf->expires == NGX_CONF_UNSET_UINT) {
+        conf->expires = prev->expires;
+        conf->expires_time = prev->expires_time;
+
+        if (conf->expires == NGX_CONF_UNSET_UINT) {
+            conf->expires = NGX_HTTP_EXPIRES_OFF;
+        }
     }
 
     if (conf->headers == NULL) {
@@ -455,56 +475,73 @@
 {
     ngx_http_headers_conf_t *hcf = conf;
 
-    ngx_uint_t   minus;
+    ngx_uint_t   minus, n;
     ngx_str_t   *value;
 
-    if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
+    if (hcf->expires != NGX_CONF_UNSET_UINT) {
         return "is duplicate";
     }
 
     value = cf->args->elts;
 
-    if (ngx_strcmp(value[1].data, "epoch") == 0) {
-        hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
-        return NGX_CONF_OK;
-    }
+    if (cf->args->nelts == 2) {
 
-    if (ngx_strcmp(value[1].data, "max") == 0) {
-        hcf->expires = NGX_HTTP_EXPIRES_MAX;
-        return NGX_CONF_OK;
-    }
+        if (ngx_strcmp(value[1].data, "epoch") == 0) {
+            hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
+            return NGX_CONF_OK;
+        }
 
-    if (ngx_strcmp(value[1].data, "off") == 0) {
-        hcf->expires = NGX_HTTP_EXPIRES_OFF;
-        return NGX_CONF_OK;
+        if (ngx_strcmp(value[1].data, "max") == 0) {
+            hcf->expires = NGX_HTTP_EXPIRES_MAX;
+            return NGX_CONF_OK;
+        }
+
+        if (ngx_strcmp(value[1].data, "off") == 0) {
+            hcf->expires = NGX_HTTP_EXPIRES_OFF;
+            return NGX_CONF_OK;
+        }
+
+        hcf->expires = NGX_HTTP_EXPIRES_ACCESS;
+
+        n = 1;
+
+    } else { /* cf->args->nelts == 3 */
+
+        if (ngx_strcmp(value[1].data, "modified") != 0) {
+            return "invalid value";
+        }
+
+        hcf->expires = NGX_HTTP_EXPIRES_MODIFIED;
+
+        n = 2;
     }
 
-    if (value[1].data[0] == '+') {
-        value[1].data++;
-        value[1].len--;
+    if (value[n].data[0] == '+') {
+        value[n].data++;
+        value[n].len--;
         minus = 0;
 
-    } else if (value[1].data[0] == '-') {
-        value[1].data++;
-        value[1].len--;
+    } else if (value[n].data[0] == '-') {
+        value[n].data++;
+        value[n].len--;
         minus = 1;
 
     } else {
         minus = 0;
     }
 
-    hcf->expires = ngx_parse_time(&value[1], 1);
+    hcf->expires_time = ngx_parse_time(&value[n], 1);
 
-    if (hcf->expires == NGX_ERROR) {
+    if (hcf->expires_time == NGX_ERROR) {
         return "invalid value";
     }
 
-    if (hcf->expires == NGX_PARSE_LARGE_TIME) {
+    if (hcf->expires_time == NGX_PARSE_LARGE_TIME) {
         return "value must be less than 68 years";
     }
 
     if (minus) {
-        hcf->expires = - hcf->expires;
+        hcf->expires_time = - hcf->expires_time;
     }
 
     return NGX_CONF_OK;


More information about the nginx mailing list