Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_scgi_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 | 94049ec3eeda |
children | 8e7bb000ba4a |
comparison
equal
deleted
inserted
replaced
4357:efd515ace6bb | 4358:94b995c7c614 |
---|---|
41 static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc); | 41 static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc); |
42 | 42 |
43 static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf); | 43 static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf); |
44 static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, | 44 static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, |
45 void *child); | 45 void *child); |
46 static ngx_int_t ngx_http_scgi_merge_params(ngx_conf_t *cf, | |
47 ngx_http_scgi_loc_conf_t *conf, ngx_http_scgi_loc_conf_t *prev); | |
46 | 48 |
47 static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 49 static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
48 static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, | 50 static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, |
49 void *conf); | 51 void *conf); |
50 | 52 |
1057 ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | 1059 ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |
1058 { | 1060 { |
1059 ngx_http_scgi_loc_conf_t *prev = parent; | 1061 ngx_http_scgi_loc_conf_t *prev = parent; |
1060 ngx_http_scgi_loc_conf_t *conf = child; | 1062 ngx_http_scgi_loc_conf_t *conf = child; |
1061 | 1063 |
1062 u_char *p; | |
1063 size_t size; | 1064 size_t size; |
1064 uintptr_t *code; | |
1065 ngx_uint_t i; | |
1066 ngx_array_t headers_names; | |
1067 ngx_keyval_t *src; | |
1068 ngx_hash_key_t *hk; | |
1069 ngx_hash_init_t hash; | 1065 ngx_hash_init_t hash; |
1070 ngx_http_core_loc_conf_t *clcf; | 1066 ngx_http_core_loc_conf_t *clcf; |
1071 ngx_http_script_compile_t sc; | |
1072 ngx_http_script_copy_code_t *copy; | |
1073 | 1067 |
1074 if (conf->upstream.store != 0) { | 1068 if (conf->upstream.store != 0) { |
1075 ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); | 1069 ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); |
1076 | 1070 |
1077 if (conf->upstream.store_lengths == NULL) { | 1071 if (conf->upstream.store_lengths == NULL) { |
1305 if (clcf->handler == NULL && clcf->lmt_excpt) { | 1299 if (clcf->handler == NULL && clcf->lmt_excpt) { |
1306 clcf->handler = ngx_http_scgi_handler; | 1300 clcf->handler = ngx_http_scgi_handler; |
1307 } | 1301 } |
1308 } | 1302 } |
1309 | 1303 |
1304 if (ngx_http_scgi_merge_params(cf, conf, prev) != NGX_OK) { | |
1305 return NGX_CONF_ERROR; | |
1306 } | |
1307 | |
1308 return NGX_CONF_OK; | |
1309 } | |
1310 | |
1311 | |
1312 static ngx_int_t | |
1313 ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf, | |
1314 ngx_http_scgi_loc_conf_t *prev) | |
1315 { | |
1316 u_char *p; | |
1317 size_t size; | |
1318 uintptr_t *code; | |
1319 ngx_uint_t i, nsrc; | |
1320 ngx_array_t headers_names; | |
1321 #if (NGX_HTTP_CACHE) | |
1322 ngx_array_t params_merged; | |
1323 #endif | |
1324 ngx_keyval_t *src; | |
1325 ngx_hash_key_t *hk; | |
1326 ngx_hash_init_t hash; | |
1327 ngx_http_script_compile_t sc; | |
1328 ngx_http_script_copy_code_t *copy; | |
1329 | |
1310 if (conf->params_source == NULL) { | 1330 if (conf->params_source == NULL) { |
1311 conf->flushes = prev->flushes; | |
1312 conf->params_len = prev->params_len; | |
1313 conf->params = prev->params; | |
1314 conf->params_source = prev->params_source; | 1331 conf->params_source = prev->params_source; |
1315 conf->headers_hash = prev->headers_hash; | 1332 |
1316 | 1333 if (prev->headers_hash.buckets |
1317 #if (NGX_HTTP_CACHE) | 1334 #if (NGX_HTTP_CACHE) |
1318 | 1335 && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) |
1319 if (conf->params_source == NULL) { | |
1320 | |
1321 if ((conf->upstream.cache == NULL) | |
1322 == (prev->upstream.cache == NULL)) | |
1323 { | |
1324 return NGX_CONF_OK; | |
1325 } | |
1326 | |
1327 /* 6 is a number of ngx_http_scgi_cache_headers entries */ | |
1328 conf->params_source = ngx_array_create(cf->pool, 6, | |
1329 sizeof(ngx_keyval_t)); | |
1330 if (conf->params_source == NULL) { | |
1331 return NGX_CONF_ERROR; | |
1332 } | |
1333 } | |
1334 #else | |
1335 | |
1336 if (conf->params_source == NULL) { | |
1337 return NGX_CONF_OK; | |
1338 } | |
1339 | |
1340 #endif | 1336 #endif |
1337 ) | |
1338 { | |
1339 conf->flushes = prev->flushes; | |
1340 conf->params_len = prev->params_len; | |
1341 conf->params = prev->params; | |
1342 conf->headers_hash = prev->headers_hash; | |
1343 conf->header_params = prev->header_params; | |
1344 | |
1345 return NGX_OK; | |
1346 } | |
1347 } | |
1348 | |
1349 if (conf->params_source == NULL | |
1350 #if (NGX_HTTP_CACHE) | |
1351 && (conf->upstream.cache == NULL) | |
1352 #endif | |
1353 ) | |
1354 { | |
1355 conf->headers_hash.buckets = (void *) 1; | |
1356 return NGX_OK; | |
1341 } | 1357 } |
1342 | 1358 |
1343 conf->params_len = ngx_array_create(cf->pool, 64, 1); | 1359 conf->params_len = ngx_array_create(cf->pool, 64, 1); |
1344 if (conf->params_len == NULL) { | 1360 if (conf->params_len == NULL) { |
1345 return NGX_CONF_ERROR; | 1361 return NGX_ERROR; |
1346 } | 1362 } |
1347 | 1363 |
1348 conf->params = ngx_array_create(cf->pool, 512, 1); | 1364 conf->params = ngx_array_create(cf->pool, 512, 1); |
1349 if (conf->params == NULL) { | 1365 if (conf->params == NULL) { |
1350 return NGX_CONF_ERROR; | 1366 return NGX_ERROR; |
1351 } | 1367 } |
1352 | 1368 |
1353 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | 1369 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) |
1354 != NGX_OK) | 1370 != NGX_OK) |
1355 { | 1371 { |
1356 return NGX_CONF_ERROR; | 1372 return NGX_ERROR; |
1357 } | 1373 } |
1358 | 1374 |
1359 src = conf->params_source->elts; | 1375 if (conf->params_source) { |
1376 src = conf->params_source->elts; | |
1377 nsrc = conf->params_source->nelts; | |
1378 | |
1379 } else { | |
1380 src = NULL; | |
1381 nsrc = 0; | |
1382 } | |
1360 | 1383 |
1361 #if (NGX_HTTP_CACHE) | 1384 #if (NGX_HTTP_CACHE) |
1362 | 1385 |
1363 if (conf->upstream.cache) { | 1386 if (conf->upstream.cache) { |
1364 ngx_keyval_t *h, *s; | 1387 ngx_keyval_t *h, *s; |
1365 | 1388 |
1366 for (h = ngx_http_scgi_cache_headers; h->key.len; h++) { | 1389 if (ngx_array_init(¶ms_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t)) |
1367 | 1390 != NGX_OK) |
1368 for (i = 0; i < conf->params_source->nelts; i++) { | 1391 { |
1392 return NGX_ERROR; | |
1393 } | |
1394 | |
1395 for (i = 0; i < nsrc; i++) { | |
1396 | |
1397 s = ngx_array_push(¶ms_merged); | |
1398 if (s == NULL) { | |
1399 return NGX_ERROR; | |
1400 } | |
1401 | |
1402 *s = src[i]; | |
1403 } | |
1404 | |
1405 h = ngx_http_scgi_cache_headers; | |
1406 | |
1407 while (h->key.len) { | |
1408 | |
1409 src = params_merged.elts; | |
1410 nsrc = params_merged.nelts; | |
1411 | |
1412 for (i = 0; i < nsrc; i++) { | |
1369 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { | 1413 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { |
1370 goto next; | 1414 goto next; |
1371 } | 1415 } |
1372 } | 1416 } |
1373 | 1417 |
1374 s = ngx_array_push(conf->params_source); | 1418 s = ngx_array_push(¶ms_merged); |
1375 if (s == NULL) { | 1419 if (s == NULL) { |
1376 return NGX_CONF_ERROR; | 1420 return NGX_ERROR; |
1377 } | 1421 } |
1378 | 1422 |
1379 *s = *h; | 1423 *s = *h; |
1380 | 1424 |
1381 src = conf->params_source->elts; | |
1382 | |
1383 next: | 1425 next: |
1384 | 1426 |
1385 h++; | 1427 h++; |
1386 } | 1428 } |
1429 | |
1430 src = params_merged.elts; | |
1431 nsrc = params_merged.nelts; | |
1387 } | 1432 } |
1388 | 1433 |
1389 #endif | 1434 #endif |
1390 | 1435 |
1391 for (i = 0; i < conf->params_source->nelts; i++) { | 1436 for (i = 0; i < nsrc; i++) { |
1392 | 1437 |
1393 if (src[i].key.len > sizeof("HTTP_") - 1 | 1438 if (src[i].key.len > sizeof("HTTP_") - 1 |
1394 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) | 1439 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) |
1395 { | 1440 { |
1396 hk = ngx_array_push(&headers_names); | 1441 hk = ngx_array_push(&headers_names); |
1397 if (hk == NULL) { | 1442 if (hk == NULL) { |
1398 return NGX_CONF_ERROR; | 1443 return NGX_ERROR; |
1399 } | 1444 } |
1400 | 1445 |
1401 hk->key.len = src[i].key.len - 5; | 1446 hk->key.len = src[i].key.len - 5; |
1402 hk->key.data = src[i].key.data + 5; | 1447 hk->key.data = src[i].key.data + 5; |
1403 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); | 1448 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); |
1409 } | 1454 } |
1410 | 1455 |
1411 copy = ngx_array_push_n(conf->params_len, | 1456 copy = ngx_array_push_n(conf->params_len, |
1412 sizeof(ngx_http_script_copy_code_t)); | 1457 sizeof(ngx_http_script_copy_code_t)); |
1413 if (copy == NULL) { | 1458 if (copy == NULL) { |
1414 return NGX_CONF_ERROR; | 1459 return NGX_ERROR; |
1415 } | 1460 } |
1416 | 1461 |
1417 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | 1462 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; |
1418 copy->len = src[i].key.len + 1; | 1463 copy->len = src[i].key.len + 1; |
1419 | 1464 |
1422 + src[i].key.len + 1 + sizeof(uintptr_t) - 1) | 1467 + src[i].key.len + 1 + sizeof(uintptr_t) - 1) |
1423 & ~(sizeof(uintptr_t) - 1); | 1468 & ~(sizeof(uintptr_t) - 1); |
1424 | 1469 |
1425 copy = ngx_array_push_n(conf->params, size); | 1470 copy = ngx_array_push_n(conf->params, size); |
1426 if (copy == NULL) { | 1471 if (copy == NULL) { |
1427 return NGX_CONF_ERROR; | 1472 return NGX_ERROR; |
1428 } | 1473 } |
1429 | 1474 |
1430 copy->code = ngx_http_script_copy_code; | 1475 copy->code = ngx_http_script_copy_code; |
1431 copy->len = src[i].key.len + 1; | 1476 copy->len = src[i].key.len + 1; |
1432 | 1477 |
1441 sc.flushes = &conf->flushes; | 1486 sc.flushes = &conf->flushes; |
1442 sc.lengths = &conf->params_len; | 1487 sc.lengths = &conf->params_len; |
1443 sc.values = &conf->params; | 1488 sc.values = &conf->params; |
1444 | 1489 |
1445 if (ngx_http_script_compile(&sc) != NGX_OK) { | 1490 if (ngx_http_script_compile(&sc) != NGX_OK) { |
1446 return NGX_CONF_ERROR; | 1491 return NGX_ERROR; |
1447 } | 1492 } |
1448 | 1493 |
1449 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | 1494 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); |
1450 if (code == NULL) { | 1495 if (code == NULL) { |
1451 return NGX_CONF_ERROR; | 1496 return NGX_ERROR; |
1452 } | 1497 } |
1453 | 1498 |
1454 *code = (uintptr_t) NULL; | 1499 *code = (uintptr_t) NULL; |
1455 | 1500 |
1456 | 1501 |
1457 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | 1502 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); |
1458 if (code == NULL) { | 1503 if (code == NULL) { |
1459 return NGX_CONF_ERROR; | 1504 return NGX_ERROR; |
1460 } | 1505 } |
1461 | 1506 |
1462 *code = (uintptr_t) NULL; | 1507 *code = (uintptr_t) NULL; |
1463 } | 1508 } |
1464 | 1509 |
1465 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | 1510 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); |
1466 if (code == NULL) { | 1511 if (code == NULL) { |
1467 return NGX_CONF_ERROR; | 1512 return NGX_ERROR; |
1468 } | 1513 } |
1469 | 1514 |
1470 *code = (uintptr_t) NULL; | 1515 *code = (uintptr_t) NULL; |
1471 | 1516 |
1472 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | 1517 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); |
1473 if (code == NULL) { | 1518 if (code == NULL) { |
1474 return NGX_CONF_ERROR; | 1519 return NGX_ERROR; |
1475 } | 1520 } |
1476 | 1521 |
1477 *code = (uintptr_t) NULL; | 1522 *code = (uintptr_t) NULL; |
1478 | 1523 |
1479 conf->header_params = headers_names.nelts; | 1524 conf->header_params = headers_names.nelts; |
1484 hash.bucket_size = 64; | 1529 hash.bucket_size = 64; |
1485 hash.name = "scgi_params_hash"; | 1530 hash.name = "scgi_params_hash"; |
1486 hash.pool = cf->pool; | 1531 hash.pool = cf->pool; |
1487 hash.temp_pool = NULL; | 1532 hash.temp_pool = NULL; |
1488 | 1533 |
1489 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) | 1534 return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); |
1490 { | |
1491 return NGX_CONF_ERROR; | |
1492 } | |
1493 | |
1494 return NGX_CONF_OK; | |
1495 } | 1535 } |
1496 | 1536 |
1497 | 1537 |
1498 static char * | 1538 static char * |
1499 ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1539 ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |