Mercurial > hg > nginx
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 |