comparison src/http/modules/ngx_http_proxy_module.c @ 4358:94b995c7c614 stable-1.0

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 14 Dec 2011 15:13:25 +0000
parents 88369902edb1
children fd40c9ef750d
comparison
equal deleted inserted replaced
4357:efd515ace6bb 4358:94b995c7c614
1720 ngx_http_proxy_loc_conf_t *prev = parent; 1720 ngx_http_proxy_loc_conf_t *prev = parent;
1721 ngx_http_proxy_loc_conf_t *conf = child; 1721 ngx_http_proxy_loc_conf_t *conf = child;
1722 1722
1723 u_char *p; 1723 u_char *p;
1724 size_t size; 1724 size_t size;
1725 ngx_keyval_t *s;
1726 ngx_hash_init_t hash; 1725 ngx_hash_init_t hash;
1727 ngx_http_core_loc_conf_t *clcf; 1726 ngx_http_core_loc_conf_t *clcf;
1728 ngx_http_proxy_redirect_t *pr; 1727 ngx_http_proxy_redirect_t *pr;
1729 ngx_http_script_compile_t sc; 1728 ngx_http_script_compile_t sc;
1730 1729
2065 sc.complete_values = 1; 2064 sc.complete_values = 1;
2066 2065
2067 if (ngx_http_script_compile(&sc) != NGX_OK) { 2066 if (ngx_http_script_compile(&sc) != NGX_OK) {
2068 return NGX_CONF_ERROR; 2067 return NGX_CONF_ERROR;
2069 } 2068 }
2070
2071 if (conf->headers_source == NULL) {
2072 conf->headers_source = ngx_array_create(cf->pool, 4,
2073 sizeof(ngx_keyval_t));
2074 if (conf->headers_source == NULL) {
2075 return NGX_CONF_ERROR;
2076 }
2077 }
2078
2079 s = ngx_array_push(conf->headers_source);
2080 if (s == NULL) {
2081 return NGX_CONF_ERROR;
2082 }
2083
2084 ngx_str_set(&s->key, "Content-Length");
2085 ngx_str_set(&s->value, "$proxy_internal_body_length");
2086 } 2069 }
2087 2070
2088 if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) { 2071 if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) {
2089 return NGX_CONF_ERROR; 2072 return NGX_CONF_ERROR;
2090 } 2073 }
2099 { 2082 {
2100 u_char *p; 2083 u_char *p;
2101 size_t size; 2084 size_t size;
2102 uintptr_t *code; 2085 uintptr_t *code;
2103 ngx_uint_t i; 2086 ngx_uint_t i;
2104 ngx_array_t headers_names; 2087 ngx_array_t headers_names, headers_merged;
2105 ngx_keyval_t *src, *s, *h; 2088 ngx_keyval_t *src, *s, *h;
2106 ngx_hash_key_t *hk; 2089 ngx_hash_key_t *hk;
2107 ngx_hash_init_t hash; 2090 ngx_hash_init_t hash;
2108 ngx_http_script_compile_t sc; 2091 ngx_http_script_compile_t sc;
2109 ngx_http_script_copy_code_t *copy; 2092 ngx_http_script_copy_code_t *copy;
2115 conf->headers_set_hash = prev->headers_set_hash; 2098 conf->headers_set_hash = prev->headers_set_hash;
2116 conf->headers_source = prev->headers_source; 2099 conf->headers_source = prev->headers_source;
2117 } 2100 }
2118 2101
2119 if (conf->headers_set_hash.buckets 2102 if (conf->headers_set_hash.buckets
2103 && ((conf->body_source.data == NULL)
2104 == (prev->body_source.data == NULL))
2120 #if (NGX_HTTP_CACHE) 2105 #if (NGX_HTTP_CACHE)
2121 && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) 2106 && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
2122 #endif 2107 #endif
2123 ) 2108 )
2124 { 2109 {
2130 != NGX_OK) 2115 != NGX_OK)
2131 { 2116 {
2132 return NGX_ERROR; 2117 return NGX_ERROR;
2133 } 2118 }
2134 2119
2120 if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
2121 != NGX_OK)
2122 {
2123 return NGX_ERROR;
2124 }
2125
2135 if (conf->headers_source == NULL) { 2126 if (conf->headers_source == NULL) {
2136 conf->headers_source = ngx_array_create(cf->pool, 4, 2127 conf->headers_source = ngx_array_create(cf->pool, 4,
2137 sizeof(ngx_keyval_t)); 2128 sizeof(ngx_keyval_t));
2138 if (conf->headers_source == NULL) { 2129 if (conf->headers_source == NULL) {
2139 return NGX_ERROR; 2130 return NGX_ERROR;
2149 if (conf->headers_set == NULL) { 2140 if (conf->headers_set == NULL) {
2150 return NGX_ERROR; 2141 return NGX_ERROR;
2151 } 2142 }
2152 2143
2153 2144
2154 src = conf->headers_source->elts;
2155
2156 #if (NGX_HTTP_CACHE) 2145 #if (NGX_HTTP_CACHE)
2157 2146
2158 h = conf->upstream.cache ? ngx_http_proxy_cache_headers: 2147 h = conf->upstream.cache ? ngx_http_proxy_cache_headers:
2159 ngx_http_proxy_headers; 2148 ngx_http_proxy_headers;
2160 #else 2149 #else
2161 2150
2162 h = ngx_http_proxy_headers; 2151 h = ngx_http_proxy_headers;
2163 2152
2164 #endif 2153 #endif
2165 2154
2155 src = conf->headers_source->elts;
2156 for (i = 0; i < conf->headers_source->nelts; i++) {
2157
2158 s = ngx_array_push(&headers_merged);
2159 if (s == NULL) {
2160 return NGX_ERROR;
2161 }
2162
2163 *s = src[i];
2164 }
2165
2166 while (h->key.len) { 2166 while (h->key.len) {
2167 2167
2168 for (i = 0; i < conf->headers_source->nelts; i++) { 2168 src = headers_merged.elts;
2169 for (i = 0; i < headers_merged.nelts; i++) {
2169 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { 2170 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
2170 goto next; 2171 goto next;
2171 } 2172 }
2172 } 2173 }
2173 2174
2174 s = ngx_array_push(conf->headers_source); 2175 s = ngx_array_push(&headers_merged);
2175 if (s == NULL) { 2176 if (s == NULL) {
2176 return NGX_ERROR; 2177 return NGX_ERROR;
2177 } 2178 }
2178 2179
2179 *s = *h; 2180 *s = *h;
2180 2181
2181 src = conf->headers_source->elts;
2182
2183 next: 2182 next:
2184 2183
2185 h++; 2184 h++;
2186 } 2185 }
2187 2186
2188 2187 if (conf->body_source.data) {
2189 src = conf->headers_source->elts; 2188 s = ngx_array_push(&headers_merged);
2190 for (i = 0; i < conf->headers_source->nelts; i++) { 2189 if (s == NULL) {
2190 return NGX_ERROR;
2191 }
2192
2193 ngx_str_set(&s->key, "Content-Length");
2194 ngx_str_set(&s->value, "$proxy_internal_body_length");
2195 }
2196
2197
2198 src = headers_merged.elts;
2199 for (i = 0; i < headers_merged.nelts; i++) {
2191 2200
2192 hk = ngx_array_push(&headers_names); 2201 hk = ngx_array_push(&headers_names);
2193 if (hk == NULL) { 2202 if (hk == NULL) {
2194 return NGX_ERROR; 2203 return NGX_ERROR;
2195 } 2204 }