[Patch] proxy cache for 304 Not Modified

MagicBear magicbearmo at gmail.com
Sun Sep 25 19:19:13 UTC 2011


Fix: patch 3 will cause nginx haven't write access static file will
direct return 403. add a new flag "is_rw" for ngx_open_file_info_t to
check has get it with write access.

Here is the full patch: http://m-b.cc/share/patch-nginx-proxy-304-4.txt
diff -ruNp a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
--- a/src/core/ngx_open_file_cache.c    2011-09-14 22:28:55.000000000 +0800
+++ b/src/core/ngx_open_file_cache.c    2011-09-26 03:13:19.000000000 +0800
@@ -495,7 +495,7 @@ ngx_open_and_stat_file(u_char *name, ngx
          * This flag has no effect on a regular files.
          */

-        fd = ngx_open_file(name, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+        fd = ngx_open_file(name, (of->is_rw ? NGX_FILE_RDWR :
NGX_FILE_RDONLY)|NGX_FILE_NONBLOCK,
                            NGX_FILE_OPEN, 0);

     } else {
diff -ruNp a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h
--- a/src/core/ngx_open_file_cache.h    2011-04-22 18:06:43.000000000 +0800
+++ b/src/core/ngx_open_file_cache.h    2011-09-26 03:12:57.000000000 +0800
@@ -42,6 +42,9 @@ typedef struct {
     unsigned                 is_link:1;
     unsigned                 is_exec:1;
     unsigned                 is_directio:1;
+#if (NGX_HTTP_CACHE)
+    unsigned                 is_rw:1;
+#endif
 } ngx_open_file_info_t;


diff -ruNp a/src/http/modules/ngx_http_proxy_module.c
b/src/http/modules/ngx_http_proxy_module.c
--- a/src/http/modules/ngx_http_proxy_module.c  2011-09-16
03:23:20.000000000 +0800
+++ b/src/http/modules/ngx_http_proxy_module.c  2011-09-26
02:01:08.000000000 +0800
@@ -543,7 +543,7 @@ static ngx_keyval_t  ngx_http_proxy_cach
     { ngx_string("Connection"), ngx_string("close") },
     { ngx_string("Keep-Alive"), ngx_string("") },
     { ngx_string("Expect"), ngx_string("") },
-    { ngx_string("If-Modified-Since"), ngx_string("") },
+    { ngx_string("If-Modified-Since"), ngx_string("$upstream_last_modified") },
     { ngx_string("If-Unmodified-Since"), ngx_string("") },
     { ngx_string("If-None-Match"), ngx_string("") },
     { ngx_string("If-Match"), ngx_string("") },
diff -ruNp a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
--- a/src/http/ngx_http_cache.h 2011-07-29 23:09:02.000000000 +0800
+++ b/src/http/ngx_http_cache.h 2011-09-26 02:01:08.000000000 +0800
@@ -133,6 +133,7 @@ ngx_int_t ngx_http_file_cache_create(ngx
 void ngx_http_file_cache_create_key(ngx_http_request_t *r);
 ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r);
 void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf);
+void ngx_http_file_cache_set_valid(ngx_http_request_t *r);
 void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf);
 ngx_int_t ngx_http_cache_send(ngx_http_request_t *);
 void ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf);
diff -ruNp a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
--- a/src/http/ngx_http_file_cache.c    2011-08-26 01:29:34.000000000 +0800
+++ b/src/http/ngx_http_file_cache.c    2011-09-26 03:13:43.000000000 +0800
@@ -319,6 +319,7 @@ ngx_http_file_cache_open(ngx_http_reques
     of.events = clcf->open_file_cache_events;
     of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
     of.read_ahead = clcf->read_ahead;
+       of.is_rw = 1;

     if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name,
&of, r->pool)
         != NGX_OK)
@@ -766,6 +767,31 @@ ngx_http_file_cache_set_header(ngx_http_
 }


+void
+ngx_http_file_cache_set_valid(ngx_http_request_t *r)
+{
+    ngx_int_t               rc;
+
+    if (r->cache->file.fd == NGX_INVALID_FILE) {
+        ngx_log_error(NGX_LOG_EMERG, r->connection->log, ngx_errno,
+                      ngx_open_file_n " \"%s\" failed",
+                      r->cache->file.name.data);
+        return;
+    }
+
+    rc = ngx_write_file(&r->cache->file, (u_char *) &r->cache->valid_sec,
+                    sizeof(r->cache->valid_sec),
+                    offsetof(ngx_http_file_cache_header_t, valid_sec));
+    if (rc == NGX_ERROR)
+    {
+        ngx_log_error(NGX_LOG_EMERG, r->connection->log, ngx_errno,
+                      "write proxy_cache \"%s\" failed",
+                      r->cache->file.name.data);
+        return;
+    }
+}
+
+
 void
 ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf)
 {
diff -ruNp a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c      2011-09-20 18:00:46.000000000 +0800
+++ b/src/http/ngx_http_upstream.c      2011-09-26 02:01:08.000000000 +0800
@@ -16,6 +16,8 @@ static ngx_int_t ngx_http_upstream_cache
     ngx_http_upstream_t *u);
 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_upstream_last_modified(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);
@@ -342,6 +344,10 @@ static ngx_http_variable_t  ngx_http_ups
       ngx_http_upstream_cache_status, 0,
       NGX_HTTP_VAR_NOCACHEABLE, 0 },

+    { ngx_string("upstream_last_modified"), NULL,
+      ngx_http_upstream_last_modified, 0,
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
 #endif

     { ngx_null_string, NULL, NULL, 0, 0, 0 }
@@ -1682,6 +1688,34 @@ ngx_http_upstream_test_next(ngx_http_req

     status = u->headers_in.status_n;

+#if (NGX_HTTP_CACHE)
+
+    if (u->cache_status == NGX_HTTP_CACHE_EXPIRED &&
+        status == NGX_HTTP_NOT_MODIFIED)
+    {
+        ngx_int_t  rc;
+        time_t  valid;
+
+        rc = u->reinit_request(r);
+
+        if (rc == NGX_OK) {
+            rc = ngx_http_upstream_cache_send(r, u);
+
+            if (r->cache->valid_sec == 0) {
+                valid = ngx_http_file_cache_valid(u->conf->cache_valid,
+                                                u->headers_in.status_n);
+                r->cache->valid_sec = ngx_time() + valid;
+            }
+
+            ngx_http_file_cache_set_valid(r);
+
+            ngx_http_upstream_finalize_request(r, u, rc);
+            return NGX_OK;
+        }
+    }
+
+#endif
+
     for (un = ngx_http_upstream_next_errors; un->status; un++) {

         if (status != un->status) {
@@ -4012,6 +4046,33 @@ ngx_http_upstream_cache_status(ngx_http_

     return NGX_OK;
 }
+
+
+ngx_int_t
+ngx_http_upstream_last_modified(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    u_char *p;
+
+    if (r->upstream == NULL || r->upstream->cache_status == 0 ||
+        r->cache->last_modified == 0) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    p = ngx_pcalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
+    if (p == NULL) {
+        return NGX_ERROR;
+    }
+
+    v->len = ngx_http_time(p, r->cache->last_modified) - p;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->data = p;
+
+    return NGX_OK;
+}

 #endif


-- 
MagicBear



More information about the nginx-devel mailing list