diff options
author | Igor Sysoev <igor@sysoev.ru> | 2007-07-30 09:15:47 +0000 |
---|---|---|
committer | Jonathan Kolb <jon@b0g.us> | 2007-07-30 09:15:47 +0000 |
commit | ad5526a0773dea7fca82cca22433e2cb0b327837 (patch) | |
tree | 83f8ffae019ea0d39633c2c5520b3dfa6cfd47d2 /src/http | |
parent | b9b71bc11c42dce8b014ee3cf3a1f5dc7b9ecc2f (diff) | |
download | nginx-ad5526a0773dea7fca82cca22433e2cb0b327837.tar.gz |
Changes with nginx 0.6.6 30 Jul 2007v0.6.6
*) Feature: the --sysconfdir=PATH option in configure.
*) Feature: named locations.
*) Feature: the $args variable can be set with the "set" directive.
*) Feature: the $is_args variable.
*) Bugfix: fair big weight upstream balancer.
*) Bugfix: if a client has closed connection to mail proxy then nginx
might not close connection to backend.
*) Bugfix: if the same host without specified port was used as backend
for HTTP and HTTPS, then nginx used only one port - 80 or 443.
*) Bugfix: fix building on Solaris/amd64 by Sun Studio 11 and early
versions; bug appeared in 0.6.4.
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_auth_basic_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_geo_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_map_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 11 | ||||
-rw-r--r-- | src/http/modules/perl/nginx.pm | 2 | ||||
-rw-r--r-- | src/http/modules/perl/ngx_http_perl_module.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http.c | 9 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 116 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 11 | ||||
-rw-r--r-- | src/http/ngx_http_special_response.c | 4 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 6 | ||||
-rw-r--r-- | src/http/ngx_http_upstream_round_robin.c | 108 | ||||
-rw-r--r-- | src/http/ngx_http_upstream_round_robin.h | 8 | ||||
-rw-r--r-- | src/http/ngx_http_variables.c | 51 |
14 files changed, 269 insertions, 65 deletions
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index 19bfe996e..72b4bbdcb 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -352,7 +352,7 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } if (conf->user_file.data) { - if (ngx_conf_full_name(cf->cycle, &conf->user_file) != NGX_OK) { + if (ngx_conf_full_name(cf->cycle, &conf->user_file, 1) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index 62ef72cf9..9c43bd716 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -198,7 +198,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; - if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ + if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){ return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 4a8acd00d..7b3a363fc 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -378,7 +378,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; - if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ + if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){ return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index c999adea2..52f67b305 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2237,6 +2237,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (port == 80) { plcf->port.len = sizeof("80") - 1; plcf->port.data = (u_char *) "80"; + } else { plcf->port.len = sizeof("443") - 1; plcf->port.data = (u_char *) "443"; @@ -2275,13 +2276,17 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 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 +2295,6 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) plcf->upstream.location.len = 0; } -#endif - plcf->upstream.url = *url; if (clcf->name.data[clcf->name.len - 1] == '/') { diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm index f510f2df0..ca86b7840 100644 --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.6.5'; +our $VERSION = '0.6.6'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index 248f57823..836a415c9 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -454,7 +454,7 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) #endif if (pmcf->modules.data) { - if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) { + if (ngx_conf_full_name(cf->cycle, &pmcf->modules, 0) != NGX_OK) { return NGX_CONF_ERROR; } } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 5823a2b91..dfe6eff70 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -401,6 +401,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 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; @@ -442,6 +443,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 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 a903c9a24..0e732cfe2 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -945,13 +945,12 @@ ngx_http_core_find_location(ngx_http_request_t *r, 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 @@ ngx_http_core_find_location(ngx_http_request_t *r, for (i = regex_start; i < locations->nelts; i++) { - if (clcfp[i]->noname) { + if (!clcfp[i]->regex) { break; } @@ -1223,7 +1222,8 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path, return NULL; } - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path) == NGX_ERROR) { + if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0)== NGX_ERROR) + { return NULL; } @@ -1513,6 +1513,51 @@ ngx_http_internal_redirect(ngx_http_request_t *r, } +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 +1602,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) 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 +1687,11 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) 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 +1702,15 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) #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 +1811,12 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) } } 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 +1842,14 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) 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 +1927,20 @@ ngx_http_core_cmp_locations(const void *one, const void *two) 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; @@ -1947,7 +2027,7 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; - if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ + if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){ return NGX_CONF_ERROR; } @@ -2290,7 +2370,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->root.len = sizeof("html") - 1; conf->root.data = (u_char *) "html"; - if (ngx_conf_full_name(cf->cycle, &conf->root) == NGX_ERROR) { + if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) { return NGX_CONF_ERROR; } } @@ -2706,6 +2786,14 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 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) { @@ -2739,7 +2827,7 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } if (lcf->root.data[0] != '$') { - if (ngx_conf_full_name(cf->cycle, &lcf->root) == NGX_ERROR) { + if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) { return NGX_CONF_ERROR; } } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 59e4624a9..dc443f64a 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -79,6 +79,7 @@ struct ngx_http_phase_handler_s { 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 @@ typedef struct { */ 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 */ @@ -212,9 +214,10 @@ struct ngx_http_core_loc_conf_s { 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; @@ -314,6 +317,8 @@ ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, 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 2598116f7..1797603a0 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -409,6 +409,10 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) 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); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 376b85fcd..bc4567458 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3209,6 +3209,12 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) continue; } + if (uscfp[i]->default_port && u->default_port + && uscfp[i]->default_port != u->default_port) + { + continue; + } + return uscfp[i]; } diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index af90d1d59..6756d2bc2 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -9,6 +9,10 @@ #include <ngx_http.h> +static ngx_uint_t +ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers); + + ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) @@ -215,7 +219,12 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) /* it's a first try - get a current peer */ for ( ;; ) { - rrp->current = rrp->peers->current; + rrp->current = ngx_http_upstream_get_peer(rrp->peers); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get rr peer, current: %ui %i", + rrp->current, + rrp->peers->peer[rrp->current].current_weight); n = rrp->current / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); @@ -236,6 +245,8 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) break; } + peer->current_weight = 0; + } else { rrp->tried[n] |= m; } @@ -243,12 +254,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) pc->tries--; } - rrp->peers->current++; - - if (rrp->peers->current >= rrp->peers->number) { - rrp->peers->current = 0; - } - if (pc->tries) { continue; } @@ -258,16 +263,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) peer->current_weight--; - if (peer->current_weight == 0) { - peer->current_weight = peer->weight; - - rrp->peers->current++; - - if (rrp->peers->current >= rrp->peers->number) { - rrp->peers->current = 0; - } - } - } else { for ( ;; ) { n = rrp->current / (8 * sizeof(uintptr_t)); @@ -290,6 +285,8 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) break; } + peer->current_weight = 0; + } else { rrp->tried[n] |= m; } @@ -311,18 +308,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) } peer->current_weight--; - - if (peer->current_weight == 0) { - peer->current_weight = peer->weight; - - if (rrp->current == rrp->peers->current) { - rrp->peers->current++; - - if (rrp->peers->current >= rrp->peers->number) { - rrp->peers->current = 0; - } - } - } } rrp->tried[n] |= m; @@ -352,6 +337,61 @@ failed: } +static ngx_uint_t +ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers) +{ + ngx_uint_t i, n; + ngx_http_upstream_rr_peer_t *peer; + + peer = &peers->peer[0]; + + for ( ;; ) { + + for (i = 0; i < peers->number; i++) { + + if (peer[i].current_weight <= 0) { + continue; + } + + n = i; + + while (i < peers->number - 1) { + + i++; + + if (peer[i].current_weight <= 0) { + continue; + } + + if (peer[n].current_weight * 1000 / peer[i].current_weight + >= peer[n].weight * 1000 / peer[i].weight) + { + return n; + } + + n = i; + } + + if (peer[i].current_weight > 0) { + n = i; + } + + return n; + } + + for (i = 0; i < peers->number; i++) { + if (peer[i].fails == 0) { + peer[i].current_weight += peer[i].weight; + + } else { + /* 1 allows to go to quick recovery when all peers failed */ + peer[i].current_weight = 1; + } + } + } +} + + void ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) @@ -385,8 +425,14 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, peer->fails++; peer->accessed = now; - if (peer->current_weight > 1) { - peer->current_weight /= 2; + peer->current_weight -= peer->weight / peer->max_fails; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "free rr peer failed: %ui %i", + rrp->current, peer->current_weight); + + if (peer->current_weight < 0) { + peer->current_weight = 0; } /* ngx_unlock_mutex(rrp->peers->mutex); */ diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h index 2e2bf132f..15e69153a 100644 --- a/src/http/ngx_http_upstream_round_robin.h +++ b/src/http/ngx_http_upstream_round_robin.h @@ -18,8 +18,8 @@ typedef struct { socklen_t socklen; ngx_str_t name; - ngx_uint_t current_weight; - ngx_uint_t weight; + ngx_int_t current_weight; + ngx_int_t weight; ngx_uint_t fails; time_t accessed; @@ -29,15 +29,13 @@ typedef struct { ngx_uint_t down; /* unsigned down:1; */ -#if (NGX_SSL) +#if (NGX_HTTP_SSL) ngx_ssl_session_t *ssl_session; /* local to a process */ #endif } ngx_http_upstream_rr_peer_t; typedef struct { - ngx_uint_t current; - ngx_uint_t number; ngx_uint_t last_cached; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index af54d29b0..123017d80 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -13,6 +13,8 @@ static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static void ngx_http_variable_request_set(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static void ngx_http_variable_request_set_size(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r, @@ -39,6 +41,8 @@ static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, @@ -155,9 +159,14 @@ static ngx_http_variable_t ngx_http_core_variables[] = { offsetof(ngx_http_request_t, args), NGX_HTTP_VAR_NOCACHABLE, 0 }, - { ngx_string("args"), NULL, ngx_http_variable_request, + { ngx_string("args"), + ngx_http_variable_request_set, + ngx_http_variable_request, offsetof(ngx_http_request_t, args), - NGX_HTTP_VAR_NOCACHABLE, 0 }, + NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOCACHABLE, 0 }, + + { ngx_string("is_args"), NULL, ngx_http_variable_is_args, + 0, NGX_HTTP_VAR_NOCACHABLE, 0 }, { ngx_string("request_filename"), NULL, ngx_http_variable_request_filename, 0, @@ -501,6 +510,19 @@ ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, static void +ngx_http_variable_request_set(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *s; + + s = (ngx_str_t *) ((char *) r + data); + + s->len = v->len; + s->data = v->data; +} + + +static void ngx_http_variable_request_set_size(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -860,6 +882,27 @@ ngx_http_variable_scheme(ngx_http_request_t *r, static ngx_int_t +ngx_http_variable_is_args(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + if (r->args.len == 0) { + v->len = 0; + v->data = NULL; + return NGX_OK; + } + + v->len = 1; + v->data = (u_char *) "?"; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -883,7 +926,9 @@ ngx_http_variable_document_root(ngx_http_request_t *r, return NGX_ERROR; } - if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path) == NGX_ERROR) { + if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) + == NGX_ERROR) + { return NGX_ERROR; } |