# HG changeset patch # User Maxim Dounin # Date 1321276695 0 # Node ID 595560d9dcbfa4fc7c3f5a74b19c157c23b6160f # Parent e444e8f6538bc27e110458c91d34c45817cfb020 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. 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 @@ -2875,7 +2875,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; @@ -2906,6 +2906,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)); @@ -2925,8 +2931,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: @@ -2937,31 +2941,41 @@ 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++) { + src = headers_merged.elts; + for (i = 0; i < headers_merged.nelts; i++) { hk = ngx_array_push(&headers_names); if (hk == NULL) {