r1354 merge:
named location
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index c999ade..c8dca82 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -2275,13 +2275,17 @@
plcf->upstream.location = clcf->name;
+ if (clcf->named
#if (NGX_PCRE)
-
- if (clcf->regex || clcf->noname) {
+ || clcf->regex
+#endif
+ || clcf->noname)
+ {
if (plcf->upstream.uri.len) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"proxy_pass\" may not have URI part in "
"location given by regular expression, "
+ "or inside named location, "
"or inside the \"if\" statement, "
"or inside the \"limit_except\" block");
return NGX_CONF_ERROR;
@@ -2290,8 +2294,6 @@
plcf->upstream.location.len = 0;
}
-#endif
-
plcf->upstream.url = *url;
if (clcf->name.data[clcf->name.len - 1] == '/') {
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index c6bc6c5..6c5acd9 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -402,6 +402,7 @@
cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
+ cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
find_config_index = 0;
use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
@@ -443,6 +444,14 @@
continue;
+ case NGX_HTTP_REWRITE_PHASE:
+ if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
+ cmcf->phase_engine.location_rewrite_index = n;
+ }
+ checker = ngx_http_core_generic_phase;
+
+ break;
+
case NGX_HTTP_POST_REWRITE_PHASE:
if (use_rewrite) {
ph->checker = ngx_http_core_post_rewrite_phase;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index c8b6994..8f36cae 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -945,13 +945,12 @@
clcfp = locations->elts;
for (i = 0; i < locations->nelts; i++) {
+ if (clcfp[i]->noname
#if (NGX_PCRE)
- if (clcfp[i]->regex) {
- break;
- }
+ || clcfp[i]->regex
#endif
-
- if (clcfp[i]->noname) {
+ || clcfp[i]->named)
+ {
break;
}
@@ -1028,7 +1027,7 @@
for (i = regex_start; i < locations->nelts; i++) {
- if (clcfp[i]->noname) {
+ if (!clcfp[i]->regex) {
break;
}
@@ -1513,6 +1512,51 @@
}
+ngx_int_t
+ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
+{
+ ngx_uint_t i;
+ ngx_http_core_srv_conf_t *cscf;
+ ngx_http_core_loc_conf_t **clcfp;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
+ clcfp = cscf->locations.elts;
+
+ for (i = cscf->named_start; i < cscf->locations.nelts; i++) {
+
+ if (name->len != clcfp[i]->name.len
+ || ngx_strncmp(name->data, clcfp[i]->name.data, name->len) != 0)
+ {
+ continue;
+ }
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "named location: %V \"%V?%V\"", name, &r->uri, &r->args);
+
+ r->internal = 1;
+
+ r->loc_conf = clcfp[i]->loc_conf;
+
+ ngx_http_update_location_config(r);
+
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ r->phase_handler = cmcf->phase_engine.location_rewrite_index;
+ ngx_http_core_run_phases(r);
+
+ return NGX_DONE;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "could not find name location \"%V\"", name);
+
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_DONE;
+}
+
+
ngx_http_cleanup_t *
ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
{
@@ -1557,10 +1601,8 @@
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx, *http_ctx;
ngx_http_core_srv_conf_t *cscf, **cscfp;
- ngx_http_core_main_conf_t *cmcf;
-#if (NGX_PCRE)
ngx_http_core_loc_conf_t **clcfp;
-#endif
+ ngx_http_core_main_conf_t *cmcf;
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
if (ctx == NULL) {
@@ -1644,10 +1686,11 @@
ngx_sort(cscf->locations.elts, (size_t) cscf->locations.nelts,
sizeof(ngx_http_core_loc_conf_t *), ngx_http_core_cmp_locations);
+ clcfp = cscf->locations.elts;
+
#if (NGX_PCRE)
cscf->regex_start = cscf->locations.nelts;
- clcfp = cscf->locations.elts;
for (i = 0; i < cscf->locations.nelts; i++) {
if (clcfp[i]->regex) {
@@ -1658,6 +1701,15 @@
#endif
+ cscf->named_start = cscf->locations.nelts;
+
+ for (i = 0; i < cscf->locations.nelts; i++) {
+ if (clcfp[i]->named) {
+ cscf->named_start = i;
+ break;
+ }
+ }
+
return rv;
}
@@ -1758,7 +1810,12 @@
}
} else {
+
clcf->name = value[1];
+
+ if (value[1].data[0] == '@') {
+ clcf->named = 1;
+ }
}
pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
@@ -1784,6 +1841,14 @@
return NGX_CONF_ERROR;
}
+ if (pclcf->named) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "location \"%V\" could not be inside "
+ "the named location \"%V\"",
+ &clcf->name, &pclcf->name);
+ return NGX_CONF_ERROR;
+ }
+
#if (NGX_PCRE)
if (clcf->regex == NULL
&& ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
@@ -1861,6 +1926,20 @@
first = *(ngx_http_core_loc_conf_t **) one;
second = *(ngx_http_core_loc_conf_t **) two;
+ if (first->named && !second->named) {
+ /* shift named locations to the end */
+ return 1;
+ }
+
+ if (!first->named && second->named) {
+ /* shift named locations to the end */
+ return -1;
+ }
+
+ if (first->named && second->named) {
+ return ngx_strcmp(first->name.data, second->name.data);
+ }
+
if (first->noname && !second->noname) {
/* shift no named locations to the end */
return 1;
@@ -2706,6 +2785,14 @@
return NGX_CONF_ERROR;
}
+ if (lcf->named && alias) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"alias\" directive may not be used "
+ "inside named location");
+
+ return NGX_CONF_ERROR;
+ }
+
#if (NGX_PCRE)
if (lcf->regex && alias) {
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index db1e043..5e9b483 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -79,6 +79,7 @@
typedef struct {
ngx_http_phase_handler_t *handlers;
ngx_uint_t server_rewrite_index;
+ ngx_uint_t location_rewrite_index;
} ngx_http_phase_engine_t;
@@ -117,7 +118,8 @@
*/
ngx_array_t locations;
- unsigned regex_start:16;
+ unsigned regex_start:15;
+ unsigned named_start:15;
unsigned wildcard:1;
/* array of the ngx_http_listen_t, "listen" directive */
@@ -211,9 +213,10 @@
ngx_regex_t *regex;
#endif
- unsigned regex_start:16;
+ unsigned regex_start:15;
- unsigned noname:1; /* "if () {}" block */
+ unsigned noname:1; /* "if () {}" block or limit_except */
+ unsigned named:1;
unsigned exact_match:1;
unsigned noregex:1;
@@ -313,6 +316,8 @@
ngx_http_post_subrequest_t *psr, ngx_uint_t flags);
ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args);
+ngx_int_t ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name);
+
ngx_http_cleanup_t *ngx_http_cleanup_add(ngx_http_request_t *r, size_t size);
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 2598116..1797603 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -409,6 +409,10 @@
return ngx_http_internal_redirect(r, uri, NULL);
}
+ if (uri->data[0] == '@') {
+ return ngx_http_named_location(r, uri);
+ }
+
r->headers_out.location =
ngx_list_push(&r->headers_out.headers);