Hello guys, <div>I have wrote a module to make nginx support 304 to decrease bandwidth usage.</div><div>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.</div>
<div>Note:</div><div>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?</div><div>
<br></div><div>You can download full patch file from here: <a href="http://m-b.cc/share/proxy_304.txt">http://m-b.cc/share/proxy_304.txt</a></div><div><br><div># User MagicBear <<a href="mailto:magicbearmo@gmail.com">magicbearmo@gmail.com</a>></div>
<div>Upstream:</div><div>add $upstream_last_modified variant.</div><div>add handler for 304 Unmodified.</div><div>Proxy:</div><div>change to send If-Modified-Since header. </div><div><br></div><div>diff -ruN a/http/modules/ngx_http_proxy_module.c b/http/modules/ngx_http_proxy_module.c</div>
<div>--- a/http/modules/ngx_http_proxy_module.c 2011-09-15 22:23:03.284431407 +0800</div><div>+++ b/http/modules/ngx_http_proxy_module.c 2011-09-16 01:41:44.654428632 +0800</div><div>@@ -543,7 +543,7 @@</div><div>
{ ngx_string("Connection"), ngx_string("close") },</div><div> { ngx_string("Keep-Alive"), ngx_string("") },</div><div> { ngx_string("Expect"), ngx_string("") },</div>
<div>- { ngx_string("If-Modified-Since"), ngx_string("") },</div><div>+ { ngx_string("If-Modified-Since"), ngx_string("$upstream_last_modified") },</div><div> { ngx_string("If-Unmodified-Since"), ngx_string("") },</div>
<div> { ngx_string("If-None-Match"), ngx_string("") },</div><div> { ngx_string("If-Match"), ngx_string("") },</div><div>diff -ruN a/http/ngx_http_upstream.c b/http/ngx_http_upstream.c</div>
<div>--- a/http/ngx_http_upstream.c 2011-09-15 22:23:03.284431407 +0800</div><div>+++ b/http/ngx_http_upstream.c 2011-09-16 01:41:44.654428632 +0800</div><div>@@ -16,6 +16,8 @@</div><div> ngx_http_upstream_t *u);</div>
<div> static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,</div><div> ngx_http_variable_value_t *v, uintptr_t data);</div><div>+static ngx_int_t ngx_http_upstream_last_modified(ngx_http_request_t *r,</div>
<div>+ ngx_http_variable_value_t *v, uintptr_t data);</div><div> #endif</div><div><br></div><div> static void ngx_http_upstream_init_request(ngx_http_request_t *r);</div><div>@@ -342,6 +344,10 @@</div><div> ngx_http_upstream_cache_status, 0,</div>
<div> NGX_HTTP_VAR_NOCACHEABLE, 0 },</div><div><br></div><div>+ { ngx_string("upstream_last_modified"), NULL,</div><div>+ ngx_http_upstream_last_modified, 0,</div><div>+ NGX_HTTP_VAR_NOCACHEABLE, 0 },</div>
<div>+</div><div> #endif</div><div><br></div><div> { ngx_null_string, NULL, NULL, 0, 0, 0 }</div><div>@@ -1618,6 +1624,80 @@</div><div> u->buffer.last = u->buffer.pos;</div><div> }</div><div>
<br></div><div>+#if (NGX_HTTP_CACHE)</div><div>+</div><div>+ if (u->cache_status == NGX_HTTP_CACHE_EXPIRED &&</div><div>+ u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED &&</div>
<div>+ ngx_http_file_cache_valid(u->conf->cache_valid, u->headers_in.status_n))</div><div>+ {</div><div>+ ngx_int_t rc;</div><div>+</div><div>+ rc = u->reinit_request(r);</div>
<div>+</div><div>+ if (rc == NGX_OK) {</div><div>+ u->cache_status = NGX_HTTP_CACHE_BYPASS;</div><div>+ rc = ngx_http_upstream_cache_send(r, u);</div><div>+</div><div>+ time_t now, valid;</div>
<div>+</div><div>+ now = ngx_time();</div><div>+</div><div>+ valid = r->cache->valid_sec;</div><div>+</div><div>+ if (valid == 0) {</div>
<div>+ valid = ngx_http_file_cache_valid(u->conf->cache_valid,</div><div>+ u->headers_in.status_n);</div>
<div>+ if (valid) {</div><div>+ r->cache->valid_sec = now + valid;</div><div>+ }</div><div>+ }</div>
<div>+</div><div>+ if (valid) {</div><div>+ r->cache->last_modified = r->headers_out.last_modified_time;</div><div>+ r->cache->date = now;</div>
<div>+ r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);</div><div>+</div><div>+ // update Header</div><div>+ ngx_http_file_cache_set_header(r, u->buffer.start);</div>
<div>+</div><div>+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,</div><div>+ "update cache \"%s\" header to new expired." , r->cache->file.name.data);</div>
<div>+</div><div>+ // Reopen file via RW</div><div>+ ngx_fd_t fd = ngx_open_file(r->cache->file.name.data, NGX_FILE_RDWR, NGX_FILE_OPEN, 0);</div>
<div>+</div><div>+ if (fd == NGX_INVALID_FILE) {</div><div>+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,</div><div>+ ngx_open_file_n " \"%s\" failed", r->cache->file.name.data);</div>
<div>+ return;</div><div>+ }</div><div>+</div><div>+ // Write cache</div><div>+ if (write(fd, u->buffer.start, sizeof(ngx_http_file_cache_header_t)) < 0)</div>
<div>+ {</div><div>+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,</div><div>+ "write proxy_cache \"%s\" failed", r->cache->file.name.data);</div>
<div>+ return;</div><div>+ }</div><div>+</div><div>+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {</div>
<div>+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,</div><div>+ ngx_close_file_n " \"%s\" failed", r->cache->file.name.data);</div>
<div>+ }</div><div>+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,</div><div>+ "update cache \"%s\" header to new expired done." , r->cache->file.name.data);</div>
<div>+ } else {</div><div>+ u->cacheable = 0;</div><div>+ r->headers_out.last_modified_time = -1;</div><div>+ }</div>
<div>+ }</div><div>+</div><div>+ ngx_http_upstream_finalize_request(r, u, rc);</div><div>+ return;</div><div>+ }</div><div>+</div><div>+#endif</div><div>+</div><div> if (ngx_http_upstream_test_next(r, u) == NGX_OK) {</div>
<div> return;</div><div> }</div><div>@@ -4006,6 +4086,32 @@</div><div><br></div><div> return NGX_OK;</div><div> }</div><div>+</div><div>+ngx_int_t</div><div>+ngx_http_upstream_last_modified(ngx_http_request_t *r,</div>
<div>+ ngx_http_variable_value_t *v, uintptr_t data)</div><div>+{</div><div>+ u_char *u;</div><div>+</div><div>+ if (r->upstream == NULL || r->upstream->cache_status == 0 || r->cache==NULL || r->cache->last_modified <= 0) {</div>
<div>+ v->not_found = 1;</div><div>+ return NGX_OK;</div><div>+ }</div><div>+</div><div>+ v->valid = 1;</div><div>+ v->no_cacheable = 0;</div><div>+ v->not_found = 0;</div><div>+ u = ngx_pcalloc(r->pool, 30);</div>
<div>+ if (u == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ v->len = 29;</div><div>+ ngx_http_time(u, r->cache->last_modified);</div><div>+ v->data = u;</div>
<div>+</div><div>+ return NGX_OK;</div><div>+}</div><div><br></div><div> #endif</div></div><div><br></div><div><br></div><div>MagicBear</div><div><br></div>