summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2010-07-19 11:31:37 +0000
committerJonathan Kolb <jon@b0g.us>2010-07-19 11:31:37 +0000
commit7ec2890e159e9eeb18b4d07c94de4583a5abd6fe (patch)
tree5ddb218d0dce28f9dc27079a83d487a34955237c
parent5bb3d73305ddc4b7adb5b791c13f66d071c5af2a (diff)
downloadnginx-7ec2890e159e9eeb18b4d07c94de4583a5abd6fe.tar.gz
Changes with nginx 0.8.46 19 Jul 2010v0.8.46
*) Change: now the "proxy_no_cache", "fastcgi_no_cache", "uwsgi_no_cache", and "sсgi_no_cache" directives affect on a cached response saving only. *) Feature: the "proxy_cache_bypass", "fastcgi_cache_bypass", "uwsgi_cache_bypass", and "sсgi_cache_bypass" directives. *) Bugfix: nginx did not free memory in cache keys zones if there was an error during working with backend: the memory was freed only after inactivity time or on memory low condition.
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru14
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c19
-rw-r--r--src/http/modules/ngx_http_proxy_module.c19
-rw-r--r--src/http/modules/ngx_http_scgi_module.c14
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c14
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_cache.h17
-rw-r--r--src/http/ngx_http_file_cache.c133
-rw-r--r--src/http/ngx_http_script.c70
-rw-r--r--src/http/ngx_http_script.h5
-rw-r--r--src/http/ngx_http_upstream.c69
-rw-r--r--src/http/ngx_http_upstream.h3
14 files changed, 336 insertions, 61 deletions
diff --git a/CHANGES b/CHANGES
index c07989efa..915a23052 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
+Changes with nginx 0.8.46 19 Jul 2010
+
+ *) Change: now the "proxy_no_cache", "fastcgi_no_cache",
+ "uwsgi_no_cache", and "sсgi_no_cache" directives affect on a cached
+ response saving only.
+
+ *) Feature: the "proxy_cache_bypass", "fastcgi_cache_bypass",
+ "uwsgi_cache_bypass", and "sсgi_cache_bypass" directives.
+
+ *) Bugfix: nginx did not free memory in cache keys zones if there was
+ an error during working with backend: the memory was freed only
+ after inactivity time or on memory low condition.
+
+
Changes with nginx 0.8.45 13 Jul 2010
*) Feature: ngx_http_xslt_filter improvements.
diff --git a/CHANGES.ru b/CHANGES.ru
index 22c9efad9..66c54a3af 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,18 @@
+Изменения в nginx 0.8.46 19.07.2010
+
+ *) Изменение: директивы proxy_no_cache, fastcgi_no_cache,
+ uwsgi_no_cache и sсgi_no_cache теперь влияют только на сохранение
+ закэшированного ответа.
+
+ *) Добавление: директивы proxy_cache_bypass, fastcgi_cache_bypass,
+ uwsgi_cache_bypass и sсgi_cache_bypass.
+
+ *) Исправление: nginx не освобождал память в keys_zone кэшей в случае
+ ошибки работы с бэкендом: память освобождалась только по истечении
+ времени неактивности или при недостатке памяти.
+
+
Изменения в nginx 0.8.45 13.07.2010
*) Добавление: улучшения в модуле ngx_http_xslt_filter.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index e9247e94b..64f7b18a5 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 8045
-#define NGINX_VERSION "0.8.45"
+#define nginx_version 8046
+#define NGINX_VERSION "0.8.46"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 16d2bf8a0..4731f784f 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -330,9 +330,16 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
0,
&ngx_http_fastcgi_module },
+ { ngx_string("fastcgi_cache_bypass"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_http_set_predicate_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_bypass),
+ NULL },
+
{ 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_set_predicate_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache),
NULL },
@@ -1985,6 +1992,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
#if (NGX_HTTP_CACHE)
conf->upstream.cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+ conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
#endif
@@ -2208,9 +2216,18 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
+ ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
+ prev->upstream.cache_bypass, NULL);
+
ngx_conf_merge_ptr_value(conf->upstream.no_cache,
prev->upstream.no_cache, NULL);
+ if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
+ ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+ "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, "
+ "now it should be used together with \"fastcgi_cache_bypass\"");
+ }
+
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
index fcae88e12..b067d60c6 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -339,9 +339,16 @@ static ngx_command_t ngx_http_proxy_commands[] = {
0,
&ngx_http_proxy_module },
+ { ngx_string("proxy_cache_bypass"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_http_set_predicate_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
+ NULL },
+
{ 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_set_predicate_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
NULL },
@@ -1678,6 +1685,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
#if (NGX_HTTP_CACHE)
conf->upstream.cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+ conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
#endif
@@ -1902,9 +1910,18 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|NGX_HTTP_UPSTREAM_FT_OFF;
}
+ ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
+ prev->upstream.cache_bypass, NULL);
+
ngx_conf_merge_ptr_value(conf->upstream.no_cache,
prev->upstream.no_cache, NULL);
+ if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
+ ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+ "\"proxy_no_cache\" functionality has been changed in 0.8.46, "
+ "now it should be used together with \"proxy_cache_bypass\"");
+ }
+
ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
prev->upstream.cache_valid, NULL);
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index c6d848e4b..9f89650b8 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -196,9 +196,16 @@ static ngx_command_t ngx_http_scgi_commands[] = {
0,
&ngx_http_scgi_module },
+ { ngx_string("scgi_cache_bypass"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_http_set_predicate_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_bypass),
+ NULL },
+
{ ngx_string("scgi_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_set_predicate_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_scgi_loc_conf_t, upstream.no_cache),
NULL },
@@ -1015,6 +1022,8 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
#if (NGX_HTTP_CACHE)
conf->upstream.cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+ conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
+ conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
#endif
@@ -1233,6 +1242,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
+ ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
+ prev->upstream.cache_bypass, NULL);
+
ngx_conf_merge_ptr_value(conf->upstream.no_cache,
prev->upstream.no_cache, NULL);
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 466d34be0..f27a3dc76 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -223,9 +223,16 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
0,
&ngx_http_uwsgi_module },
+ { ngx_string("uwsgi_cache_bypass"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_http_set_predicate_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
+ NULL },
+
{ ngx_string("uwsgi_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_set_predicate_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
NULL },
@@ -1068,6 +1075,8 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
#if (NGX_HTTP_CACHE)
conf->upstream.cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+ conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
+ conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
#endif
@@ -1286,6 +1295,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
+ ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
+ prev->upstream.cache_bypass, NULL);
+
ngx_conf_merge_ptr_value(conf->upstream.no_cache,
prev->upstream.no_cache, NULL);
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index f8527658f..c720a23e8 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.8.45';
+our $VERSION = '0.8.46';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index 8f0032921..36b14b26e 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -14,11 +14,12 @@
#define NGX_HTTP_CACHE_MISS 1
-#define NGX_HTTP_CACHE_EXPIRED 2
-#define NGX_HTTP_CACHE_STALE 3
-#define NGX_HTTP_CACHE_UPDATING 4
-#define NGX_HTTP_CACHE_HIT 5
-#define NGX_HTTP_CACHE_SCARCE 6
+#define NGX_HTTP_CACHE_BYPASS 2
+#define NGX_HTTP_CACHE_EXPIRED 3
+#define NGX_HTTP_CACHE_STALE 4
+#define NGX_HTTP_CACHE_UPDATING 5
+#define NGX_HTTP_CACHE_HIT 6
+#define NGX_HTTP_CACHE_SCARCE 7
#define NGX_HTTP_CACHE_KEY_LEN 16
@@ -121,6 +122,8 @@ struct ngx_http_file_cache_s {
};
+ngx_int_t ngx_http_file_cache_new(ngx_http_request_t *r);
+ngx_int_t ngx_http_file_cache_create(ngx_http_request_t *r);
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);
@@ -134,10 +137,6 @@ char *ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
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
index 277475179..2fefe095b 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -19,6 +19,8 @@ static void ngx_http_cache_aio_event_handler(ngx_event_t *ev);
#endif
static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache,
ngx_http_cache_t *c);
+static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r,
+ ngx_path_t *path);
static ngx_http_file_cache_node_t *
ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key);
static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
@@ -44,6 +46,7 @@ static ngx_int_t ngx_http_file_cache_delete_file(ngx_tree_ctx_t *ctx,
ngx_str_t ngx_http_cache_status[] = {
ngx_string("MISS"),
+ ngx_string("BYPASS"),
ngx_string("EXPIRED"),
ngx_string("STALE"),
ngx_string("UPDATING"),
@@ -142,6 +145,59 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
}
+ngx_int_t
+ngx_http_file_cache_new(ngx_http_request_t *r)
+{
+ ngx_http_cache_t *c;
+
+ c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
+ if (c == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ r->cache = c;
+ c->file.log = r->connection->log;
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_http_file_cache_create(ngx_http_request_t *r)
+{
+ ngx_http_cache_t *c;
+ ngx_pool_cleanup_t *cln;
+ ngx_http_file_cache_t *cache;
+
+ ngx_http_file_cache_create_key(r);
+
+ c = r->cache;
+ cache = c->file_cache;
+
+ cln = ngx_pool_cleanup_add(r->pool, 0);
+ if (cln == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ cln->handler = ngx_http_file_cache_cleanup;
+ cln->data = c;
+
+ if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
void
ngx_http_file_cache_create_key(ngx_http_request_t *r)
{
@@ -180,10 +236,8 @@ ngx_http_file_cache_create_key(ngx_http_request_t *r)
ngx_int_t
ngx_http_file_cache_open(ngx_http_request_t *r)
{
- u_char *p;
ngx_int_t rc, rv;
ngx_uint_t cold, test;
- ngx_path_t *path;
ngx_http_cache_t *c;
ngx_pool_cleanup_t *cln;
ngx_open_file_info_t of;
@@ -249,27 +303,10 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
}
}
- path = cache->path;
-
- c->file.name.len = path->name.len + 1 + path->len
- + 2 * NGX_HTTP_CACHE_KEY_LEN;
-
- c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
- if (c->file.name.data == NULL) {
+ if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
return NGX_ERROR;
}
- ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
-
- p = c->file.name.data + path->name.len + 1 + path->len;
- p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
- *p = '\0';
-
- ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
- "cache file: \"%s\"", c->file.name.data);
-
if (!test) {
return NGX_DECLINED;
}
@@ -574,6 +611,37 @@ failed:
}
+static ngx_int_t
+ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
+{
+ u_char *p;
+ ngx_http_cache_t *c;
+
+ c = r->cache;
+
+ c->file.name.len = path->name.len + 1 + path->len
+ + 2 * NGX_HTTP_CACHE_KEY_LEN;
+
+ c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
+ if (c->file.name.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
+
+ p = c->file.name.data + path->name.len + 1 + path->len;
+ p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
+ *p = '\0';
+
+ ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "cache file: \"%s\"", c->file.name.data);
+
+ return NGX_OK;
+}
+
+
static ngx_http_file_cache_node_t *
ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key)
{
@@ -835,8 +903,9 @@ ngx_http_cache_send(ngx_http_request_t *r)
void
ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf)
{
- ngx_http_cache_t *c;
- ngx_http_file_cache_t *cache;
+ ngx_http_cache_t *c;
+ ngx_http_file_cache_t *cache;
+ ngx_http_file_cache_node_t *fcn;
c = r->cache;
@@ -853,15 +922,21 @@ ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf)
ngx_shmtx_lock(&cache->shpool->mutex);
- c->node->count--;
+ fcn = c->node;
+ fcn->count--;
+ fcn->updating = 0;
if (c->error) {
- c->node->valid_sec = c->valid_sec;
- c->node->valid_msec = c->valid_msec;
- c->node->error = c->error;
- }
+ fcn->valid_sec = c->valid_sec;
+ fcn->valid_msec = c->valid_msec;
+ fcn->error = c->error;
- c->node->updating = 0;
+ } else if (fcn->valid_msec == 0 && fcn->count == 0) {
+ ngx_queue_remove(&fcn->queue);
+ ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
+ ngx_slab_free_locked(cache->shpool, fcn);
+ c->node = NULL;
+ }
ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -1104,9 +1179,7 @@ ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q,
*p = '\0';
ngx_queue_remove(q);
-
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
-
ngx_slab_free_locked(cache->shpool, fcn);
ngx_shmtx_unlock(&cache->shpool->mutex);
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 1f4288969..1474f3245 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -211,6 +211,76 @@ ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
}
+ngx_int_t
+ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
+{
+ ngx_str_t val;
+ ngx_uint_t i;
+ ngx_http_complex_value_t *cv;
+
+ if (predicates == NULL) {
+ return NGX_OK;
+ }
+
+ cv = predicates->elts;
+
+ for (i = 0; i < predicates->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_set_predicate_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;
+}
+
+
ngx_uint_t
ngx_http_script_variables_count(ngx_str_t *value)
{
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index f7943d37c..d741ceabb 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -208,6 +208,11 @@ ngx_int_t ngx_http_complex_value(ngx_http_request_t *r,
ngx_http_complex_value_t *val, ngx_str_t *value);
ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
+ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r,
+ ngx_array_t *predicates);
+char *ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value);
ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc);
u_char *ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 44b8b947c..8ee5aeabd 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -633,11 +633,17 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (c == NULL) {
- if (u->conf->no_cache) {
- rc = ngx_http_cache(r, u->conf->no_cache);
- if (rc != NGX_OK) {
- return rc;
- }
+ switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
+
+ case NGX_ERROR:
+ return NGX_ERROR;
+
+ case NGX_DECLINED:
+ u->cache_status = NGX_HTTP_CACHE_BYPASS;
+ return NGX_DECLINED;
+
+ default: /* NGX_OK */
+ break;
}
if (!(r->method & u->conf->cache_methods)) {
@@ -648,18 +654,10 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->method = ngx_http_core_get_method;
}
- c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
- if (c == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
+ if (ngx_http_file_cache_new(r) != NGX_OK) {
return NGX_ERROR;
}
- r->cache = c;
- c->file.log = r->connection->log;
-
if (u->create_key(r) != NGX_OK) {
return NGX_ERROR;
}
@@ -670,6 +668,8 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->cacheable = 1;
+ c = r->cache;
+
c->min_uses = u->conf->cache_min_uses;
c->body_start = u->conf->buffer_size;
c->file_cache = u->conf->cache->data;
@@ -2098,6 +2098,47 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->cache->file.fd = NGX_INVALID_FILE;
}
+ switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
+
+ case NGX_ERROR:
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+
+ case NGX_DECLINED:
+ u->cacheable = 0;
+ break;
+
+ default: /* NGX_OK */
+
+ if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
+
+ if (ngx_http_file_cache_new(r) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ if (u->create_key(r) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ /* TODO: add keys */
+
+ r->cache->min_uses = u->conf->cache_min_uses;
+ r->cache->body_start = u->conf->buffer_size;
+ r->cache->file_cache = u->conf->cache->data;
+
+ if (ngx_http_file_cache_create(r) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ u->cacheable = 1;
+ }
+
+ break;
+ }
+
if (u->cacheable) {
time_t now, valid;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index bcdfc5fdd..ef460a488 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -163,7 +163,8 @@ typedef struct {
ngx_uint_t cache_methods;
ngx_array_t *cache_valid;
- ngx_array_t *no_cache; /* ngx_http_complex_value_t */
+ ngx_array_t *cache_bypass;
+ ngx_array_t *no_cache;
#endif
ngx_array_t *store_lengths;