summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2011-12-26 15:47:52 +0000
committerJonathan Kolb <jon@b0g.us>2011-12-26 15:47:52 +0000
commit009625684c294b0d8512d4dc70749d88b161de25 (patch)
tree0787ee0cd662c479e1903251e8800056441270ce /src/http
parentf3f84820db369aade03ed922872e206760e0ce0f (diff)
downloadnginx-009625684c294b0d8512d4dc70749d88b161de25.tar.gz
Changes with nginx 1.1.12 26 Dec 2011v1.1.12
*) Change: a "proxy_pass" directive without URI part now uses changed URI after redirection with the "error_page" directive. Thanks to Lanshun Zhou. *) Feature: the "proxy/fastcgi/scgi/uwsgi_cache_lock", "proxy/fastcgi/scgi/uwsgi_cache_lock_timeout" directives. *) Feature: the "pcre_jit" directive. *) Feature: the "if" SSI command supports captures in regular expressions. *) Bugfix: the "if" SSI command did not work inside the "block" command. *) Bugfix: the "limit_conn_log_level" and "limit_req_log_level" directives might not work. *) Bugfix: the "limit_rate" directive did not allow to use full throughput, even if limit value was very high. *) Bugfix: the "sendfile_max_chunk" directive did not work, if the "limit_rate" directive was used. *) Bugfix: a "proxy_pass" directive without URI part always used original request URI if variables were used. *) Bugfix: a "proxy_pass" directive without URI part might use original request after redirection with the "try_files" directive. Thanks to Lanshun Zhou. *) Bugfix: in the ngx_http_scgi_module. *) Bugfix: in the ngx_http_mp4_module. *) Bugfix: nginx could not be built on Solaris; the bug had appeared in 1.1.9. Maxim Dounin _______________________________________________ nginx-announce mailing list nginx-announce@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-announce
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c22
-rw-r--r--src/http/modules/ngx_http_limit_conn_module.c2
-rw-r--r--src/http/modules/ngx_http_limit_req_module.c2
-rw-r--r--src/http/modules/ngx_http_mp4_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c31
-rw-r--r--src/http/modules/ngx_http_scgi_module.c38
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c191
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.h6
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c22
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_cache.h8
-rw-r--r--src/http/ngx_http_core_module.c1
-rw-r--r--src/http/ngx_http_file_cache.c159
-rw-r--r--src/http/ngx_http_upstream.c5
-rw-r--r--src/http/ngx_http_upstream.h3
-rw-r--r--src/http/ngx_http_write_filter_module.c20
16 files changed, 429 insertions, 85 deletions
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 599edc77c..f976b7aea 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -380,6 +380,20 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("fastcgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("fastcgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("fastcgi_temp_path"),
@@ -2086,6 +2100,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -2323,6 +2339,12 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c
index a84d54d7e..40f05a22e 100644
--- a/src/http/modules/ngx_http_limit_conn_module.c
+++ b/src/http/modules/ngx_http_limit_conn_module.c
@@ -483,7 +483,7 @@ ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_limit_conn_conf_t *conf = child;
if (conf->limits.elts == NULL) {
- *conf = *prev;
+ conf->limits = prev->limits;
}
ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c
index 718fae8e2..865f7666d 100644
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -569,7 +569,7 @@ ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_limit_req_conf_t *conf = child;
if (conf->shm_zone == NULL) {
- *conf = *prev;
+ conf->shm_zone = prev->shm_zone;
}
ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 3c9f88cfc..7bfb3db66 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -2382,6 +2382,8 @@ found:
data->pos = (u_char *) entry;
atom_size = sizeof(ngx_mp4_stsc_atom_t) + (data->last - data->pos);
+ ngx_mp4_set_32value(entry->chunk, 1);
+
if (trak->chunk_samples) {
first = &trak->stsc_chunk_entry;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5ce875f62..b65093b72 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -402,6 +402,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("proxy_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("proxy_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("proxy_temp_path"),
@@ -736,9 +750,6 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
url.uri.len++;
url.uri.data = p - 1;
}
-
- } else {
- url.uri = r->unparsed_uri;
}
ctx->vars.key_start = u->schema;
@@ -806,7 +817,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
*key = ctx->vars.uri;
u->uri = ctx->vars.uri;
@@ -916,7 +927,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
loc_len = 0;
unparsed_uri = 0;
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
uri_len = ctx->vars.uri.len;
} else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
@@ -1022,7 +1033,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
u->uri.data = b->last;
- if (plcf->proxy_lengths) {
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
} else if (unparsed_uri) {
@@ -2438,6 +2449,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -2684,6 +2697,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
if (conf->method.len == 0) {
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 41cf23bc6..9fd60147e 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -36,7 +36,6 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
@@ -247,6 +246,20 @@ static ngx_command_t ngx_http_scgi_commands[] = {
offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("scgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("scgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("scgi_temp_path"),
@@ -857,11 +870,7 @@ ngx_http_scgi_process_status_line(ngx_http_request_t *r)
}
if (rc == NGX_ERROR) {
-
- r->http_version = NGX_HTTP_VERSION_9;
-
u->process_header = ngx_http_scgi_process_header;
-
return ngx_http_scgi_process_header(r);
}
@@ -961,12 +970,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http scgi header done");
- if (r->http_version > NGX_HTTP_VERSION_9) {
+ u = r->upstream;
+
+ if (u->headers_in.status_n) {
return NGX_OK;
}
- u = r->upstream;
-
if (u->headers_in.status) {
status_line = &u->headers_in.status->value;
@@ -978,20 +987,15 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
- r->http_version = NGX_HTTP_VERSION_10;
u->headers_in.status_n = status;
u->headers_in.status_line = *status_line;
} else if (u->headers_in.location) {
- r->http_version = NGX_HTTP_VERSION_10;
u->headers_in.status_n = 302;
ngx_str_set(&u->headers_in.status_line,
"302 Moved Temporarily");
} else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent neither valid HTTP/1.0 header "
- "nor \"Status\" header line");
u->headers_in.status_n = 200;
ngx_str_set(&u->headers_in.status_line, "200 OK");
}
@@ -1072,6 +1076,8 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1299,6 +1305,12 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 0b8bc9bf8..e33782166 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -78,6 +78,8 @@ static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
ngx_str_t *name, ngx_uint_t key);
static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
+static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
+ ngx_str_t *pattern, ngx_str_t *str);
static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
@@ -624,16 +626,6 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
continue;
}
- if (cmd->conditional
- && (ctx->conditional == 0
- || ctx->conditional > cmd->conditional))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid context of SSI command: \"%V\"",
- &ctx->command);
- goto ssi_error;
- }
-
if (!ctx->output && !cmd->block) {
if (ctx->block) {
@@ -709,6 +701,16 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
+ if (cmd->conditional
+ && (ctx->conditional == 0
+ || ctx->conditional > cmd->conditional))
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid context of SSI command: \"%V\"",
+ &ctx->command);
+ goto ssi_error;
+ }
+
if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"too many SSI command paramters: \"%V\"",
@@ -1531,6 +1533,30 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+#if (NGX_PCRE)
+ {
+ ngx_str_t *value;
+
+ if (key >= '0' && key <= '9') {
+ i = key - '0';
+
+ if (i < ctx->ncaptures) {
+ value = ngx_palloc(r->pool, sizeof(ngx_str_t));
+ if (value == NULL) {
+ return NULL;
+ }
+
+ i *= 2;
+
+ value->data = ctx->captures_data + ctx->captures[i];
+ value->len = ctx->captures[i + 1] - ctx->captures[i];
+
+ return value;
+ }
+ }
+ }
+#endif
+
if (ctx->variables == NULL) {
return NULL;
}
@@ -1820,6 +1846,115 @@ invalid_variable:
static ngx_int_t
+ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
+ ngx_str_t *str)
+{
+#if (NGX_PCRE)
+ int rc, *captures;
+ u_char *p, errstr[NGX_MAX_CONF_ERRSTR];
+ size_t size;
+ ngx_int_t key;
+ ngx_str_t *vv, name, value;
+ ngx_uint_t i, n;
+ ngx_http_ssi_ctx_t *ctx;
+ ngx_http_ssi_var_t *var;
+ ngx_regex_compile_t rgc;
+
+ ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
+
+ rgc.pattern = *pattern;
+ rgc.pool = r->pool;
+ rgc.err.len = NGX_MAX_CONF_ERRSTR;
+ rgc.err.data = errstr;
+
+ if (ngx_regex_compile(&rgc) != NGX_OK) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ n = (rgc.captures + 1) * 3;
+
+ captures = ngx_palloc(r->pool, n * sizeof(int));
+ if (captures == NULL) {
+ return NGX_ERROR;
+ }
+
+ rc = ngx_regex_exec(rgc.regex, str, captures, n);
+
+ if (rc < NGX_REGEX_NO_MATCHED) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+ rc, str, pattern);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (rc == NGX_REGEX_NO_MATCHED) {
+ return NGX_DECLINED;
+ }
+
+ ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+ ctx->ncaptures = rc;
+ ctx->captures = captures;
+ ctx->captures_data = str->data;
+
+ if (rgc.named_captures > 0) {
+
+ if (ctx->variables == NULL) {
+ ctx->variables = ngx_list_create(r->pool, 4,
+ sizeof(ngx_http_ssi_var_t));
+ if (ctx->variables == NULL) {
+ return NGX_ERROR;
+ }
+ }
+
+ size = rgc.name_size;
+ p = rgc.names;
+
+ for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) {
+
+ name.data = &p[2];
+ name.len = ngx_strlen(name.data);
+
+ n = 2 * ((p[0] << 8) + p[1]);
+
+ value.data = &str->data[captures[n]];
+ value.len = captures[n + 1] - captures[n];
+
+ key = ngx_hash_strlow(name.data, name.data, name.len);
+
+ vv = ngx_http_ssi_get_variable(r, &name, key);
+
+ if (vv) {
+ *vv = value;
+ continue;
+ }
+
+ var = ngx_list_push(ctx->variables);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->name = name;
+ var->key = key;
+ var->value = value;
+ }
+ }
+
+ return NGX_OK;
+
+#else
+
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the using of the regex \"%V\" in SSI requires PCRE library",
+ pattern);
+ return NGX_HTTP_SSI_ERROR;
+
+#endif
+}
+
+
+static ngx_int_t
ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
@@ -2451,39 +2586,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
} else {
-#if (NGX_PCRE)
- ngx_regex_compile_t rgc;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
right.data[right.len] = '\0';
- ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
-
- rgc.pattern = right;
- rgc.pool = r->pool;
- rgc.err.len = NGX_MAX_CONF_ERRSTR;
- rgc.err.data = errstr;
-
- if (ngx_regex_compile(&rgc) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
- return NGX_HTTP_SSI_ERROR;
- }
+ rc = ngx_http_ssi_regex_match(r, &right, &left);
- rc = ngx_regex_exec(rgc.regex, &left, NULL, 0);
-
- if (rc < NGX_REGEX_NO_MATCHED) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
- rc, &left, &right);
- return NGX_HTTP_SSI_ERROR;
+ if (rc == NGX_OK) {
+ rc = 0;
+ } else if (rc == NGX_DECLINED) {
+ rc = -1;
+ } else {
+ return rc;
}
-#else
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the using of the regex \"%V\" in SSI "
- "requires PCRE library", &right);
-
- return NGX_HTTP_SSI_ERROR;
-#endif
}
if ((rc == 0 && !negative) || (rc != 0 && negative)) {
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 6ab18841c..2b0018662 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -64,6 +64,12 @@ typedef struct {
ngx_list_t *variables;
ngx_array_t *blocks;
+#if (NGX_PCRE)
+ ngx_uint_t ncaptures;
+ int *captures;
+ u_char *captures_data;
+#endif
+
unsigned conditional:2;
unsigned encoding:2;
unsigned block:1;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 2916a5916..86959b3e3 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -274,6 +274,20 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
&ngx_http_upstream_cache_method_mask },
+ { ngx_string("uwsgi_cache_lock"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
+ NULL },
+
+ { ngx_string("uwsgi_cache_lock_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
+ NULL },
+
#endif
{ ngx_string("uwsgi_temp_path"),
@@ -1114,6 +1128,8 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1341,6 +1357,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->cache_key = prev->cache_key;
}
+ ngx_conf_merge_value(conf->upstream.cache_lock,
+ prev->upstream.cache_lock, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
+ prev->upstream.cache_lock_timeout, 5000);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index ec49d7bad..8cd3b7469 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 = '1.1.11';
+our $VERSION = '1.1.12';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index bd02100da..ae8b8c376 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -79,6 +79,14 @@ struct ngx_http_cache_s {
ngx_http_file_cache_t *file_cache;
ngx_http_file_cache_node_t *node;
+ ngx_msec_t lock_timeout;
+ ngx_msec_t wait_time;
+
+ ngx_event_t wait_event;
+
+ unsigned lock:1;
+ unsigned waiting:1;
+
unsigned updated:1;
unsigned updating:1;
unsigned exists:1;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 3c5711748..1d5ee5dc6 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2506,6 +2506,7 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
#endif
r->internal = 1;
+ r->valid_unparsed_uri = 0;
r->add_uri_to_alias = 0;
r->main->count++;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 050f356f1..dccbbac68 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -10,6 +10,9 @@
#include <ngx_md5.h>
+static ngx_int_t ngx_http_file_cache_lock(ngx_http_request_t *r,
+ ngx_http_cache_t *c);
+static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev);
static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r,
ngx_http_cache_t *c);
static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r,
@@ -181,13 +184,13 @@ ngx_http_file_cache_create(ngx_http_request_t *r)
return NGX_ERROR;
}
+ cln->handler = ngx_http_file_cache_cleanup;
+ cln->data = c;
+
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;
}
@@ -244,15 +247,24 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
c = r->cache;
+ if (c->waiting) {
+ return NGX_AGAIN;
+ }
+
if (c->buf) {
return ngx_http_file_cache_read(r, c);
}
cache = c->file_cache;
- cln = ngx_pool_cleanup_add(r->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
+ if (c->node == NULL) {
+ cln = ngx_pool_cleanup_add(r->pool, 0);
+ if (cln == NULL) {
+ return NGX_ERROR;
+ }
+
+ cln->handler = ngx_http_file_cache_cleanup;
+ cln->data = c;
}
rc = ngx_http_file_cache_exists(cache, c);
@@ -264,9 +276,6 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
return rc;
}
- cln->handler = ngx_http_file_cache_cleanup;
- cln->data = c;
-
if (rc == NGX_AGAIN) {
return NGX_HTTP_CACHE_SCARCE;
}
@@ -306,7 +315,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
}
if (!test) {
- return NGX_DECLINED;
+ goto done;
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -330,7 +339,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
case NGX_ENOENT:
case NGX_ENOTDIR:
- return rv;
+ goto done;
default:
ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
@@ -354,6 +363,114 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
}
return ngx_http_file_cache_read(r, c);
+
+done:
+
+ if (rv == NGX_DECLINED) {
+ return ngx_http_file_cache_lock(r, c);
+ }
+
+ return rv;
+}
+
+
+static ngx_int_t
+ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
+ ngx_msec_t now, timer;
+ ngx_http_file_cache_t *cache;
+
+ if (!c->lock) {
+ return NGX_DECLINED;
+ }
+
+ cache = c->file_cache;
+
+ ngx_shmtx_lock(&cache->shpool->mutex);
+
+ if (!c->node->updating) {
+ c->node->updating = 1;
+ c->updating = 1;
+ }
+
+ ngx_shmtx_unlock(&cache->shpool->mutex);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http file cache lock u:%d wt:%M",
+ c->updating, c->wait_time);
+
+ if (c->updating) {
+ return NGX_DECLINED;
+ }
+
+ c->waiting = 1;
+
+ now = ngx_current_msec;
+
+ if (c->wait_time == 0) {
+ c->wait_time = now + c->lock_timeout;
+
+ c->wait_event.handler = ngx_http_file_cache_lock_wait_handler;
+ c->wait_event.data = r;
+ c->wait_event.log = r->connection->log;
+ }
+
+ timer = c->wait_time - now;
+
+ ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer);
+
+ r->main->blocked++;
+
+ return NGX_AGAIN;
+}
+
+
+static void
+ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
+{
+ ngx_uint_t wait;
+ ngx_msec_t timer;
+ ngx_http_cache_t *c;
+ ngx_http_request_t *r;
+ ngx_http_file_cache_t *cache;
+
+ r = ev->data;
+ c = r->cache;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+ "http file cache wait handler wt:%M cur:%M",
+ c->wait_time, ngx_current_msec);
+
+ timer = c->wait_time - ngx_current_msec;
+
+ if ((ngx_msec_int_t) timer <= 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+ "http file cache lock timeout");
+ c->lock = 0;
+ goto wakeup;
+ }
+
+ cache = c->file_cache;
+ wait = 0;
+
+ ngx_shmtx_lock(&cache->shpool->mutex);
+
+ if (c->node->updating) {
+ wait = 1;
+ }
+
+ ngx_shmtx_unlock(&cache->shpool->mutex);
+
+ if (wait) {
+ ngx_add_timer(ev, (timer > 500) ? 500 : timer);
+ return;
+ }
+
+wakeup:
+
+ c->waiting = 0;
+ r->main->blocked--;
+ r->connection->write->handler(r->connection->write);
}
@@ -518,13 +635,19 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
ngx_shmtx_lock(&cache->shpool->mutex);
- fcn = ngx_http_file_cache_lookup(cache, c->key);
+ fcn = c->node;
+
+ if (fcn == NULL) {
+ fcn = ngx_http_file_cache_lookup(cache, c->key);
+ }
if (fcn) {
ngx_queue_remove(&fcn->queue);
- fcn->uses++;
- fcn->count++;
+ if (c->node == NULL) {
+ fcn->uses++;
+ fcn->count++;
+ }
if (fcn->error) {
@@ -621,6 +744,10 @@ ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
c = r->cache;
+ if (c->file.name.len) {
+ return NGX_OK;
+ }
+
c->file.name.len = path->name.len + 1 + path->len
+ 2 * NGX_HTTP_CACHE_KEY_LEN;
@@ -957,6 +1084,10 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
}
}
}
+
+ if (c->wait_event.timer_set) {
+ ngx_del_timer(&c->wait_event);
+ }
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9f0ff3a54..781ef1f96 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -707,6 +707,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->body_start = u->conf->buffer_size;
c->file_cache = u->conf->cache->data;
+ c->lock = u->conf->cache_lock;
+ c->lock_timeout = u->conf->cache_lock_timeout;
+
u->cache_status = NGX_HTTP_CACHE_MISS;
}
@@ -1895,8 +1898,6 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->method = NGX_HTTP_GET;
}
- r->valid_unparsed_uri = 0;
-
ngx_http_internal_redirect(r, uri, &args);
ngx_http_finalize_request(r, NGX_DONE);
return NGX_DONE;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index fa93be69f..62cbf533e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -165,6 +165,9 @@ typedef struct {
ngx_uint_t cache_use_stale;
ngx_uint_t cache_methods;
+ ngx_flag_t cache_lock;
+ ngx_msec_t cache_lock_timeout;
+
ngx_array_t *cache_valid;
ngx_array_t *cache_bypass;
ngx_array_t *no_cache;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 46351349c..a9660ee1f 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -223,11 +223,14 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_AGAIN;
}
- } else if (clcf->sendfile_max_chunk) {
- limit = clcf->sendfile_max_chunk;
+ if (clcf->sendfile_max_chunk
+ && (off_t) clcf->sendfile_max_chunk < limit)
+ {
+ limit = clcf->sendfile_max_chunk;
+ }
} else {
- limit = 0;
+ limit = clcf->sendfile_max_chunk;
}
sent = c->sent;
@@ -262,17 +265,18 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
- delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate + 1);
+ delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
if (delay > 0) {
+ limit = 0;
c->write->delayed = 1;
ngx_add_timer(c->write, delay);
}
+ }
- } else if (c->write->ready
- && clcf->sendfile_max_chunk
- && (size_t) (c->sent - sent)
- >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
+ if (limit
+ && c->write->ready
+ && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
{
c->write->delayed = 1;
ngx_add_timer(c->write, 1);