# HG changeset patch # User Igor Sysoev # Date 1187121729 0 # Node ID bf5b86d5f00e65efe5419114e919996e1843cb9d # Parent 6485121a080d38b78dc9e99a3d386b8de7cbd9b0 r1354 merge: named location diff -r 6485121a080d -r bf5b86d5f00e src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Sat Aug 11 10:17:02 2007 +0000 +++ b/src/http/modules/ngx_http_proxy_module.c Tue Aug 14 20:02:09 2007 +0000 @@ -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 -r 6485121a080d -r bf5b86d5f00e src/http/ngx_http.c --- a/src/http/ngx_http.c Sat Aug 11 10:17:02 2007 +0000 +++ b/src/http/ngx_http.c Tue Aug 14 20:02:09 2007 +0000 @@ -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 -r 6485121a080d -r bf5b86d5f00e src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Sat Aug 11 10:17:02 2007 +0000 +++ b/src/http/ngx_http_core_module.c Tue Aug 14 20:02:09 2007 +0000 @@ -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_loc_conf_t **clcfp; ngx_http_core_main_conf_t *cmcf; -#if (NGX_PCRE) - ngx_http_core_loc_conf_t **clcfp; -#endif 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 -r 6485121a080d -r bf5b86d5f00e src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Sat Aug 11 10:17:02 2007 +0000 +++ b/src/http/ngx_http_core_module.h Tue Aug 14 20:02:09 2007 +0000 @@ -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 -r 6485121a080d -r bf5b86d5f00e src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c Sat Aug 11 10:17:02 2007 +0000 +++ b/src/http/ngx_http_special_response.c Tue Aug 14 20:02:09 2007 +0000 @@ -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);