Mercurial > hg > nginx
comparison src/http/modules/ngx_http_uwsgi_module.c @ 3566:b81d44244cb1
allow uwsgi_param to override client headers using HTTP_ parameters
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 04 Jun 2010 12:26:27 +0000 |
parents | 1e86f0ac9a44 |
children | 9bbfce117cfb |
comparison
equal
deleted
inserted
replaced
3565:1e86f0ac9a44 | 3566:b81d44244cb1 |
---|---|
16 | 16 |
17 ngx_array_t *flushes; | 17 ngx_array_t *flushes; |
18 ngx_array_t *params_len; | 18 ngx_array_t *params_len; |
19 ngx_array_t *params; | 19 ngx_array_t *params; |
20 ngx_array_t *params_source; | 20 ngx_array_t *params_source; |
21 | |
22 ngx_hash_t headers_hash; | |
23 ngx_uint_t header_params; | |
21 | 24 |
22 ngx_array_t *uwsgi_lengths; | 25 ngx_array_t *uwsgi_lengths; |
23 ngx_array_t *uwsgi_values; | 26 ngx_array_t *uwsgi_values; |
24 | 27 |
25 ngx_str_t uwsgi_string; | 28 ngx_str_t uwsgi_string; |
431 | 434 |
432 | 435 |
433 static ngx_int_t | 436 static ngx_int_t |
434 ngx_http_uwsgi_create_request(ngx_http_request_t *r) | 437 ngx_http_uwsgi_create_request(ngx_http_request_t *r) |
435 { | 438 { |
436 u_char ch; | 439 u_char ch, *lowcase_key; |
437 size_t key_len, val_len, len; | 440 size_t key_len, val_len, len, allocated; |
438 ngx_uint_t i, n; | 441 ngx_uint_t i, n, hash, header_params; |
439 ngx_buf_t *b; | 442 ngx_buf_t *b; |
440 ngx_chain_t *cl, *body; | 443 ngx_chain_t *cl, *body; |
441 ngx_list_part_t *part; | 444 ngx_list_part_t *part; |
442 ngx_table_elt_t *header; | 445 ngx_table_elt_t *header, **ignored; |
443 ngx_http_script_code_pt code; | 446 ngx_http_script_code_pt code; |
444 ngx_http_script_engine_t e, le; | 447 ngx_http_script_engine_t e, le; |
445 ngx_http_uwsgi_loc_conf_t *uwcf; | 448 ngx_http_uwsgi_loc_conf_t *uwcf; |
446 ngx_http_script_len_code_pt lcode; | 449 ngx_http_script_len_code_pt lcode; |
447 | 450 |
448 len = 0; | 451 len = 0; |
452 header_params = 0; | |
453 ignored = NULL; | |
449 | 454 |
450 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); | 455 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module); |
451 | 456 |
452 if (uwcf->params_len) { | 457 if (uwcf->params_len) { |
453 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); | 458 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); |
471 len += 2 + key_len + 2 + val_len; | 476 len += 2 + key_len + 2 + val_len; |
472 } | 477 } |
473 } | 478 } |
474 | 479 |
475 if (uwcf->upstream.pass_request_headers) { | 480 if (uwcf->upstream.pass_request_headers) { |
481 | |
482 allocated = 0; | |
483 lowcase_key = NULL; | |
484 | |
485 if (uwcf->header_params) { | |
486 ignored = ngx_palloc(r->pool, uwcf->header_params * sizeof(void *)); | |
487 if (ignored == NULL) { | |
488 return NGX_ERROR; | |
489 } | |
490 } | |
476 | 491 |
477 part = &r->headers_in.headers.part; | 492 part = &r->headers_in.headers.part; |
478 header = part->elts; | 493 header = part->elts; |
479 | 494 |
480 for (i = 0; /* void */ ; i++) { | 495 for (i = 0; /* void */ ; i++) { |
487 part = part->next; | 502 part = part->next; |
488 header = part->elts; | 503 header = part->elts; |
489 i = 0; | 504 i = 0; |
490 } | 505 } |
491 | 506 |
492 len += 2 + 5 + header[i].key.len + 2 + header[i].value.len; | 507 if (uwcf->header_params) { |
508 if (allocated < header[i].key.len) { | |
509 allocated = header[i].key.len + 16; | |
510 lowcase_key = ngx_pnalloc(r->pool, allocated); | |
511 if (lowcase_key == NULL) { | |
512 return NGX_ERROR; | |
513 } | |
514 } | |
515 | |
516 hash = 0; | |
517 | |
518 for (n = 0; n < header[i].key.len; n++) { | |
519 ch = header[i].key.data[n]; | |
520 | |
521 if (ch >= 'A' && ch <= 'Z') { | |
522 ch |= 0x20; | |
523 | |
524 } else if (ch == '-') { | |
525 ch = '_'; | |
526 } | |
527 | |
528 hash = ngx_hash(hash, ch); | |
529 lowcase_key[n] = ch; | |
530 } | |
531 | |
532 if (ngx_hash_find(&uwcf->headers_hash, hash, lowcase_key, n)) { | |
533 ignored[header_params++] = &header[i]; | |
534 continue; | |
535 } | |
536 } | |
537 | |
538 len += 2 + sizeof("HTTP_") - 1 + header[i].key.len | |
539 + 2 + header[i].value.len; | |
493 } | 540 } |
494 } | 541 } |
495 | 542 |
496 len += uwcf->uwsgi_string.len; | 543 len += uwcf->uwsgi_string.len; |
497 | 544 |
581 part = part->next; | 628 part = part->next; |
582 header = part->elts; | 629 header = part->elts; |
583 i = 0; | 630 i = 0; |
584 } | 631 } |
585 | 632 |
586 key_len = 5 + header[i].key.len; | 633 for (n = 0; n < header_params; n++) { |
634 if (&header[i] == ignored[n]) { | |
635 goto next; | |
636 } | |
637 } | |
638 | |
639 key_len = sizeof("HTTP_") - 1 + header[i].key.len; | |
587 *b->last++ = (u_char) (key_len & 0xff); | 640 *b->last++ = (u_char) (key_len & 0xff); |
588 *b->last++ = (u_char) ((key_len >> 8) & 0xff); | 641 *b->last++ = (u_char) ((key_len >> 8) & 0xff); |
589 | 642 |
590 b->last = ngx_cpymem(b->last, "HTTP_", 5); | 643 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); |
591 for (n = 0; n < header[i].key.len; n++) { | 644 for (n = 0; n < header[i].key.len; n++) { |
592 ch = header[i].key.data[n]; | 645 ch = header[i].key.data[n]; |
593 | 646 |
594 if (ch >= 'a' && ch <= 'z') { | 647 if (ch >= 'a' && ch <= 'z') { |
595 ch &= ~0x20; | 648 ch &= ~0x20; |
608 | 661 |
609 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 662 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
610 "uwsgi param: \"%*s: %*s\"", | 663 "uwsgi param: \"%*s: %*s\"", |
611 key_len, b->last - (key_len + 2 + val_len), | 664 key_len, b->last - (key_len + 2 + val_len), |
612 val_len, b->last - val_len); | 665 val_len, b->last - val_len); |
666 next: | |
667 | |
668 continue; | |
613 } | 669 } |
614 } | 670 } |
615 | 671 |
616 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, | 672 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, |
617 uwcf->uwsgi_string.len); | 673 uwcf->uwsgi_string.len); |
1128 | 1184 |
1129 u_char *p; | 1185 u_char *p; |
1130 size_t size; | 1186 size_t size; |
1131 uintptr_t *code; | 1187 uintptr_t *code; |
1132 ngx_uint_t i; | 1188 ngx_uint_t i; |
1189 ngx_array_t headers_names; | |
1133 ngx_keyval_t *src; | 1190 ngx_keyval_t *src; |
1191 ngx_hash_key_t *hk; | |
1134 ngx_hash_init_t hash; | 1192 ngx_hash_init_t hash; |
1135 ngx_http_script_compile_t sc; | 1193 ngx_http_script_compile_t sc; |
1136 ngx_http_script_copy_code_t *copy; | 1194 ngx_http_script_copy_code_t *copy; |
1137 | 1195 |
1138 if (conf->upstream.store != 0) { | 1196 if (conf->upstream.store != 0) { |
1322 if (conf->params_source == NULL) { | 1380 if (conf->params_source == NULL) { |
1323 conf->flushes = prev->flushes; | 1381 conf->flushes = prev->flushes; |
1324 conf->params_len = prev->params_len; | 1382 conf->params_len = prev->params_len; |
1325 conf->params = prev->params; | 1383 conf->params = prev->params; |
1326 conf->params_source = prev->params_source; | 1384 conf->params_source = prev->params_source; |
1385 conf->headers_hash = prev->headers_hash; | |
1327 | 1386 |
1328 if (conf->params_source == NULL) { | 1387 if (conf->params_source == NULL) { |
1329 return NGX_CONF_OK; | 1388 return NGX_CONF_OK; |
1330 } | 1389 } |
1331 } | 1390 } |
1338 conf->params = ngx_array_create(cf->pool, 512, 1); | 1397 conf->params = ngx_array_create(cf->pool, 512, 1); |
1339 if (conf->params == NULL) { | 1398 if (conf->params == NULL) { |
1340 return NGX_CONF_ERROR; | 1399 return NGX_CONF_ERROR; |
1341 } | 1400 } |
1342 | 1401 |
1402 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | |
1403 != NGX_OK) | |
1404 { | |
1405 return NGX_CONF_ERROR; | |
1406 } | |
1407 | |
1343 src = conf->params_source->elts; | 1408 src = conf->params_source->elts; |
1344 for (i = 0; i < conf->params_source->nelts; i++) { | 1409 for (i = 0; i < conf->params_source->nelts; i++) { |
1410 | |
1411 if (src[i].key.len > sizeof("HTTP_") - 1 | |
1412 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) | |
1413 { | |
1414 hk = ngx_array_push(&headers_names); | |
1415 if (hk == NULL) { | |
1416 return NGX_CONF_ERROR; | |
1417 } | |
1418 | |
1419 hk->key.len = src[i].key.len - 5; | |
1420 hk->key.data = src[i].key.data + 5; | |
1421 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); | |
1422 hk->value = (void *) 1; | |
1423 | |
1424 if (src[i].value.len == 0) { | |
1425 continue; | |
1426 } | |
1427 } | |
1345 | 1428 |
1346 copy = ngx_array_push_n(conf->params_len, | 1429 copy = ngx_array_push_n(conf->params_len, |
1347 sizeof(ngx_http_script_copy_code_t)); | 1430 sizeof(ngx_http_script_copy_code_t)); |
1348 if (copy == NULL) { | 1431 if (copy == NULL) { |
1349 return NGX_CONF_ERROR; | 1432 return NGX_CONF_ERROR; |
1401 if (code == NULL) { | 1484 if (code == NULL) { |
1402 return NGX_CONF_ERROR; | 1485 return NGX_CONF_ERROR; |
1403 } | 1486 } |
1404 | 1487 |
1405 *code = (uintptr_t) NULL; | 1488 *code = (uintptr_t) NULL; |
1489 | |
1490 conf->header_params = headers_names.nelts; | |
1491 | |
1492 hash.hash = &conf->headers_hash; | |
1493 hash.key = ngx_hash_key_lc; | |
1494 hash.max_size = 512; | |
1495 hash.bucket_size = 64; | |
1496 hash.name = "uwsgi_params_hash"; | |
1497 hash.pool = cf->pool; | |
1498 hash.temp_pool = NULL; | |
1499 | |
1500 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) | |
1501 { | |
1502 return NGX_CONF_ERROR; | |
1503 } | |
1406 | 1504 |
1407 return NGX_CONF_OK; | 1505 return NGX_CONF_OK; |
1408 } | 1506 } |
1409 | 1507 |
1410 | 1508 |