# HG changeset patch # User Maxim Dounin # Date 1323875605 0 # Node ID 94b995c7c6149c749c0450e63c6891c19c64ea51 # Parent efd515ace6bbda2a804a4fb99fbe75142af8bb44 Merge of r4275, r4276, r4278, r4279: Fixes for proxy_set_header, fastcgi/scgi/uwsgi_param inheritance: *) Fixed proxy_set_header inheritance with proxy_cache (ticket #45). Headers cleared with cache enabled (If-Modified-Since etc.) might be cleared in unrelated servers/locations without proxy_cache enabled if proxy_cache was used in some server/location. Example config which triggered the problem: proxy_set_header X-Test "test"; server { location /1 { proxy_cache name; proxy_pass ... } } server { location /2 { proxy_pass ... } } Another one: server { proxy_cache name; location /1 { proxy_pass ... } location /2 { proxy_cache off; proxy_pass ... } } In both cases If-Modified-Since header wasn't sent to backend in location /2. Fix is to not modify conf->headers_source, but instead merge user-supplied headers from conf->headers_source and default headers (either cache or not) into separate headers_merged array. *) Fixed proxy_set_header inheritance with proxy_set_body. *) Separate functions to merge fastcgi/scgi/uwsgi params. No functional changes. *) Fixed fastcgi/scgi/uwsgi_param inheritance. The following problems were fixed: 1. Directive fastcgi_cache affected headers sent to backends in unrelated servers / locations (see ticket #45). 2. If-Unmodified-Since, If-Match and If-Range headers were sent to backends if fastcgi_cache was used. 3. Cache-related headers were sent to backends if there were no fastcgi_param directives and fastcgi_cache was used at server level. diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -142,6 +142,9 @@ static ngx_int_t ngx_http_fastcgi_add_va static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_fastcgi_merge_params(ngx_conf_t *cf, + ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev); + static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, @@ -2025,17 +2028,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_http_fastcgi_loc_conf_t *prev = parent; ngx_http_fastcgi_loc_conf_t *conf = child; - u_char *p; size_t size; - uintptr_t *code; - ngx_uint_t i; - ngx_array_t headers_names; - ngx_keyval_t *src; - ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - ngx_http_script_compile_t sc; - ngx_http_script_copy_code_t *copy; if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, @@ -2293,95 +2288,146 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf } #endif - if (conf->params_source == NULL) { - conf->flushes = prev->flushes; - conf->params_len = prev->params_len; - conf->params = prev->params; - conf->params_source = prev->params_source; - conf->headers_hash = prev->headers_hash; - + if (ngx_http_fastcgi_merge_params(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_fastcgi_merge_params(ngx_conf_t *cf, + ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev) +{ + u_char *p; + size_t size; + uintptr_t *code; + ngx_uint_t i, nsrc; + ngx_array_t headers_names; #if (NGX_HTTP_CACHE) - - if (conf->params_source == NULL) { - - if ((conf->upstream.cache == NULL) - == (prev->upstream.cache == NULL)) - { - return NGX_CONF_OK; - } - - /* 6 is a number of ngx_http_fastcgi_cache_headers entries */ - conf->params_source = ngx_array_create(cf->pool, 6, - sizeof(ngx_keyval_t)); - if (conf->params_source == NULL) { - return NGX_CONF_ERROR; - } + ngx_array_t params_merged; +#endif + ngx_keyval_t *src; + ngx_hash_key_t *hk; + ngx_hash_init_t hash; + ngx_http_script_compile_t sc; + ngx_http_script_copy_code_t *copy; + + if (conf->params_source == NULL) { + conf->params_source = prev->params_source; + + if (prev->headers_hash.buckets +#if (NGX_HTTP_CACHE) + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) +#endif + ) + { + conf->flushes = prev->flushes; + conf->params_len = prev->params_len; + conf->params = prev->params; + conf->headers_hash = prev->headers_hash; + conf->header_params = prev->header_params; + + return NGX_OK; } -#else - - if (conf->params_source == NULL) { - return NGX_CONF_OK; - } - + } + + if (conf->params_source == NULL +#if (NGX_HTTP_CACHE) + && (conf->upstream.cache == NULL) #endif + ) + { + conf->headers_hash.buckets = (void *) 1; + return NGX_OK; } conf->params_len = ngx_array_create(cf->pool, 64, 1); if (conf->params_len == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } conf->params = ngx_array_create(cf->pool, 512, 1); if (conf->params == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } - src = conf->params_source->elts; + if (conf->params_source) { + src = conf->params_source->elts; + nsrc = conf->params_source->nelts; + + } else { + src = NULL; + nsrc = 0; + } #if (NGX_HTTP_CACHE) if (conf->upstream.cache) { ngx_keyval_t *h, *s; - for (h = ngx_http_fastcgi_cache_headers; h->key.len; h++) { - - for (i = 0; i < conf->params_source->nelts; i++) { + if (ngx_array_init(¶ms_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (i = 0; i < nsrc; i++) { + + s = ngx_array_push(¶ms_merged); + if (s == NULL) { + return NGX_ERROR; + } + + *s = src[i]; + } + + h = ngx_http_fastcgi_cache_headers; + + while (h->key.len) { + + src = params_merged.elts; + nsrc = params_merged.nelts; + + for (i = 0; i < nsrc; i++) { if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { goto next; } } - s = ngx_array_push(conf->params_source); + s = ngx_array_push(¶ms_merged); if (s == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *s = *h; - src = conf->params_source->elts; - next: h++; } + + src = params_merged.elts; + nsrc = params_merged.nelts; } #endif - for (i = 0; i < conf->params_source->nelts; i++) { + for (i = 0; i < nsrc; i++) { if (src[i].key.len > sizeof("HTTP_") - 1 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) { hk = ngx_array_push(&headers_names); if (hk == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } hk->key.len = src[i].key.len - 5; @@ -2397,7 +2443,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf copy = ngx_array_push_n(conf->params_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; @@ -2406,11 +2452,11 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf size = (sizeof(ngx_http_script_copy_code_t) + src[i].key.len + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); + & ~(sizeof(uintptr_t) - 1); copy = ngx_array_push_n(conf->params, size); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = ngx_http_script_copy_code; @@ -2429,12 +2475,12 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf sc.values = &conf->params; if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -2442,7 +2488,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -2450,12 +2496,11 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; - conf->header_params = headers_names.nelts; hash.hash = &conf->headers_hash; @@ -2466,12 +2511,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf hash.pool = cf->pool; hash.temp_pool = NULL; - if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; + return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1722,7 +1722,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t u_char *p; size_t size; - ngx_keyval_t *s; ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; ngx_http_proxy_redirect_t *pr; @@ -2067,22 +2066,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_CONF_ERROR; } - - if (conf->headers_source == NULL) { - conf->headers_source = ngx_array_create(cf->pool, 4, - sizeof(ngx_keyval_t)); - if (conf->headers_source == NULL) { - return NGX_CONF_ERROR; - } - } - - s = ngx_array_push(conf->headers_source); - if (s == NULL) { - return NGX_CONF_ERROR; - } - - ngx_str_set(&s->key, "Content-Length"); - ngx_str_set(&s->value, "$proxy_internal_body_length"); } if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) { @@ -2101,7 +2084,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t size_t size; uintptr_t *code; ngx_uint_t i; - ngx_array_t headers_names; + ngx_array_t headers_names, headers_merged; ngx_keyval_t *src, *s, *h; ngx_hash_key_t *hk; ngx_hash_init_t hash; @@ -2117,6 +2100,8 @@ ngx_http_proxy_merge_headers(ngx_conf_t } if (conf->headers_set_hash.buckets + && ((conf->body_source.data == NULL) + == (prev->body_source.data == NULL)) #if (NGX_HTTP_CACHE) && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) #endif @@ -2132,6 +2117,12 @@ ngx_http_proxy_merge_headers(ngx_conf_t return NGX_ERROR; } + if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) + != NGX_OK) + { + return NGX_ERROR; + } + if (conf->headers_source == NULL) { conf->headers_source = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t)); @@ -2151,8 +2142,6 @@ ngx_http_proxy_merge_headers(ngx_conf_t } - src = conf->headers_source->elts; - #if (NGX_HTTP_CACHE) h = conf->upstream.cache ? ngx_http_proxy_cache_headers: @@ -2163,31 +2152,51 @@ ngx_http_proxy_merge_headers(ngx_conf_t #endif + src = conf->headers_source->elts; + for (i = 0; i < conf->headers_source->nelts; i++) { + + s = ngx_array_push(&headers_merged); + if (s == NULL) { + return NGX_ERROR; + } + + *s = src[i]; + } + while (h->key.len) { - for (i = 0; i < conf->headers_source->nelts; i++) { + src = headers_merged.elts; + for (i = 0; i < headers_merged.nelts; i++) { if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { goto next; } } - s = ngx_array_push(conf->headers_source); + s = ngx_array_push(&headers_merged); if (s == NULL) { return NGX_ERROR; } *s = *h; - src = conf->headers_source->elts; - next: h++; } - - src = conf->headers_source->elts; - for (i = 0; i < conf->headers_source->nelts; i++) { + if (conf->body_source.data) { + s = ngx_array_push(&headers_merged); + if (s == NULL) { + return NGX_ERROR; + } + + ngx_str_set(&s->key, "Content-Length"); + ngx_str_set(&s->value, "$proxy_internal_body_length"); + } + + + src = headers_merged.elts; + for (i = 0; i < headers_merged.nelts; i++) { hk = ngx_array_push(&headers_names); if (hk == NULL) { diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -43,6 +43,8 @@ static void ngx_http_scgi_finalize_reque static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_scgi_merge_params(ngx_conf_t *cf, + ngx_http_scgi_loc_conf_t *conf, ngx_http_scgi_loc_conf_t *prev); static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, @@ -1059,17 +1061,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_http_scgi_loc_conf_t *prev = parent; ngx_http_scgi_loc_conf_t *conf = child; - u_char *p; size_t size; - uintptr_t *code; - ngx_uint_t i; - ngx_array_t headers_names; - ngx_keyval_t *src; - ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - ngx_http_script_compile_t sc; - ngx_http_script_copy_code_t *copy; if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); @@ -1307,95 +1301,146 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t } } - if (conf->params_source == NULL) { - conf->flushes = prev->flushes; - conf->params_len = prev->params_len; - conf->params = prev->params; - conf->params_source = prev->params_source; - conf->headers_hash = prev->headers_hash; + if (ngx_http_scgi_merge_params(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + +static ngx_int_t +ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf, + ngx_http_scgi_loc_conf_t *prev) +{ + u_char *p; + size_t size; + uintptr_t *code; + ngx_uint_t i, nsrc; + ngx_array_t headers_names; #if (NGX_HTTP_CACHE) - - if (conf->params_source == NULL) { + ngx_array_t params_merged; +#endif + ngx_keyval_t *src; + ngx_hash_key_t *hk; + ngx_hash_init_t hash; + ngx_http_script_compile_t sc; + ngx_http_script_copy_code_t *copy; - if ((conf->upstream.cache == NULL) - == (prev->upstream.cache == NULL)) - { - return NGX_CONF_OK; - } + if (conf->params_source == NULL) { + conf->params_source = prev->params_source; - /* 6 is a number of ngx_http_scgi_cache_headers entries */ - conf->params_source = ngx_array_create(cf->pool, 6, - sizeof(ngx_keyval_t)); - if (conf->params_source == NULL) { - return NGX_CONF_ERROR; - } + if (prev->headers_hash.buckets +#if (NGX_HTTP_CACHE) + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) +#endif + ) + { + conf->flushes = prev->flushes; + conf->params_len = prev->params_len; + conf->params = prev->params; + conf->headers_hash = prev->headers_hash; + conf->header_params = prev->header_params; + + return NGX_OK; } -#else + } - if (conf->params_source == NULL) { - return NGX_CONF_OK; - } - + if (conf->params_source == NULL +#if (NGX_HTTP_CACHE) + && (conf->upstream.cache == NULL) #endif + ) + { + conf->headers_hash.buckets = (void *) 1; + return NGX_OK; } conf->params_len = ngx_array_create(cf->pool, 64, 1); if (conf->params_len == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } conf->params = ngx_array_create(cf->pool, 512, 1); if (conf->params == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } - src = conf->params_source->elts; + if (conf->params_source) { + src = conf->params_source->elts; + nsrc = conf->params_source->nelts; + + } else { + src = NULL; + nsrc = 0; + } #if (NGX_HTTP_CACHE) if (conf->upstream.cache) { ngx_keyval_t *h, *s; - for (h = ngx_http_scgi_cache_headers; h->key.len; h++) { + if (ngx_array_init(¶ms_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (i = 0; i < nsrc; i++) { - for (i = 0; i < conf->params_source->nelts; i++) { + s = ngx_array_push(¶ms_merged); + if (s == NULL) { + return NGX_ERROR; + } + + *s = src[i]; + } + + h = ngx_http_scgi_cache_headers; + + while (h->key.len) { + + src = params_merged.elts; + nsrc = params_merged.nelts; + + for (i = 0; i < nsrc; i++) { if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { goto next; } } - s = ngx_array_push(conf->params_source); + s = ngx_array_push(¶ms_merged); if (s == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *s = *h; - src = conf->params_source->elts; - next: h++; } + + src = params_merged.elts; + nsrc = params_merged.nelts; } #endif - for (i = 0; i < conf->params_source->nelts; i++) { + for (i = 0; i < nsrc; i++) { if (src[i].key.len > sizeof("HTTP_") - 1 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) { hk = ngx_array_push(&headers_names); if (hk == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } hk->key.len = src[i].key.len - 5; @@ -1411,7 +1456,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t copy = ngx_array_push_n(conf->params_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; @@ -1424,7 +1469,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t copy = ngx_array_push_n(conf->params, size); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = ngx_http_script_copy_code; @@ -1443,12 +1488,12 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t sc.values = &conf->params; if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1456,7 +1501,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1464,14 +1509,14 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1486,12 +1531,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t hash.pool = cf->pool; hash.temp_pool = NULL; - if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; + return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -50,6 +50,8 @@ static void ngx_http_uwsgi_finalize_requ static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_uwsgi_merge_params(ngx_conf_t *cf, + ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev); static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -1112,17 +1114,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_http_uwsgi_loc_conf_t *prev = parent; ngx_http_uwsgi_loc_conf_t *conf = child; - u_char *p; size_t size; - uintptr_t *code; - ngx_uint_t i; - ngx_array_t headers_names; - ngx_keyval_t *src; - ngx_hash_key_t *hk; ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - ngx_http_script_compile_t sc; - ngx_http_script_copy_code_t *copy; if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); @@ -1365,95 +1359,146 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0); ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0); - if (conf->params_source == NULL) { - conf->flushes = prev->flushes; - conf->params_len = prev->params_len; - conf->params = prev->params; - conf->params_source = prev->params_source; - conf->headers_hash = prev->headers_hash; + if (ngx_http_uwsgi_merge_params(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + +static ngx_int_t +ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf, + ngx_http_uwsgi_loc_conf_t *prev) +{ + u_char *p; + size_t size; + uintptr_t *code; + ngx_uint_t i, nsrc; + ngx_array_t headers_names; #if (NGX_HTTP_CACHE) - - if (conf->params_source == NULL) { + ngx_array_t params_merged; +#endif + ngx_keyval_t *src; + ngx_hash_key_t *hk; + ngx_hash_init_t hash; + ngx_http_script_compile_t sc; + ngx_http_script_copy_code_t *copy; - if ((conf->upstream.cache == NULL) - == (prev->upstream.cache == NULL)) - { - return NGX_CONF_OK; - } + if (conf->params_source == NULL) { + conf->params_source = prev->params_source; - /* 6 is a number of ngx_http_uwsgi_cache_headers entries */ - conf->params_source = ngx_array_create(cf->pool, 6, - sizeof(ngx_keyval_t)); - if (conf->params_source == NULL) { - return NGX_CONF_ERROR; - } + if (prev->headers_hash.buckets +#if (NGX_HTTP_CACHE) + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) +#endif + ) + { + conf->flushes = prev->flushes; + conf->params_len = prev->params_len; + conf->params = prev->params; + conf->headers_hash = prev->headers_hash; + conf->header_params = prev->header_params; + + return NGX_OK; } -#else + } - if (conf->params_source == NULL) { - return NGX_CONF_OK; - } - + if (conf->params_source == NULL +#if (NGX_HTTP_CACHE) + && (conf->upstream.cache == NULL) #endif + ) + { + conf->headers_hash.buckets = (void *) 1; + return NGX_OK; } conf->params_len = ngx_array_create(cf->pool, 64, 1); if (conf->params_len == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } conf->params = ngx_array_create(cf->pool, 512, 1); if (conf->params == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } - src = conf->params_source->elts; + if (conf->params_source) { + src = conf->params_source->elts; + nsrc = conf->params_source->nelts; + + } else { + src = NULL; + nsrc = 0; + } #if (NGX_HTTP_CACHE) if (conf->upstream.cache) { ngx_keyval_t *h, *s; - for (h = ngx_http_uwsgi_cache_headers; h->key.len; h++) { + if (ngx_array_init(¶ms_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (i = 0; i < nsrc; i++) { - for (i = 0; i < conf->params_source->nelts; i++) { + s = ngx_array_push(¶ms_merged); + if (s == NULL) { + return NGX_ERROR; + } + + *s = src[i]; + } + + h = ngx_http_uwsgi_cache_headers; + + while (h->key.len) { + + src = params_merged.elts; + nsrc = params_merged.nelts; + + for (i = 0; i < nsrc; i++) { if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { goto next; } } - s = ngx_array_push(conf->params_source); + s = ngx_array_push(¶ms_merged); if (s == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *s = *h; - src = conf->params_source->elts; - next: h++; } + + src = params_merged.elts; + nsrc = params_merged.nelts; } #endif - for (i = 0; i < conf->params_source->nelts; i++) { + for (i = 0; i < nsrc; i++) { if (src[i].key.len > sizeof("HTTP_") - 1 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) { hk = ngx_array_push(&headers_names); if (hk == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } hk->key.len = src[i].key.len - 5; @@ -1469,7 +1514,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t copy = ngx_array_push_n(conf->params_len, sizeof(ngx_http_script_copy_code_t)); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; @@ -1482,7 +1527,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t copy = ngx_array_push_n(conf->params, size); if (copy == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } copy->code = ngx_http_script_copy_code; @@ -1501,12 +1546,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t sc.values = &conf->params; if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1514,7 +1559,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1522,7 +1567,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); if (code == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *code = (uintptr_t) NULL; @@ -1537,12 +1582,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t hash.pool = cf->pool; hash.temp_pool = NULL; - if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; + return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); }