comparison src/http/modules/ngx_http_fastcgi_module.c @ 3560:a36c63c6d26a

allow fastcgi_param to override client headers using HTTP_ parameters
author Igor Sysoev <igor@sysoev.ru>
date Thu, 03 Jun 2010 14:41:30 +0000
parents 519dcf4cb3de
children e2d54eb7472e
comparison
equal deleted inserted replaced
3559:519dcf4cb3de 3560:a36c63c6d26a
20 ngx_array_t *params_source; 20 ngx_array_t *params_source;
21 ngx_array_t *catch_stderr; 21 ngx_array_t *catch_stderr;
22 22
23 ngx_array_t *fastcgi_lengths; 23 ngx_array_t *fastcgi_lengths;
24 ngx_array_t *fastcgi_values; 24 ngx_array_t *fastcgi_values;
25
26 ngx_hash_t headers_hash;
27 ngx_uint_t header_params;
25 28
26 #if (NGX_HTTP_CACHE) 29 #if (NGX_HTTP_CACHE)
27 ngx_http_complex_value_t cache_key; 30 ngx_http_complex_value_t cache_key;
28 #endif 31 #endif
29 32
690 693
691 static ngx_int_t 694 static ngx_int_t
692 ngx_http_fastcgi_create_request(ngx_http_request_t *r) 695 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
693 { 696 {
694 off_t file_pos; 697 off_t file_pos;
695 u_char ch, *pos; 698 u_char ch, *pos, *lowcase_key;
696 size_t size, len, key_len, val_len, padding; 699 size_t size, len, key_len, val_len, padding,
697 ngx_uint_t i, n, next; 700 allocated;
701 ngx_uint_t i, n, next, hash, header_params;
698 ngx_buf_t *b; 702 ngx_buf_t *b;
699 ngx_chain_t *cl, *body; 703 ngx_chain_t *cl, *body;
700 ngx_list_part_t *part; 704 ngx_list_part_t *part;
701 ngx_table_elt_t *header; 705 ngx_table_elt_t *header, **ignored;
702 ngx_http_script_code_pt code; 706 ngx_http_script_code_pt code;
703 ngx_http_script_engine_t e, le; 707 ngx_http_script_engine_t e, le;
704 ngx_http_fastcgi_header_t *h; 708 ngx_http_fastcgi_header_t *h;
705 ngx_http_fastcgi_loc_conf_t *flcf; 709 ngx_http_fastcgi_loc_conf_t *flcf;
706 ngx_http_script_len_code_pt lcode; 710 ngx_http_script_len_code_pt lcode;
707 711
708 len = 0; 712 len = 0;
713 header_params = 0;
714 ignored = NULL;
709 715
710 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); 716 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
711 717
712 if (flcf->params_len) { 718 if (flcf->params_len) {
713 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 719 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
731 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; 737 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
732 } 738 }
733 } 739 }
734 740
735 if (flcf->upstream.pass_request_headers) { 741 if (flcf->upstream.pass_request_headers) {
742
743 allocated = 0;
744 lowcase_key = NULL;
745
746 if (flcf->header_params) {
747 ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));
748 if (ignored == NULL) {
749 return NGX_ERROR;
750 }
751 }
736 752
737 part = &r->headers_in.headers.part; 753 part = &r->headers_in.headers.part;
738 header = part->elts; 754 header = part->elts;
739 755
740 for (i = 0; /* void */; i++) { 756 for (i = 0; /* void */; i++) {
747 part = part->next; 763 part = part->next;
748 header = part->elts; 764 header = part->elts;
749 i = 0; 765 i = 0;
750 } 766 }
751 767
752 len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1) 768 if (flcf->header_params) {
753 + ((header[i].value.len > 127) ? 4 : 1) 769 if (allocated < header[i].key.len) {
754 + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len; 770 allocated = header[i].key.len + 16;
771 lowcase_key = ngx_pnalloc(r->pool, allocated);
772 if (lowcase_key == NULL) {
773 return NGX_ERROR;
774 }
775 }
776
777 hash = 0;
778
779 for (n = 0; n < header[i].key.len; n++) {
780 ch = header[i].key.data[n];
781
782 if (ch >= 'A' && ch <= 'Z') {
783 ch |= 0x20;
784
785 } else if (ch == '-') {
786 ch = '_';
787 }
788
789 hash = ngx_hash(hash, ch);
790 lowcase_key[n] = ch;
791 }
792
793 if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {
794 ignored[header_params++] = &header[i];
795 continue;
796 }
797
798 n += sizeof("HTTP_") - 1;
799
800 } else {
801 n = sizeof("HTTP_") - 1 + header[i].key.len;
802 }
803
804 len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
805 + n + header[i].value.len;
755 } 806 }
756 } 807 }
757 808
758 809
759 if (len > 65535) { 810 if (len > 65535) {
867 } 918 }
868 919
869 part = part->next; 920 part = part->next;
870 header = part->elts; 921 header = part->elts;
871 i = 0; 922 i = 0;
923 }
924
925 for (n = 0; n < header_params; n++) {
926 if (&header[i] == ignored[n]) {
927 goto next;
928 }
872 } 929 }
873 930
874 key_len = sizeof("HTTP_") - 1 + header[i].key.len; 931 key_len = sizeof("HTTP_") - 1 + header[i].key.len;
875 if (key_len > 127) { 932 if (key_len > 127) {
876 *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80); 933 *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
912 969
913 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 970 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
914 "fastcgi param: \"%*s: %*s\"", 971 "fastcgi param: \"%*s: %*s\"",
915 key_len, b->last - (key_len + val_len), 972 key_len, b->last - (key_len + val_len),
916 val_len, b->last - val_len); 973 val_len, b->last - val_len);
974 next:
975
976 continue;
917 } 977 }
918 } 978 }
919 979
920 980
921 if (padding) { 981 if (padding) {
1961 u_char *p; 2021 u_char *p;
1962 size_t size; 2022 size_t size;
1963 uintptr_t *code; 2023 uintptr_t *code;
1964 ngx_str_t *h; 2024 ngx_str_t *h;
1965 ngx_uint_t i; 2025 ngx_uint_t i;
2026 ngx_array_t headers_names;
1966 ngx_keyval_t *src; 2027 ngx_keyval_t *src;
2028 ngx_hash_key_t *hk;
1967 ngx_hash_init_t hash; 2029 ngx_hash_init_t hash;
1968 ngx_http_script_compile_t sc; 2030 ngx_http_script_compile_t sc;
1969 ngx_http_script_copy_code_t *copy; 2031 ngx_http_script_copy_code_t *copy;
1970 2032
1971 if (conf->upstream.store != 0) { 2033 if (conf->upstream.store != 0) {
2221 if (conf->params_source == NULL) { 2283 if (conf->params_source == NULL) {
2222 conf->flushes = prev->flushes; 2284 conf->flushes = prev->flushes;
2223 conf->params_len = prev->params_len; 2285 conf->params_len = prev->params_len;
2224 conf->params = prev->params; 2286 conf->params = prev->params;
2225 conf->params_source = prev->params_source; 2287 conf->params_source = prev->params_source;
2288 conf->headers_hash = prev->headers_hash;
2226 2289
2227 if (conf->params_source == NULL) { 2290 if (conf->params_source == NULL) {
2228 return NGX_CONF_OK; 2291 return NGX_CONF_OK;
2229 } 2292 }
2230 } 2293 }
2237 conf->params = ngx_array_create(cf->pool, 512, 1); 2300 conf->params = ngx_array_create(cf->pool, 512, 1);
2238 if (conf->params == NULL) { 2301 if (conf->params == NULL) {
2239 return NGX_CONF_ERROR; 2302 return NGX_CONF_ERROR;
2240 } 2303 }
2241 2304
2305 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
2306 != NGX_OK)
2307 {
2308 return NGX_CONF_ERROR;
2309 }
2310
2242 src = conf->params_source->elts; 2311 src = conf->params_source->elts;
2243 for (i = 0; i < conf->params_source->nelts; i++) { 2312 for (i = 0; i < conf->params_source->nelts; i++) {
2313
2314 if (src[i].key.len > sizeof("HTTP_") - 1
2315 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
2316 {
2317 hk = ngx_array_push(&headers_names);
2318 if (hk == NULL) {
2319 return NGX_CONF_ERROR;
2320 }
2321
2322 hk->key.len = src[i].key.len - 5;
2323 hk->key.data = src[i].key.data + 5;
2324 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
2325 hk->value = (void *) 1;
2326
2327 if (src[i].value.len == 0) {
2328 continue;
2329 }
2330 }
2244 2331
2245 copy = ngx_array_push_n(conf->params_len, 2332 copy = ngx_array_push_n(conf->params_len,
2246 sizeof(ngx_http_script_copy_code_t)); 2333 sizeof(ngx_http_script_copy_code_t));
2247 if (copy == NULL) { 2334 if (copy == NULL) {
2248 return NGX_CONF_ERROR; 2335 return NGX_CONF_ERROR;
2300 if (code == NULL) { 2387 if (code == NULL) {
2301 return NGX_CONF_ERROR; 2388 return NGX_CONF_ERROR;
2302 } 2389 }
2303 2390
2304 *code = (uintptr_t) NULL; 2391 *code = (uintptr_t) NULL;
2392
2393
2394 conf->header_params = headers_names.nelts;
2395
2396 hash.hash = &conf->headers_hash;
2397 hash.key = ngx_hash_key_lc;
2398 hash.max_size = 512;
2399 hash.bucket_size = 64;
2400 hash.name = "fastcgi_params_hash";
2401 hash.pool = cf->pool;
2402 hash.temp_pool = NULL;
2403
2404 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
2405 {
2406 return NGX_CONF_ERROR;
2407 }
2305 2408
2306 return NGX_CONF_OK; 2409 return NGX_CONF_OK;
2307 } 2410 }
2308 2411
2309 2412