Mercurial > hg > nginx
comparison src/http/modules/ngx_http_fastcgi_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 | efd515ace6bb |
children | 2b2d51cdbd97 |
comparison
equal
deleted
inserted
replaced
4357:efd515ace6bb | 4358:94b995c7c614 |
---|---|
140 | 140 |
141 static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf); | 141 static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf); |
142 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); | 142 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); |
143 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, | 143 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, |
144 void *parent, void *child); | 144 void *parent, void *child); |
145 static ngx_int_t ngx_http_fastcgi_merge_params(ngx_conf_t *cf, | |
146 ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev); | |
147 | |
145 static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, | 148 static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, |
146 ngx_http_variable_value_t *v, uintptr_t data); | 149 ngx_http_variable_value_t *v, uintptr_t data); |
147 static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, | 150 static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, |
148 ngx_http_variable_value_t *v, uintptr_t data); | 151 ngx_http_variable_value_t *v, uintptr_t data); |
149 static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r, | 152 static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r, |
2023 ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | 2026 ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |
2024 { | 2027 { |
2025 ngx_http_fastcgi_loc_conf_t *prev = parent; | 2028 ngx_http_fastcgi_loc_conf_t *prev = parent; |
2026 ngx_http_fastcgi_loc_conf_t *conf = child; | 2029 ngx_http_fastcgi_loc_conf_t *conf = child; |
2027 | 2030 |
2028 u_char *p; | |
2029 size_t size; | 2031 size_t size; |
2030 uintptr_t *code; | |
2031 ngx_uint_t i; | |
2032 ngx_array_t headers_names; | |
2033 ngx_keyval_t *src; | |
2034 ngx_hash_key_t *hk; | |
2035 ngx_hash_init_t hash; | 2032 ngx_hash_init_t hash; |
2036 ngx_http_core_loc_conf_t *clcf; | 2033 ngx_http_core_loc_conf_t *clcf; |
2037 ngx_http_script_compile_t sc; | |
2038 ngx_http_script_copy_code_t *copy; | |
2039 | 2034 |
2040 if (conf->upstream.store != 0) { | 2035 if (conf->upstream.store != 0) { |
2041 ngx_conf_merge_value(conf->upstream.store, | 2036 ngx_conf_merge_value(conf->upstream.store, |
2042 prev->upstream.store, 0); | 2037 prev->upstream.store, 0); |
2043 | 2038 |
2291 conf->split_regex = prev->split_regex; | 2286 conf->split_regex = prev->split_regex; |
2292 conf->split_name = prev->split_name; | 2287 conf->split_name = prev->split_name; |
2293 } | 2288 } |
2294 #endif | 2289 #endif |
2295 | 2290 |
2291 if (ngx_http_fastcgi_merge_params(cf, conf, prev) != NGX_OK) { | |
2292 return NGX_CONF_ERROR; | |
2293 } | |
2294 | |
2295 return NGX_CONF_OK; | |
2296 } | |
2297 | |
2298 | |
2299 static ngx_int_t | |
2300 ngx_http_fastcgi_merge_params(ngx_conf_t *cf, | |
2301 ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev) | |
2302 { | |
2303 u_char *p; | |
2304 size_t size; | |
2305 uintptr_t *code; | |
2306 ngx_uint_t i, nsrc; | |
2307 ngx_array_t headers_names; | |
2308 #if (NGX_HTTP_CACHE) | |
2309 ngx_array_t params_merged; | |
2310 #endif | |
2311 ngx_keyval_t *src; | |
2312 ngx_hash_key_t *hk; | |
2313 ngx_hash_init_t hash; | |
2314 ngx_http_script_compile_t sc; | |
2315 ngx_http_script_copy_code_t *copy; | |
2316 | |
2296 if (conf->params_source == NULL) { | 2317 if (conf->params_source == NULL) { |
2297 conf->flushes = prev->flushes; | |
2298 conf->params_len = prev->params_len; | |
2299 conf->params = prev->params; | |
2300 conf->params_source = prev->params_source; | 2318 conf->params_source = prev->params_source; |
2301 conf->headers_hash = prev->headers_hash; | 2319 |
2302 | 2320 if (prev->headers_hash.buckets |
2303 #if (NGX_HTTP_CACHE) | 2321 #if (NGX_HTTP_CACHE) |
2304 | 2322 && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) |
2305 if (conf->params_source == NULL) { | |
2306 | |
2307 if ((conf->upstream.cache == NULL) | |
2308 == (prev->upstream.cache == NULL)) | |
2309 { | |
2310 return NGX_CONF_OK; | |
2311 } | |
2312 | |
2313 /* 6 is a number of ngx_http_fastcgi_cache_headers entries */ | |
2314 conf->params_source = ngx_array_create(cf->pool, 6, | |
2315 sizeof(ngx_keyval_t)); | |
2316 if (conf->params_source == NULL) { | |
2317 return NGX_CONF_ERROR; | |
2318 } | |
2319 } | |
2320 #else | |
2321 | |
2322 if (conf->params_source == NULL) { | |
2323 return NGX_CONF_OK; | |
2324 } | |
2325 | |
2326 #endif | 2323 #endif |
2324 ) | |
2325 { | |
2326 conf->flushes = prev->flushes; | |
2327 conf->params_len = prev->params_len; | |
2328 conf->params = prev->params; | |
2329 conf->headers_hash = prev->headers_hash; | |
2330 conf->header_params = prev->header_params; | |
2331 | |
2332 return NGX_OK; | |
2333 } | |
2334 } | |
2335 | |
2336 if (conf->params_source == NULL | |
2337 #if (NGX_HTTP_CACHE) | |
2338 && (conf->upstream.cache == NULL) | |
2339 #endif | |
2340 ) | |
2341 { | |
2342 conf->headers_hash.buckets = (void *) 1; | |
2343 return NGX_OK; | |
2327 } | 2344 } |
2328 | 2345 |
2329 conf->params_len = ngx_array_create(cf->pool, 64, 1); | 2346 conf->params_len = ngx_array_create(cf->pool, 64, 1); |
2330 if (conf->params_len == NULL) { | 2347 if (conf->params_len == NULL) { |
2331 return NGX_CONF_ERROR; | 2348 return NGX_ERROR; |
2332 } | 2349 } |
2333 | 2350 |
2334 conf->params = ngx_array_create(cf->pool, 512, 1); | 2351 conf->params = ngx_array_create(cf->pool, 512, 1); |
2335 if (conf->params == NULL) { | 2352 if (conf->params == NULL) { |
2336 return NGX_CONF_ERROR; | 2353 return NGX_ERROR; |
2337 } | 2354 } |
2338 | 2355 |
2339 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | 2356 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) |
2340 != NGX_OK) | 2357 != NGX_OK) |
2341 { | 2358 { |
2342 return NGX_CONF_ERROR; | 2359 return NGX_ERROR; |
2343 } | 2360 } |
2344 | 2361 |
2345 src = conf->params_source->elts; | 2362 if (conf->params_source) { |
2363 src = conf->params_source->elts; | |
2364 nsrc = conf->params_source->nelts; | |
2365 | |
2366 } else { | |
2367 src = NULL; | |
2368 nsrc = 0; | |
2369 } | |
2346 | 2370 |
2347 #if (NGX_HTTP_CACHE) | 2371 #if (NGX_HTTP_CACHE) |
2348 | 2372 |
2349 if (conf->upstream.cache) { | 2373 if (conf->upstream.cache) { |
2350 ngx_keyval_t *h, *s; | 2374 ngx_keyval_t *h, *s; |
2351 | 2375 |
2352 for (h = ngx_http_fastcgi_cache_headers; h->key.len; h++) { | 2376 if (ngx_array_init(¶ms_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) |
2353 | 2377 != NGX_OK) |
2354 for (i = 0; i < conf->params_source->nelts; i++) { | 2378 { |
2379 return NGX_ERROR; | |
2380 } | |
2381 | |
2382 for (i = 0; i < nsrc; i++) { | |
2383 | |
2384 s = ngx_array_push(¶ms_merged); | |
2385 if (s == NULL) { | |
2386 return NGX_ERROR; | |
2387 } | |
2388 | |
2389 *s = src[i]; | |
2390 } | |
2391 | |
2392 h = ngx_http_fastcgi_cache_headers; | |
2393 | |
2394 while (h->key.len) { | |
2395 | |
2396 src = params_merged.elts; | |
2397 nsrc = params_merged.nelts; | |
2398 | |
2399 for (i = 0; i < nsrc; i++) { | |
2355 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { | 2400 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { |
2356 goto next; | 2401 goto next; |
2357 } | 2402 } |
2358 } | 2403 } |
2359 | 2404 |
2360 s = ngx_array_push(conf->params_source); | 2405 s = ngx_array_push(¶ms_merged); |
2361 if (s == NULL) { | 2406 if (s == NULL) { |
2362 return NGX_CONF_ERROR; | 2407 return NGX_ERROR; |
2363 } | 2408 } |
2364 | 2409 |
2365 *s = *h; | 2410 *s = *h; |
2366 | 2411 |
2367 src = conf->params_source->elts; | |
2368 | |
2369 next: | 2412 next: |
2370 | 2413 |
2371 h++; | 2414 h++; |
2372 } | 2415 } |
2416 | |
2417 src = params_merged.elts; | |
2418 nsrc = params_merged.nelts; | |
2373 } | 2419 } |
2374 | 2420 |
2375 #endif | 2421 #endif |
2376 | 2422 |
2377 for (i = 0; i < conf->params_source->nelts; i++) { | 2423 for (i = 0; i < nsrc; i++) { |
2378 | 2424 |
2379 if (src[i].key.len > sizeof("HTTP_") - 1 | 2425 if (src[i].key.len > sizeof("HTTP_") - 1 |
2380 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) | 2426 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) |
2381 { | 2427 { |
2382 hk = ngx_array_push(&headers_names); | 2428 hk = ngx_array_push(&headers_names); |
2383 if (hk == NULL) { | 2429 if (hk == NULL) { |
2384 return NGX_CONF_ERROR; | 2430 return NGX_ERROR; |
2385 } | 2431 } |
2386 | 2432 |
2387 hk->key.len = src[i].key.len - 5; | 2433 hk->key.len = src[i].key.len - 5; |
2388 hk->key.data = src[i].key.data + 5; | 2434 hk->key.data = src[i].key.data + 5; |
2389 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); | 2435 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); |
2395 } | 2441 } |
2396 | 2442 |
2397 copy = ngx_array_push_n(conf->params_len, | 2443 copy = ngx_array_push_n(conf->params_len, |
2398 sizeof(ngx_http_script_copy_code_t)); | 2444 sizeof(ngx_http_script_copy_code_t)); |
2399 if (copy == NULL) { | 2445 if (copy == NULL) { |
2400 return NGX_CONF_ERROR; | 2446 return NGX_ERROR; |
2401 } | 2447 } |
2402 | 2448 |
2403 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | 2449 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; |
2404 copy->len = src[i].key.len; | 2450 copy->len = src[i].key.len; |
2405 | 2451 |
2406 | 2452 |
2407 size = (sizeof(ngx_http_script_copy_code_t) | 2453 size = (sizeof(ngx_http_script_copy_code_t) |
2408 + src[i].key.len + sizeof(uintptr_t) - 1) | 2454 + src[i].key.len + sizeof(uintptr_t) - 1) |
2409 & ~(sizeof(uintptr_t) - 1); | 2455 & ~(sizeof(uintptr_t) - 1); |
2410 | 2456 |
2411 copy = ngx_array_push_n(conf->params, size); | 2457 copy = ngx_array_push_n(conf->params, size); |
2412 if (copy == NULL) { | 2458 if (copy == NULL) { |
2413 return NGX_CONF_ERROR; | 2459 return NGX_ERROR; |
2414 } | 2460 } |
2415 | 2461 |
2416 copy->code = ngx_http_script_copy_code; | 2462 copy->code = ngx_http_script_copy_code; |
2417 copy->len = src[i].key.len; | 2463 copy->len = src[i].key.len; |
2418 | 2464 |
2427 sc.flushes = &conf->flushes; | 2473 sc.flushes = &conf->flushes; |
2428 sc.lengths = &conf->params_len; | 2474 sc.lengths = &conf->params_len; |
2429 sc.values = &conf->params; | 2475 sc.values = &conf->params; |
2430 | 2476 |
2431 if (ngx_http_script_compile(&sc) != NGX_OK) { | 2477 if (ngx_http_script_compile(&sc) != NGX_OK) { |
2432 return NGX_CONF_ERROR; | 2478 return NGX_ERROR; |
2433 } | 2479 } |
2434 | 2480 |
2435 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | 2481 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); |
2436 if (code == NULL) { | 2482 if (code == NULL) { |
2437 return NGX_CONF_ERROR; | 2483 return NGX_ERROR; |
2438 } | 2484 } |
2439 | 2485 |
2440 *code = (uintptr_t) NULL; | 2486 *code = (uintptr_t) NULL; |
2441 | 2487 |
2442 | 2488 |
2443 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | 2489 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); |
2444 if (code == NULL) { | 2490 if (code == NULL) { |
2445 return NGX_CONF_ERROR; | 2491 return NGX_ERROR; |
2446 } | 2492 } |
2447 | 2493 |
2448 *code = (uintptr_t) NULL; | 2494 *code = (uintptr_t) NULL; |
2449 } | 2495 } |
2450 | 2496 |
2451 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | 2497 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); |
2452 if (code == NULL) { | 2498 if (code == NULL) { |
2453 return NGX_CONF_ERROR; | 2499 return NGX_ERROR; |
2454 } | 2500 } |
2455 | 2501 |
2456 *code = (uintptr_t) NULL; | 2502 *code = (uintptr_t) NULL; |
2457 | |
2458 | 2503 |
2459 conf->header_params = headers_names.nelts; | 2504 conf->header_params = headers_names.nelts; |
2460 | 2505 |
2461 hash.hash = &conf->headers_hash; | 2506 hash.hash = &conf->headers_hash; |
2462 hash.key = ngx_hash_key_lc; | 2507 hash.key = ngx_hash_key_lc; |
2464 hash.bucket_size = 64; | 2509 hash.bucket_size = 64; |
2465 hash.name = "fastcgi_params_hash"; | 2510 hash.name = "fastcgi_params_hash"; |
2466 hash.pool = cf->pool; | 2511 hash.pool = cf->pool; |
2467 hash.temp_pool = NULL; | 2512 hash.temp_pool = NULL; |
2468 | 2513 |
2469 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) | 2514 return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); |
2470 { | |
2471 return NGX_CONF_ERROR; | |
2472 } | |
2473 | |
2474 return NGX_CONF_OK; | |
2475 } | 2515 } |
2476 | 2516 |
2477 | 2517 |
2478 static ngx_int_t | 2518 static ngx_int_t |
2479 ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, | 2519 ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, |