comparison src/http/modules/ngx_http_fastcgi_module.c @ 576:01f2313e34f1 NGINX_0_8_40

nginx 0.8.40 *) Security: now nginx/Windows ignores default file stream name. Thanks to Jose Antonio Vazquez Gonzalez. *) Feature: the ngx_http_uwsgi_module. Thanks to Roberto De Ioris. *) Feature: a "fastcgi_param" directive with value starting with "HTTP_" overrides a client request header line. *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request header lines were passed to FastCGI-server while caching. *) Bugfix: listen unix domain socket could not be changed during reconfiguration. Thanks to Maxim Dounin.
author Igor Sysoev <http://sysoev.ru>
date Mon, 07 Jun 2010 00:00:00 +0400
parents ff463db0be31
children bc110f60c0de
comparison
equal deleted inserted replaced
575:6ad548c0b830 576:01f2313e34f1
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
531 ngx_string("Set-Cookie"), 534 ngx_string("Set-Cookie"),
532 ngx_string("P3P"), 535 ngx_string("P3P"),
533 ngx_null_string 536 ngx_null_string
534 }; 537 };
535 538
539
540 static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
541 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
542 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
543 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
544 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
545 { ngx_string("HTTP_RANGE"), ngx_string("") },
546 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
547 { ngx_null_string, ngx_null_string }
548 };
549
536 #endif 550 #endif
537 551
538 552
539 static ngx_path_init_t ngx_http_fastcgi_temp_path = { 553 static ngx_path_init_t ngx_http_fastcgi_temp_path = {
540 ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 } 554 ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
690 704
691 static ngx_int_t 705 static ngx_int_t
692 ngx_http_fastcgi_create_request(ngx_http_request_t *r) 706 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
693 { 707 {
694 off_t file_pos; 708 off_t file_pos;
695 u_char ch, *pos; 709 u_char ch, *pos, *lowcase_key;
696 size_t size, len, key_len, val_len, padding; 710 size_t size, len, key_len, val_len, padding,
697 ngx_uint_t i, n, next; 711 allocated;
712 ngx_uint_t i, n, next, hash, header_params;
698 ngx_buf_t *b; 713 ngx_buf_t *b;
699 ngx_chain_t *cl, *body; 714 ngx_chain_t *cl, *body;
700 ngx_list_part_t *part; 715 ngx_list_part_t *part;
701 ngx_table_elt_t *header; 716 ngx_table_elt_t *header, **ignored;
702 ngx_http_script_code_pt code; 717 ngx_http_script_code_pt code;
703 ngx_http_script_engine_t e, le; 718 ngx_http_script_engine_t e, le;
704 ngx_http_fastcgi_header_t *h; 719 ngx_http_fastcgi_header_t *h;
705 ngx_http_fastcgi_loc_conf_t *flcf; 720 ngx_http_fastcgi_loc_conf_t *flcf;
706 ngx_http_script_len_code_pt lcode; 721 ngx_http_script_len_code_pt lcode;
707 722
708 len = 0; 723 len = 0;
724 header_params = 0;
725 ignored = NULL;
709 726
710 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); 727 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
711 728
712 if (flcf->params_len) { 729 if (flcf->params_len) {
713 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 730 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
731 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; 748 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
732 } 749 }
733 } 750 }
734 751
735 if (flcf->upstream.pass_request_headers) { 752 if (flcf->upstream.pass_request_headers) {
753
754 allocated = 0;
755 lowcase_key = NULL;
756
757 if (flcf->header_params) {
758 ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));
759 if (ignored == NULL) {
760 return NGX_ERROR;
761 }
762 }
736 763
737 part = &r->headers_in.headers.part; 764 part = &r->headers_in.headers.part;
738 header = part->elts; 765 header = part->elts;
739 766
740 for (i = 0; /* void */; i++) { 767 for (i = 0; /* void */; i++) {
747 part = part->next; 774 part = part->next;
748 header = part->elts; 775 header = part->elts;
749 i = 0; 776 i = 0;
750 } 777 }
751 778
752 len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1) 779 if (flcf->header_params) {
753 + ((header[i].value.len > 127) ? 4 : 1) 780 if (allocated < header[i].key.len) {
754 + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len; 781 allocated = header[i].key.len + 16;
782 lowcase_key = ngx_pnalloc(r->pool, allocated);
783 if (lowcase_key == NULL) {
784 return NGX_ERROR;
785 }
786 }
787
788 hash = 0;
789
790 for (n = 0; n < header[i].key.len; n++) {
791 ch = header[i].key.data[n];
792
793 if (ch >= 'A' && ch <= 'Z') {
794 ch |= 0x20;
795
796 } else if (ch == '-') {
797 ch = '_';
798 }
799
800 hash = ngx_hash(hash, ch);
801 lowcase_key[n] = ch;
802 }
803
804 if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {
805 ignored[header_params++] = &header[i];
806 continue;
807 }
808
809 n += sizeof("HTTP_") - 1;
810
811 } else {
812 n = sizeof("HTTP_") - 1 + header[i].key.len;
813 }
814
815 len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
816 + n + header[i].value.len;
755 } 817 }
756 } 818 }
757 819
758 820
759 if (len > 65535) { 821 if (len > 65535) {
869 part = part->next; 931 part = part->next;
870 header = part->elts; 932 header = part->elts;
871 i = 0; 933 i = 0;
872 } 934 }
873 935
874 len = sizeof("HTTP_") - 1 + header[i].key.len; 936 for (n = 0; n < header_params; n++) {
875 if (len > 127) { 937 if (&header[i] == ignored[n]) {
876 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 938 goto next;
877 *b->last++ = (u_char) ((len >> 16) & 0xff); 939 }
878 *b->last++ = (u_char) ((len >> 8) & 0xff); 940 }
879 *b->last++ = (u_char) (len & 0xff); 941
942 key_len = sizeof("HTTP_") - 1 + header[i].key.len;
943 if (key_len > 127) {
944 *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
945 *b->last++ = (u_char) ((key_len >> 16) & 0xff);
946 *b->last++ = (u_char) ((key_len >> 8) & 0xff);
947 *b->last++ = (u_char) (key_len & 0xff);
880 948
881 } else { 949 } else {
882 *b->last++ = (u_char) len; 950 *b->last++ = (u_char) key_len;
883 } 951 }
884 952
885 len = header[i].value.len; 953 val_len = header[i].value.len;
886 if (len > 127) { 954 if (val_len > 127) {
887 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 955 *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
888 *b->last++ = (u_char) ((len >> 16) & 0xff); 956 *b->last++ = (u_char) ((val_len >> 16) & 0xff);
889 *b->last++ = (u_char) ((len >> 8) & 0xff); 957 *b->last++ = (u_char) ((val_len >> 8) & 0xff);
890 *b->last++ = (u_char) (len & 0xff); 958 *b->last++ = (u_char) (val_len & 0xff);
891 959
892 } else { 960 } else {
893 *b->last++ = (u_char) len; 961 *b->last++ = (u_char) val_len;
894 } 962 }
895 963
896 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); 964 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
897 965
898 for (n = 0; n < header[i].key.len; n++) { 966 for (n = 0; n < header[i].key.len; n++) {
906 } 974 }
907 975
908 *b->last++ = ch; 976 *b->last++ = ch;
909 } 977 }
910 978
911 b->last = ngx_copy(b->last, header[i].value.data, 979 b->last = ngx_copy(b->last, header[i].value.data, val_len);
912 header[i].value.len); 980
981 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
982 "fastcgi param: \"%*s: %*s\"",
983 key_len, b->last - (key_len + val_len),
984 val_len, b->last - val_len);
985 next:
986
987 continue;
913 } 988 }
914 } 989 }
915 990
916 991
917 if (padding) { 992 if (padding) {
1955 ngx_http_fastcgi_loc_conf_t *conf = child; 2030 ngx_http_fastcgi_loc_conf_t *conf = child;
1956 2031
1957 u_char *p; 2032 u_char *p;
1958 size_t size; 2033 size_t size;
1959 uintptr_t *code; 2034 uintptr_t *code;
1960 ngx_str_t *h; 2035 ngx_str_t *hide;
1961 ngx_uint_t i; 2036 ngx_uint_t i;
2037 ngx_array_t headers_names;
1962 ngx_keyval_t *src; 2038 ngx_keyval_t *src;
2039 ngx_hash_key_t *hk;
1963 ngx_hash_init_t hash; 2040 ngx_hash_init_t hash;
1964 ngx_http_script_compile_t sc; 2041 ngx_http_script_compile_t sc;
1965 ngx_http_script_copy_code_t *copy; 2042 ngx_http_script_copy_code_t *copy;
1966 2043
1967 if (conf->upstream.store != 0) { 2044 if (conf->upstream.store != 0) {
2181 hash.bucket_size = ngx_align(64, ngx_cacheline_size); 2258 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
2182 hash.name = "fastcgi_hide_headers_hash"; 2259 hash.name = "fastcgi_hide_headers_hash";
2183 2260
2184 #if (NGX_HTTP_CACHE) 2261 #if (NGX_HTTP_CACHE)
2185 2262
2186 h = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers: 2263 hide = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
2187 ngx_http_fastcgi_hide_headers; 2264 ngx_http_fastcgi_hide_headers;
2188 #else 2265 #else
2189 2266
2190 h = ngx_http_fastcgi_hide_headers; 2267 hide = ngx_http_fastcgi_hide_headers;
2191 2268
2192 #endif 2269 #endif
2193 2270
2194 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, 2271 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
2195 &prev->upstream, h, &hash) 2272 &prev->upstream, hide, &hash)
2196 != NGX_OK) 2273 != NGX_OK)
2197 { 2274 {
2198 return NGX_CONF_ERROR; 2275 return NGX_CONF_ERROR;
2199 } 2276 }
2200 2277
2217 if (conf->params_source == NULL) { 2294 if (conf->params_source == NULL) {
2218 conf->flushes = prev->flushes; 2295 conf->flushes = prev->flushes;
2219 conf->params_len = prev->params_len; 2296 conf->params_len = prev->params_len;
2220 conf->params = prev->params; 2297 conf->params = prev->params;
2221 conf->params_source = prev->params_source; 2298 conf->params_source = prev->params_source;
2299 conf->headers_hash = prev->headers_hash;
2300
2301 #if (NGX_HTTP_CACHE)
2302
2303 if (conf->params_source == NULL) {
2304
2305 if ((conf->upstream.cache == NULL)
2306 == (prev->upstream.cache == NULL))
2307 {
2308 return NGX_CONF_OK;
2309 }
2310
2311 /* 6 is a number of ngx_http_fastcgi_cache_headers entries */
2312 conf->params_source = ngx_array_create(cf->pool, 6,
2313 sizeof(ngx_keyval_t));
2314 if (conf->params_source == NULL) {
2315 return NGX_CONF_ERROR;
2316 }
2317 }
2318 #else
2222 2319
2223 if (conf->params_source == NULL) { 2320 if (conf->params_source == NULL) {
2224 return NGX_CONF_OK; 2321 return NGX_CONF_OK;
2225 } 2322 }
2323
2324 #endif
2226 } 2325 }
2227 2326
2228 conf->params_len = ngx_array_create(cf->pool, 64, 1); 2327 conf->params_len = ngx_array_create(cf->pool, 64, 1);
2229 if (conf->params_len == NULL) { 2328 if (conf->params_len == NULL) {
2230 return NGX_CONF_ERROR; 2329 return NGX_CONF_ERROR;
2233 conf->params = ngx_array_create(cf->pool, 512, 1); 2332 conf->params = ngx_array_create(cf->pool, 512, 1);
2234 if (conf->params == NULL) { 2333 if (conf->params == NULL) {
2235 return NGX_CONF_ERROR; 2334 return NGX_CONF_ERROR;
2236 } 2335 }
2237 2336
2337 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
2338 != NGX_OK)
2339 {
2340 return NGX_CONF_ERROR;
2341 }
2342
2238 src = conf->params_source->elts; 2343 src = conf->params_source->elts;
2344
2345 #if (NGX_HTTP_CACHE)
2346
2347 if (conf->upstream.cache) {
2348 ngx_keyval_t *h, *s;
2349
2350 for (h = ngx_http_fastcgi_cache_headers; h->key.len; h++) {
2351
2352 for (i = 0; i < conf->params_source->nelts; i++) {
2353 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
2354 goto next;
2355 }
2356 }
2357
2358 s = ngx_array_push(conf->params_source);
2359 if (s == NULL) {
2360 return NGX_CONF_ERROR;
2361 }
2362
2363 *s = *h;
2364
2365 src = conf->params_source->elts;
2366
2367 next:
2368
2369 h++;
2370 }
2371 }
2372
2373 #endif
2374
2239 for (i = 0; i < conf->params_source->nelts; i++) { 2375 for (i = 0; i < conf->params_source->nelts; i++) {
2240 2376
2241 if (ngx_http_script_variables_count(&src[i].value) == 0) { 2377 if (src[i].key.len > sizeof("HTTP_") - 1
2242 copy = ngx_array_push_n(conf->params_len, 2378 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
2243 sizeof(ngx_http_script_copy_code_t)); 2379 {
2244 if (copy == NULL) { 2380 hk = ngx_array_push(&headers_names);
2381 if (hk == NULL) {
2245 return NGX_CONF_ERROR; 2382 return NGX_CONF_ERROR;
2246 } 2383 }
2247 2384
2248 copy->code = (ngx_http_script_code_pt) 2385 hk->key.len = src[i].key.len - 5;
2249 ngx_http_script_copy_len_code; 2386 hk->key.data = src[i].key.data + 5;
2250 copy->len = src[i].key.len; 2387 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
2251 2388 hk->value = (void *) 1;
2252 2389
2253 copy = ngx_array_push_n(conf->params_len, 2390 if (src[i].value.len == 0) {
2254 sizeof(ngx_http_script_copy_code_t)); 2391 continue;
2255 if (copy == NULL) { 2392 }
2256 return NGX_CONF_ERROR; 2393 }
2257 } 2394
2258 2395 copy = ngx_array_push_n(conf->params_len,
2259 copy->code = (ngx_http_script_code_pt) 2396 sizeof(ngx_http_script_copy_code_t));
2260 ngx_http_script_copy_len_code; 2397 if (copy == NULL) {
2261 copy->len = src[i].value.len; 2398 return NGX_CONF_ERROR;
2262 2399 }
2263 2400
2264 size = (sizeof(ngx_http_script_copy_code_t) 2401 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
2265 + src[i].key.len + src[i].value.len 2402 copy->len = src[i].key.len;
2266 + sizeof(uintptr_t) - 1) 2403
2267 & ~(sizeof(uintptr_t) - 1); 2404
2268 2405 size = (sizeof(ngx_http_script_copy_code_t)
2269 copy = ngx_array_push_n(conf->params, size); 2406 + src[i].key.len + sizeof(uintptr_t) - 1)
2270 if (copy == NULL) { 2407 & ~(sizeof(uintptr_t) - 1);
2271 return NGX_CONF_ERROR; 2408
2272 } 2409 copy = ngx_array_push_n(conf->params, size);
2273 2410 if (copy == NULL) {
2274 copy->code = ngx_http_script_copy_code; 2411 return NGX_CONF_ERROR;
2275 copy->len = src[i].key.len + src[i].value.len; 2412 }
2276 2413
2277 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); 2414 copy->code = ngx_http_script_copy_code;
2278 2415 copy->len = src[i].key.len;
2279 p = ngx_cpymem(p, src[i].key.data, src[i].key.len); 2416
2280 ngx_memcpy(p, src[i].value.data, src[i].value.len); 2417 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2281 2418 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2282 } else { 2419
2283 copy = ngx_array_push_n(conf->params_len, 2420
2284 sizeof(ngx_http_script_copy_code_t)); 2421 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2285 if (copy == NULL) { 2422
2286 return NGX_CONF_ERROR; 2423 sc.cf = cf;
2287 } 2424 sc.source = &src[i].value;
2288 2425 sc.flushes = &conf->flushes;
2289 copy->code = (ngx_http_script_code_pt) 2426 sc.lengths = &conf->params_len;
2290 ngx_http_script_copy_len_code; 2427 sc.values = &conf->params;
2291 copy->len = src[i].key.len; 2428
2292 2429 if (ngx_http_script_compile(&sc) != NGX_OK) {
2293 2430 return NGX_CONF_ERROR;
2294 size = (sizeof(ngx_http_script_copy_code_t)
2295 + src[i].key.len + sizeof(uintptr_t) - 1)
2296 & ~(sizeof(uintptr_t) - 1);
2297
2298 copy = ngx_array_push_n(conf->params, size);
2299 if (copy == NULL) {
2300 return NGX_CONF_ERROR;
2301 }
2302
2303 copy->code = ngx_http_script_copy_code;
2304 copy->len = src[i].key.len;
2305
2306 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2307 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2308
2309
2310 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2311
2312 sc.cf = cf;
2313 sc.source = &src[i].value;
2314 sc.flushes = &conf->flushes;
2315 sc.lengths = &conf->params_len;
2316 sc.values = &conf->params;
2317
2318 if (ngx_http_script_compile(&sc) != NGX_OK) {
2319 return NGX_CONF_ERROR;
2320 }
2321 } 2431 }
2322 2432
2323 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); 2433 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
2324 if (code == NULL) { 2434 if (code == NULL) {
2325 return NGX_CONF_ERROR; 2435 return NGX_CONF_ERROR;
2340 if (code == NULL) { 2450 if (code == NULL) {
2341 return NGX_CONF_ERROR; 2451 return NGX_CONF_ERROR;
2342 } 2452 }
2343 2453
2344 *code = (uintptr_t) NULL; 2454 *code = (uintptr_t) NULL;
2455
2456
2457 conf->header_params = headers_names.nelts;
2458
2459 hash.hash = &conf->headers_hash;
2460 hash.key = ngx_hash_key_lc;
2461 hash.max_size = 512;
2462 hash.bucket_size = 64;
2463 hash.name = "fastcgi_params_hash";
2464 hash.pool = cf->pool;
2465 hash.temp_pool = NULL;
2466
2467 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
2468 {
2469 return NGX_CONF_ERROR;
2470 }
2345 2471
2346 return NGX_CONF_OK; 2472 return NGX_CONF_OK;
2347 } 2473 }
2348 2474
2349 2475