[Patch] proxy cache for 304 Not Modified
ビリビリⅤ
orz at loli.my
Thu Sep 15 17:54:04 UTC 2011
Hello guys,
I have wrote a module to make nginx support 304 to decrease bandwidth usage.
note: I have a newbie for nginx module development, so the above module may
have some problem. Welcome to test it and feedback another problem with me.
Note:
I cannot found where can using nginx internal cache update without delete
the old cache, so I using reopen the cache file to write a new expire
header. Can anyone help me to fix this problem?
You can download full patch file from here:
http://m-b.cc/share/proxy_304.txt
# User MagicBear <magicbearmo at gmail.com>
Upstream:
add $upstream_last_modified variant.
add handler for 304 Unmodified.
Proxy:
change to send If-Modified-Since header.
diff -ruN a/http/modules/ngx_http_proxy_module.c
b/http/modules/ngx_http_proxy_module.c
--- a/http/modules/ngx_http_proxy_module.c 2011-09-15
22:23:03.284431407 +0800
+++ b/http/modules/ngx_http_proxy_module.c 2011-09-16
01:41:44.654428632 +0800
@@ -543,7 +543,7 @@
{ 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 -ruN a/http/ngx_http_upstream.c b/http/ngx_http_upstream.c
--- a/http/ngx_http_upstream.c 2011-09-15 22:23:03.284431407 +0800
+++ b/http/ngx_http_upstream.c 2011-09-16 01:41:44.654428632 +0800
@@ -16,6 +16,8 @@
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 @@
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 }
@@ -1618,6 +1624,80 @@
u->buffer.last = u->buffer.pos;
}
+#if (NGX_HTTP_CACHE)
+
+ if (u->cache_status == NGX_HTTP_CACHE_EXPIRED &&
+ u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED &&
+ ngx_http_file_cache_valid(u->conf->cache_valid,
u->headers_in.status_n))
+ {
+ ngx_int_t rc;
+
+ rc = u->reinit_request(r);
+
+ if (rc == NGX_OK) {
+ u->cache_status = NGX_HTTP_CACHE_BYPASS;
+ rc = ngx_http_upstream_cache_send(r, u);
+
+ time_t now, valid;
+
+ now = ngx_time();
+
+ valid = r->cache->valid_sec;
+
+ if (valid == 0) {
+ valid =
ngx_http_file_cache_valid(u->conf->cache_valid,
+
u->headers_in.status_n);
+ if (valid) {
+ r->cache->valid_sec = now +
valid;
+ }
+ }
+
+ if (valid) {
+ r->cache->last_modified =
r->headers_out.last_modified_time;
+ r->cache->date = now;
+ r->cache->body_start = (u_short)
(u->buffer.pos - u->buffer.start);
+
+ // update Header
+ ngx_http_file_cache_set_header(r,
u->buffer.start);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
r->connection->log, 0,
+
"update cache \"%s\" header to new expired." , r->cache->file.name.data);
+
+ // Reopen file via RW
+ ngx_fd_t fd =
ngx_open_file(r->cache->file.name.data, NGX_FILE_RDWR, NGX_FILE_OPEN, 0);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_CRIT,
r->connection->log, ngx_errno,
+
ngx_open_file_n " \"%s\" failed", r->cache->file.name.data);
+ return;
+ }
+
+ // Write cache
+ if (write(fd, u->buffer.start,
sizeof(ngx_http_file_cache_header_t)) < 0)
+ {
+ ngx_log_error(NGX_LOG_CRIT,
r->connection->log, ngx_errno,
+
"write proxy_cache \"%s\" failed", r->cache->file.name.data);
+ return;
+ }
+
+ if (ngx_close_file(fd) ==
NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT,
r->connection->log, ngx_errno,
+
ngx_close_file_n " \"%s\" failed", r->cache->file.name.data);
+ }
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
r->connection->log, 0,
+
"update cache \"%s\" header to new expired done." ,
r->cache->file.name.data);
+ } else {
+ u->cacheable = 0;
+ r->headers_out.last_modified_time =
-1;
+ }
+ }
+
+ ngx_http_upstream_finalize_request(r, u, rc);
+ return;
+ }
+
+#endif
+
if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
return;
}
@@ -4006,6 +4086,32 @@
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 *u;
+
+ if (r->upstream == NULL || r->upstream->cache_status == 0 ||
r->cache==NULL || r->cache->last_modified <= 0) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ u = ngx_pcalloc(r->pool, 30);
+ if (u == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->len = 29;
+ ngx_http_time(u, r->cache->last_modified);
+ v->data = u;
+
+ return NGX_OK;
+}
#endif
MagicBear
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20110916/c5086bf9/attachment.html>
More information about the nginx-devel
mailing list