[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