# HG changeset patch # User Igor Sysoev # Date 1275913403 0 # Node ID 0d8b8c84bab7f051f1864326095a324458fab10c # Parent 555de5bdb80070b94a4c1bbfdca272d7a9f4c7f2 merge r3518, r3527: cache related fixes: *) do not cache response if it has "no-store" or "private" in "Cache-Control" header *) proxy_no_cache and fastcgi_no_cache diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -333,6 +333,13 @@ static ngx_command_t ngx_http_fastcgi_c 0, &ngx_http_fastcgi_module }, + { ngx_string("fastcgi_no_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_no_cache_set_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache), + NULL }, + { ngx_string("fastcgi_cache_valid"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_file_cache_valid_set_slot, @@ -1890,6 +1897,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; #endif @@ -2111,6 +2119,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; + ngx_conf_merge_ptr_value(conf->upstream.no_cache, + prev->upstream.no_cache, NULL); + ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); diff --git 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 +++ b/src/http/modules/ngx_http_proxy_module.c @@ -357,6 +357,13 @@ static ngx_command_t ngx_http_proxy_com 0, &ngx_http_proxy_module }, + { ngx_string("proxy_no_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_no_cache_set_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache), + NULL }, + { ngx_string("proxy_cache_valid"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_file_cache_valid_set_slot, @@ -1933,6 +1940,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; #endif @@ -2157,6 +2165,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t |NGX_HTTP_UPSTREAM_FT_OFF; } + ngx_conf_merge_ptr_value(conf->upstream.no_cache, + prev->upstream.no_cache, NULL); + ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -133,6 +133,11 @@ char *ngx_http_file_cache_set_slot(ngx_c char *ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +ngx_int_t ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache); +char *ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + extern ngx_str_t ngx_http_cache_status[]; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1604,3 +1604,69 @@ ngx_http_file_cache_valid_set_slot(ngx_c return NGX_CONF_OK; } + + +ngx_int_t +ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache) +{ + ngx_str_t val; + ngx_uint_t i; + ngx_http_complex_value_t *cv; + + cv = no_cache->elts; + + for (i = 0; i < no_cache->nelts; i++) { + if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) { + return NGX_ERROR; + } + + if (val.len && val.data[0] != '0') { + return NGX_DECLINED; + } + } + + return NGX_OK; +} + + +char * +ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_uint_t i; + ngx_array_t **a; + ngx_http_complex_value_t *cv; + ngx_http_compile_complex_value_t ccv; + + a = (ngx_array_t **) (p + cmd->offset); + + if (*a == NGX_CONF_UNSET_PTR) { + *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t)); + if (*a == NULL) { + return NGX_CONF_ERROR; + } + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + cv = ngx_array_push(*a); + if (cv == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[i]; + ccv.complex_value = cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -585,6 +585,13 @@ ngx_http_upstream_cache(ngx_http_request ngx_int_t rc; ngx_http_cache_t *c; + if (u->conf->no_cache) { + rc = ngx_http_cache(r, u->conf->no_cache); + if (rc != NGX_OK) { + return rc; + } + } + if (!(r->method & u->conf->cache_methods)) { return NGX_DECLINED; } @@ -3002,16 +3009,18 @@ ngx_http_upstream_process_cache_control( return NGX_OK; } - last = h->value.data + h->value.len; - - if (ngx_strlcasestrn(h->value.data, last, (u_char *) "no-cache", 8 - 1) - != NULL) + p = h->value.data; + last = p + h->value.len; + + if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL + || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL + || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL) { u->cacheable = 0; return NGX_OK; } - p = ngx_strlcasestrn(h->value.data, last, (u_char *) "max-age=", 8 - 1); + p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1); if (p == NULL) { return NGX_OK; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -160,6 +160,7 @@ typedef struct { ngx_uint_t cache_methods; ngx_array_t *cache_valid; + ngx_array_t *no_cache; /* ngx_http_complex_value_t */ #endif ngx_array_t *store_lengths;