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(&params_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(&params_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(&params_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,