comparison src/http/modules/ngx_http_fastcgi_module.c @ 635:e67b227c8dbb default tip

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:07:55 +0400
parents b9763778e212
children
comparison
equal deleted inserted replaced
578:f3a9e57d2e17 635:e67b227c8dbb
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
160 #endif 163 #endif
161 164
162 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, 165 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
163 void *data); 166 void *data);
164 167
165 static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
166 ngx_command_t *cmd, void *conf);
167 static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
168 ngx_command_t *cmd, void *conf);
169
170 168
171 static ngx_conf_post_t ngx_http_fastcgi_lowat_post = 169 static ngx_conf_post_t ngx_http_fastcgi_lowat_post =
172 { ngx_http_fastcgi_lowat_check }; 170 { ngx_http_fastcgi_lowat_check };
173 171
174 172
183 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, 181 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
184 { ngx_null_string, 0 } 182 { ngx_null_string, 0 }
185 }; 183 };
186 184
187 185
188 static ngx_conf_bitmask_t ngx_http_fastcgi_ignore_headers_masks[] = {
189 { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
190 { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
191 { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
192 { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
193 { ngx_null_string, 0 }
194 };
195
196
197 ngx_module_t ngx_http_fastcgi_module; 186 ngx_module_t ngx_http_fastcgi_module;
198 187
199 188
200 static ngx_command_t ngx_http_fastcgi_commands[] = { 189 static ngx_command_t ngx_http_fastcgi_commands[] = {
201 190
319 NULL }, 308 NULL },
320 309
321 #if (NGX_HTTP_CACHE) 310 #if (NGX_HTTP_CACHE)
322 311
323 { ngx_string("fastcgi_cache"), 312 { ngx_string("fastcgi_cache"),
324 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 313 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
325 ngx_http_fastcgi_cache, 314 ngx_http_fastcgi_cache,
326 NGX_HTTP_LOC_CONF_OFFSET, 315 NGX_HTTP_LOC_CONF_OFFSET,
327 0, 316 0,
328 NULL }, 317 NULL },
329 318
330 { ngx_string("fastcgi_cache_key"), 319 { ngx_string("fastcgi_cache_key"),
331 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 320 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
332 ngx_http_fastcgi_cache_key, 321 ngx_http_fastcgi_cache_key,
333 NGX_HTTP_LOC_CONF_OFFSET, 322 NGX_HTTP_LOC_CONF_OFFSET,
334 0, 323 0,
335 NULL }, 324 NULL },
336 325
339 ngx_http_file_cache_set_slot, 328 ngx_http_file_cache_set_slot,
340 0, 329 0,
341 0, 330 0,
342 &ngx_http_fastcgi_module }, 331 &ngx_http_fastcgi_module },
343 332
333 { ngx_string("fastcgi_cache_bypass"),
334 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
335 ngx_http_set_predicate_slot,
336 NGX_HTTP_LOC_CONF_OFFSET,
337 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_bypass),
338 NULL },
339
340 { ngx_string("fastcgi_no_cache"),
341 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
342 ngx_http_set_predicate_slot,
343 NGX_HTTP_LOC_CONF_OFFSET,
344 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache),
345 NULL },
346
344 { ngx_string("fastcgi_cache_valid"), 347 { ngx_string("fastcgi_cache_valid"),
345 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, 348 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
346 ngx_http_file_cache_valid_set_slot, 349 ngx_http_file_cache_valid_set_slot,
347 NGX_HTTP_LOC_CONF_OFFSET, 350 NGX_HTTP_LOC_CONF_OFFSET,
348 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid), 351 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid),
397 ngx_conf_set_bitmask_slot, 400 ngx_conf_set_bitmask_slot,
398 NGX_HTTP_LOC_CONF_OFFSET, 401 NGX_HTTP_LOC_CONF_OFFSET,
399 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream), 402 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
400 &ngx_http_fastcgi_next_upstream_masks }, 403 &ngx_http_fastcgi_next_upstream_masks },
401 404
402 { ngx_string("fastcgi_upstream_max_fails"),
403 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
404 ngx_http_fastcgi_upstream_max_fails_unsupported,
405 0,
406 0,
407 NULL },
408
409 { ngx_string("fastcgi_upstream_fail_timeout"),
410 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
411 ngx_http_fastcgi_upstream_fail_timeout_unsupported,
412 0,
413 0,
414 NULL },
415
416 { ngx_string("fastcgi_param"), 405 { ngx_string("fastcgi_param"),
417 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, 406 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
418 ngx_conf_set_keyval_slot, 407 ngx_conf_set_keyval_slot,
419 NGX_HTTP_LOC_CONF_OFFSET, 408 NGX_HTTP_LOC_CONF_OFFSET,
420 offsetof(ngx_http_fastcgi_loc_conf_t, params_source), 409 offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
421 NULL }, 410 NULL },
422 411
423 { ngx_string("fastcgi_pass_header"), 412 { ngx_string("fastcgi_pass_header"),
424 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 413 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
425 ngx_conf_set_str_array_slot, 414 ngx_conf_set_str_array_slot,
426 NGX_HTTP_LOC_CONF_OFFSET, 415 NGX_HTTP_LOC_CONF_OFFSET,
427 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers), 416 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
428 NULL }, 417 NULL },
429 418
430 { ngx_string("fastcgi_hide_header"), 419 { ngx_string("fastcgi_hide_header"),
431 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 420 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
432 ngx_conf_set_str_array_slot, 421 ngx_conf_set_str_array_slot,
433 NGX_HTTP_LOC_CONF_OFFSET, 422 NGX_HTTP_LOC_CONF_OFFSET,
434 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers), 423 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
435 NULL }, 424 NULL },
436 425
437 { ngx_string("fastcgi_ignore_headers"), 426 { ngx_string("fastcgi_ignore_headers"),
438 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, 427 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
439 ngx_conf_set_bitmask_slot, 428 ngx_conf_set_bitmask_slot,
440 NGX_HTTP_LOC_CONF_OFFSET, 429 NGX_HTTP_LOC_CONF_OFFSET,
441 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers), 430 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
442 &ngx_http_fastcgi_ignore_headers_masks }, 431 &ngx_http_upstream_ignore_headers_masks },
443 432
444 { ngx_string("fastcgi_catch_stderr"), 433 { ngx_string("fastcgi_catch_stderr"),
445 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 434 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
446 ngx_conf_set_str_array_slot, 435 ngx_conf_set_str_array_slot,
447 NGX_HTTP_LOC_CONF_OFFSET, 436 NGX_HTTP_LOC_CONF_OFFSET,
531 }; 520 };
532 521
533 522
534 #if (NGX_HTTP_CACHE) 523 #if (NGX_HTTP_CACHE)
535 524
536 static ngx_str_t ngx_http_fastcgi_hide_cache_headers[] = { 525 static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
537 ngx_string("Status"), 526 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
538 ngx_string("X-Accel-Expires"), 527 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
539 ngx_string("X-Accel-Redirect"), 528 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
540 ngx_string("X-Accel-Limit-Rate"), 529 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
541 ngx_string("X-Accel-Buffering"), 530 { ngx_string("HTTP_RANGE"), ngx_string("") },
542 ngx_string("X-Accel-Charset"), 531 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
543 ngx_string("Set-Cookie"), 532 { ngx_null_string, ngx_null_string }
544 ngx_string("P3P"),
545 ngx_null_string
546 }; 533 };
547 534
548 #endif 535 #endif
549 536
550 537
587 } 574 }
588 } 575 }
589 576
590 u = r->upstream; 577 u = r->upstream;
591 578
592 u->schema.len = sizeof("fastcgi://") - 1; 579 ngx_str_set(&u->schema, "fastcgi://");
593 u->schema.data = (u_char *) "fastcgi://";
594
595 u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module; 580 u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
596 581
597 u->conf = &flcf->upstream; 582 u->conf = &flcf->upstream;
598 583
599 #if (NGX_HTTP_CACHE) 584 #if (NGX_HTTP_CACHE)
626 611
627 612
628 static ngx_int_t 613 static ngx_int_t
629 ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf) 614 ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
630 { 615 {
631 ngx_url_t u; 616 ngx_url_t url;
632 617 ngx_http_upstream_t *u;
633 ngx_memzero(&u, sizeof(ngx_url_t)); 618
634 619 ngx_memzero(&url, sizeof(ngx_url_t));
635 if (ngx_http_script_run(r, &u.url, flcf->fastcgi_lengths->elts, 0, 620
621 if (ngx_http_script_run(r, &url.url, flcf->fastcgi_lengths->elts, 0,
636 flcf->fastcgi_values->elts) 622 flcf->fastcgi_values->elts)
637 == NULL) 623 == NULL)
638 { 624 {
639 return NGX_ERROR; 625 return NGX_ERROR;
640 } 626 }
641 627
642 u.no_resolve = 1; 628 url.no_resolve = 1;
643 629
644 if (ngx_parse_url(r->pool, &u) != NGX_OK) { 630 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
645 if (u.err) { 631 if (url.err) {
646 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 632 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
647 "%s in upstream \"%V\"", u.err, &u.url); 633 "%s in upstream \"%V\"", url.err, &url.url);
648 } 634 }
649 635
650 return NGX_ERROR; 636 return NGX_ERROR;
651 } 637 }
652 638
653 if (u.no_port) { 639 u = r->upstream;
654 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 640
655 "no port in upstream \"%V\"", &u.url); 641 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
642 if (u->resolved == NULL) {
656 return NGX_ERROR; 643 return NGX_ERROR;
657 } 644 }
658 645
659 r->upstream->resolved = ngx_pcalloc(r->pool, 646 if (url.addrs && url.addrs[0].sockaddr) {
660 sizeof(ngx_http_upstream_resolved_t)); 647 u->resolved->sockaddr = url.addrs[0].sockaddr;
661 if (r->upstream->resolved == NULL) { 648 u->resolved->socklen = url.addrs[0].socklen;
662 return NGX_ERROR; 649 u->resolved->naddrs = 1;
663 } 650 u->resolved->host = url.addrs[0].name;
664
665 if (u.addrs && u.addrs[0].sockaddr) {
666 r->upstream->resolved->sockaddr = u.addrs[0].sockaddr;
667 r->upstream->resolved->socklen = u.addrs[0].socklen;
668 r->upstream->resolved->naddrs = 1;
669 r->upstream->resolved->host = u.addrs[0].name;
670 651
671 } else { 652 } else {
672 r->upstream->resolved->host = u.host; 653 u->resolved->host = url.host;
673 r->upstream->resolved->port = u.port; 654 u->resolved->port = url.port;
655 u->resolved->no_port = url.no_port;
674 } 656 }
675 657
676 return NGX_OK; 658 return NGX_OK;
677 } 659 }
678 660
704 686
705 static ngx_int_t 687 static ngx_int_t
706 ngx_http_fastcgi_create_request(ngx_http_request_t *r) 688 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
707 { 689 {
708 off_t file_pos; 690 off_t file_pos;
709 u_char ch, *pos; 691 u_char ch, *pos, *lowcase_key;
710 size_t size, len, key_len, val_len, padding; 692 size_t size, len, key_len, val_len, padding,
711 ngx_uint_t i, n, next; 693 allocated;
694 ngx_uint_t i, n, next, hash, header_params;
712 ngx_buf_t *b; 695 ngx_buf_t *b;
713 ngx_chain_t *cl, *body; 696 ngx_chain_t *cl, *body;
714 ngx_list_part_t *part; 697 ngx_list_part_t *part;
715 ngx_table_elt_t *header; 698 ngx_table_elt_t *header, **ignored;
716 ngx_http_script_code_pt code; 699 ngx_http_script_code_pt code;
717 ngx_http_script_engine_t e, le; 700 ngx_http_script_engine_t e, le;
718 ngx_http_fastcgi_header_t *h; 701 ngx_http_fastcgi_header_t *h;
719 ngx_http_fastcgi_loc_conf_t *flcf; 702 ngx_http_fastcgi_loc_conf_t *flcf;
720 ngx_http_script_len_code_pt lcode; 703 ngx_http_script_len_code_pt lcode;
721 704
722 len = 0; 705 len = 0;
706 header_params = 0;
707 ignored = NULL;
723 708
724 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); 709 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
725 710
726 if (flcf->params_len) { 711 if (flcf->params_len) {
727 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 712 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
745 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; 730 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
746 } 731 }
747 } 732 }
748 733
749 if (flcf->upstream.pass_request_headers) { 734 if (flcf->upstream.pass_request_headers) {
735
736 allocated = 0;
737 lowcase_key = NULL;
738
739 if (flcf->header_params) {
740 ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));
741 if (ignored == NULL) {
742 return NGX_ERROR;
743 }
744 }
750 745
751 part = &r->headers_in.headers.part; 746 part = &r->headers_in.headers.part;
752 header = part->elts; 747 header = part->elts;
753 748
754 for (i = 0; /* void */; i++) { 749 for (i = 0; /* void */; i++) {
761 part = part->next; 756 part = part->next;
762 header = part->elts; 757 header = part->elts;
763 i = 0; 758 i = 0;
764 } 759 }
765 760
766 len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1) 761 if (flcf->header_params) {
767 + ((header[i].value.len > 127) ? 4 : 1) 762 if (allocated < header[i].key.len) {
768 + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len; 763 allocated = header[i].key.len + 16;
764 lowcase_key = ngx_pnalloc(r->pool, allocated);
765 if (lowcase_key == NULL) {
766 return NGX_ERROR;
767 }
768 }
769
770 hash = 0;
771
772 for (n = 0; n < header[i].key.len; n++) {
773 ch = header[i].key.data[n];
774
775 if (ch >= 'A' && ch <= 'Z') {
776 ch |= 0x20;
777
778 } else if (ch == '-') {
779 ch = '_';
780 }
781
782 hash = ngx_hash(hash, ch);
783 lowcase_key[n] = ch;
784 }
785
786 if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {
787 ignored[header_params++] = &header[i];
788 continue;
789 }
790
791 n += sizeof("HTTP_") - 1;
792
793 } else {
794 n = sizeof("HTTP_") - 1 + header[i].key.len;
795 }
796
797 len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
798 + n + header[i].value.len;
769 } 799 }
770 } 800 }
771 801
772 802
773 if (len > 65535) { 803 if (len > 65535) {
883 part = part->next; 913 part = part->next;
884 header = part->elts; 914 header = part->elts;
885 i = 0; 915 i = 0;
886 } 916 }
887 917
888 len = sizeof("HTTP_") - 1 + header[i].key.len; 918 for (n = 0; n < header_params; n++) {
889 if (len > 127) { 919 if (&header[i] == ignored[n]) {
890 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 920 goto next;
891 *b->last++ = (u_char) ((len >> 16) & 0xff); 921 }
892 *b->last++ = (u_char) ((len >> 8) & 0xff); 922 }
893 *b->last++ = (u_char) (len & 0xff); 923
924 key_len = sizeof("HTTP_") - 1 + header[i].key.len;
925 if (key_len > 127) {
926 *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
927 *b->last++ = (u_char) ((key_len >> 16) & 0xff);
928 *b->last++ = (u_char) ((key_len >> 8) & 0xff);
929 *b->last++ = (u_char) (key_len & 0xff);
894 930
895 } else { 931 } else {
896 *b->last++ = (u_char) len; 932 *b->last++ = (u_char) key_len;
897 } 933 }
898 934
899 len = header[i].value.len; 935 val_len = header[i].value.len;
900 if (len > 127) { 936 if (val_len > 127) {
901 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 937 *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
902 *b->last++ = (u_char) ((len >> 16) & 0xff); 938 *b->last++ = (u_char) ((val_len >> 16) & 0xff);
903 *b->last++ = (u_char) ((len >> 8) & 0xff); 939 *b->last++ = (u_char) ((val_len >> 8) & 0xff);
904 *b->last++ = (u_char) (len & 0xff); 940 *b->last++ = (u_char) (val_len & 0xff);
905 941
906 } else { 942 } else {
907 *b->last++ = (u_char) len; 943 *b->last++ = (u_char) val_len;
908 } 944 }
909 945
910 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); 946 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
911 947
912 for (n = 0; n < header[i].key.len; n++) { 948 for (n = 0; n < header[i].key.len; n++) {
920 } 956 }
921 957
922 *b->last++ = ch; 958 *b->last++ = ch;
923 } 959 }
924 960
925 b->last = ngx_copy(b->last, header[i].value.data, 961 b->last = ngx_copy(b->last, header[i].value.data, val_len);
926 header[i].value.len); 962
963 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
964 "fastcgi param: \"%*s: %*s\"",
965 key_len, b->last - (key_len + val_len),
966 val_len, b->last - val_len);
967 next:
968
969 continue;
927 } 970 }
928 } 971 }
929 972
930 973
931 if (padding) { 974 if (padding) {
1099 ngx_buf_t buf; 1142 ngx_buf_t buf;
1100 ngx_uint_t i; 1143 ngx_uint_t i;
1101 ngx_table_elt_t *h; 1144 ngx_table_elt_t *h;
1102 ngx_http_upstream_t *u; 1145 ngx_http_upstream_t *u;
1103 ngx_http_fastcgi_ctx_t *f; 1146 ngx_http_fastcgi_ctx_t *f;
1104 ngx_http_fastcgi_header_t *fh;
1105 ngx_http_upstream_header_t *hh; 1147 ngx_http_upstream_header_t *hh;
1106 ngx_http_fastcgi_loc_conf_t *flcf; 1148 ngx_http_fastcgi_loc_conf_t *flcf;
1107 ngx_http_fastcgi_split_part_t *part; 1149 ngx_http_fastcgi_split_part_t *part;
1108 ngx_http_upstream_main_conf_t *umcf; 1150 ngx_http_upstream_main_conf_t *umcf;
1109 1151
1231 u->buffer.pos = u->buffer.start 1273 u->buffer.pos = u->buffer.start
1232 + r->cache->header_start; 1274 + r->cache->header_start;
1233 } else { 1275 } else {
1234 u->buffer.pos = u->buffer.start; 1276 u->buffer.pos = u->buffer.start;
1235 } 1277 }
1278 #else
1279 u->buffer.pos = u->buffer.start;
1236 #endif 1280 #endif
1237
1238 u->buffer.last = u->buffer.pos; 1281 u->buffer.last = u->buffer.pos;
1239 f->large_stderr = 1; 1282 f->large_stderr = 1;
1240 } 1283 }
1241 1284
1242 return NGX_AGAIN; 1285 return NGX_AGAIN;
1252 1295
1253 /* f->type == NGX_HTTP_FASTCGI_STDOUT */ 1296 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1254 1297
1255 #if (NGX_HTTP_CACHE) 1298 #if (NGX_HTTP_CACHE)
1256 1299
1257 if (f->large_stderr) { 1300 if (f->large_stderr && r->cache) {
1258 u_char *start; 1301 u_char *start;
1259 ssize_t len; 1302 ssize_t len;
1303 ngx_http_fastcgi_header_t *fh;
1260 1304
1261 start = u->buffer.start + r->cache->header_start; 1305 start = u->buffer.start + r->cache->header_start;
1262 1306
1263 len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t); 1307 len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
1264 1308
1447 u->headers_in.status_n = status; 1491 u->headers_in.status_n = status;
1448 u->headers_in.status_line = *status_line; 1492 u->headers_in.status_line = *status_line;
1449 1493
1450 } else if (u->headers_in.location) { 1494 } else if (u->headers_in.location) {
1451 u->headers_in.status_n = 302; 1495 u->headers_in.status_n = 302;
1452 u->headers_in.status_line.len = 1496 ngx_str_set(&u->headers_in.status_line,
1453 sizeof("302 Moved Temporarily") - 1; 1497 "302 Moved Temporarily");
1454 u->headers_in.status_line.data =
1455 (u_char *) "302 Moved Temporarily";
1456 1498
1457 } else { 1499 } else {
1458 u->headers_in.status_n = 200; 1500 u->headers_in.status_n = 200;
1459 u->headers_in.status_line.len = sizeof("200 OK") - 1; 1501 ngx_str_set(&u->headers_in.status_line, "200 OK");
1460 u->headers_in.status_line.data = (u_char *) "200 OK";
1461 } 1502 }
1462 1503
1463 if (u->state) { 1504 if (u->state) {
1464 u->state->status = u->headers_in.status_n; 1505 u->state->status = u->headers_in.status_n;
1465 } 1506 }
1920 * conf->upstream.uri = { 0, NULL }; 1961 * conf->upstream.uri = { 0, NULL };
1921 * conf->upstream.location = NULL; 1962 * conf->upstream.location = NULL;
1922 * conf->upstream.store_lengths = NULL; 1963 * conf->upstream.store_lengths = NULL;
1923 * conf->upstream.store_values = NULL; 1964 * conf->upstream.store_values = NULL;
1924 * 1965 *
1925 * conf->index.len = 0; 1966 * conf->index.len = { 0, NULL };
1926 * conf->index.data = NULL;
1927 */ 1967 */
1928 1968
1929 conf->upstream.store = NGX_CONF_UNSET; 1969 conf->upstream.store = NGX_CONF_UNSET;
1930 conf->upstream.store_access = NGX_CONF_UNSET_UINT; 1970 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
1931 conf->upstream.buffering = NGX_CONF_UNSET; 1971 conf->upstream.buffering = NGX_CONF_UNSET;
1946 conf->upstream.pass_request_body = NGX_CONF_UNSET; 1986 conf->upstream.pass_request_body = NGX_CONF_UNSET;
1947 1987
1948 #if (NGX_HTTP_CACHE) 1988 #if (NGX_HTTP_CACHE)
1949 conf->upstream.cache = NGX_CONF_UNSET_PTR; 1989 conf->upstream.cache = NGX_CONF_UNSET_PTR;
1950 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; 1990 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
1991 conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
1992 conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
1951 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; 1993 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1952 #endif 1994 #endif
1953 1995
1954 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; 1996 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
1955 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; 1997 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
1972 ngx_http_fastcgi_loc_conf_t *conf = child; 2014 ngx_http_fastcgi_loc_conf_t *conf = child;
1973 2015
1974 u_char *p; 2016 u_char *p;
1975 size_t size; 2017 size_t size;
1976 uintptr_t *code; 2018 uintptr_t *code;
1977 ngx_str_t *h;
1978 ngx_uint_t i; 2019 ngx_uint_t i;
2020 ngx_array_t headers_names;
1979 ngx_keyval_t *src; 2021 ngx_keyval_t *src;
2022 ngx_hash_key_t *hk;
1980 ngx_hash_init_t hash; 2023 ngx_hash_init_t hash;
2024 ngx_http_core_loc_conf_t *clcf;
1981 ngx_http_script_compile_t sc; 2025 ngx_http_script_compile_t sc;
1982 ngx_http_script_copy_code_t *copy; 2026 ngx_http_script_copy_code_t *copy;
1983 2027
1984 if (conf->upstream.store != 0) { 2028 if (conf->upstream.store != 0) {
1985 ngx_conf_merge_value(conf->upstream.store, 2029 ngx_conf_merge_value(conf->upstream.store,
2167 conf->upstream.cache_methods = prev->upstream.cache_methods; 2211 conf->upstream.cache_methods = prev->upstream.cache_methods;
2168 } 2212 }
2169 2213
2170 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; 2214 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
2171 2215
2216 ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
2217 prev->upstream.cache_bypass, NULL);
2218
2219 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
2220 prev->upstream.no_cache, NULL);
2221
2222 if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
2223 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
2224 "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, "
2225 "now it should be used together with \"fastcgi_cache_bypass\"");
2226 }
2227
2172 ngx_conf_merge_ptr_value(conf->upstream.cache_valid, 2228 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
2173 prev->upstream.cache_valid, NULL); 2229 prev->upstream.cache_valid, NULL);
2174 2230
2175 if (conf->cache_key.value.data == NULL) { 2231 if (conf->cache_key.value.data == NULL) {
2176 conf->cache_key = prev->cache_key; 2232 conf->cache_key = prev->cache_key;
2193 2249
2194 hash.max_size = 512; 2250 hash.max_size = 512;
2195 hash.bucket_size = ngx_align(64, ngx_cacheline_size); 2251 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
2196 hash.name = "fastcgi_hide_headers_hash"; 2252 hash.name = "fastcgi_hide_headers_hash";
2197 2253
2198 #if (NGX_HTTP_CACHE)
2199
2200 h = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
2201 ngx_http_fastcgi_hide_headers;
2202 #else
2203
2204 h = ngx_http_fastcgi_hide_headers;
2205
2206 #endif
2207
2208 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, 2254 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
2209 &prev->upstream, h, &hash) 2255 &prev->upstream, ngx_http_fastcgi_hide_headers, &hash)
2210 != NGX_OK) 2256 != NGX_OK)
2211 { 2257 {
2212 return NGX_CONF_ERROR; 2258 return NGX_CONF_ERROR;
2213 } 2259 }
2214 2260
2217 } 2263 }
2218 2264
2219 if (conf->fastcgi_lengths == NULL) { 2265 if (conf->fastcgi_lengths == NULL) {
2220 conf->fastcgi_lengths = prev->fastcgi_lengths; 2266 conf->fastcgi_lengths = prev->fastcgi_lengths;
2221 conf->fastcgi_values = prev->fastcgi_values; 2267 conf->fastcgi_values = prev->fastcgi_values;
2268 }
2269
2270 if (conf->upstream.upstream || conf->fastcgi_lengths) {
2271 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2272 if (clcf->handler == NULL && clcf->lmt_excpt) {
2273 clcf->handler = ngx_http_fastcgi_handler;
2274 }
2222 } 2275 }
2223 2276
2224 #if (NGX_PCRE) 2277 #if (NGX_PCRE)
2225 if (conf->split_regex == NULL) { 2278 if (conf->split_regex == NULL) {
2226 conf->split_regex = prev->split_regex; 2279 conf->split_regex = prev->split_regex;
2231 if (conf->params_source == NULL) { 2284 if (conf->params_source == NULL) {
2232 conf->flushes = prev->flushes; 2285 conf->flushes = prev->flushes;
2233 conf->params_len = prev->params_len; 2286 conf->params_len = prev->params_len;
2234 conf->params = prev->params; 2287 conf->params = prev->params;
2235 conf->params_source = prev->params_source; 2288 conf->params_source = prev->params_source;
2289 conf->headers_hash = prev->headers_hash;
2290
2291 #if (NGX_HTTP_CACHE)
2292
2293 if (conf->params_source == NULL) {
2294
2295 if ((conf->upstream.cache == NULL)
2296 == (prev->upstream.cache == NULL))
2297 {
2298 return NGX_CONF_OK;
2299 }
2300
2301 /* 6 is a number of ngx_http_fastcgi_cache_headers entries */
2302 conf->params_source = ngx_array_create(cf->pool, 6,
2303 sizeof(ngx_keyval_t));
2304 if (conf->params_source == NULL) {
2305 return NGX_CONF_ERROR;
2306 }
2307 }
2308 #else
2236 2309
2237 if (conf->params_source == NULL) { 2310 if (conf->params_source == NULL) {
2238 return NGX_CONF_OK; 2311 return NGX_CONF_OK;
2239 } 2312 }
2313
2314 #endif
2240 } 2315 }
2241 2316
2242 conf->params_len = ngx_array_create(cf->pool, 64, 1); 2317 conf->params_len = ngx_array_create(cf->pool, 64, 1);
2243 if (conf->params_len == NULL) { 2318 if (conf->params_len == NULL) {
2244 return NGX_CONF_ERROR; 2319 return NGX_CONF_ERROR;
2247 conf->params = ngx_array_create(cf->pool, 512, 1); 2322 conf->params = ngx_array_create(cf->pool, 512, 1);
2248 if (conf->params == NULL) { 2323 if (conf->params == NULL) {
2249 return NGX_CONF_ERROR; 2324 return NGX_CONF_ERROR;
2250 } 2325 }
2251 2326
2327 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
2328 != NGX_OK)
2329 {
2330 return NGX_CONF_ERROR;
2331 }
2332
2252 src = conf->params_source->elts; 2333 src = conf->params_source->elts;
2334
2335 #if (NGX_HTTP_CACHE)
2336
2337 if (conf->upstream.cache) {
2338 ngx_keyval_t *h, *s;
2339
2340 for (h = ngx_http_fastcgi_cache_headers; h->key.len; h++) {
2341
2342 for (i = 0; i < conf->params_source->nelts; i++) {
2343 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
2344 goto next;
2345 }
2346 }
2347
2348 s = ngx_array_push(conf->params_source);
2349 if (s == NULL) {
2350 return NGX_CONF_ERROR;
2351 }
2352
2353 *s = *h;
2354
2355 src = conf->params_source->elts;
2356
2357 next:
2358
2359 h++;
2360 }
2361 }
2362
2363 #endif
2364
2253 for (i = 0; i < conf->params_source->nelts; i++) { 2365 for (i = 0; i < conf->params_source->nelts; i++) {
2254 2366
2255 if (ngx_http_script_variables_count(&src[i].value) == 0) { 2367 if (src[i].key.len > sizeof("HTTP_") - 1
2256 copy = ngx_array_push_n(conf->params_len, 2368 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
2257 sizeof(ngx_http_script_copy_code_t)); 2369 {
2258 if (copy == NULL) { 2370 hk = ngx_array_push(&headers_names);
2371 if (hk == NULL) {
2259 return NGX_CONF_ERROR; 2372 return NGX_CONF_ERROR;
2260 } 2373 }
2261 2374
2262 copy->code = (ngx_http_script_code_pt) 2375 hk->key.len = src[i].key.len - 5;
2263 ngx_http_script_copy_len_code; 2376 hk->key.data = src[i].key.data + 5;
2264 copy->len = src[i].key.len; 2377 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
2265 2378 hk->value = (void *) 1;
2266 2379
2267 copy = ngx_array_push_n(conf->params_len, 2380 if (src[i].value.len == 0) {
2268 sizeof(ngx_http_script_copy_code_t)); 2381 continue;
2269 if (copy == NULL) { 2382 }
2270 return NGX_CONF_ERROR; 2383 }
2271 } 2384
2272 2385 copy = ngx_array_push_n(conf->params_len,
2273 copy->code = (ngx_http_script_code_pt) 2386 sizeof(ngx_http_script_copy_code_t));
2274 ngx_http_script_copy_len_code; 2387 if (copy == NULL) {
2275 copy->len = src[i].value.len; 2388 return NGX_CONF_ERROR;
2276 2389 }
2277 2390
2278 size = (sizeof(ngx_http_script_copy_code_t) 2391 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
2279 + src[i].key.len + src[i].value.len 2392 copy->len = src[i].key.len;
2280 + sizeof(uintptr_t) - 1) 2393
2281 & ~(sizeof(uintptr_t) - 1); 2394
2282 2395 size = (sizeof(ngx_http_script_copy_code_t)
2283 copy = ngx_array_push_n(conf->params, size); 2396 + src[i].key.len + sizeof(uintptr_t) - 1)
2284 if (copy == NULL) { 2397 & ~(sizeof(uintptr_t) - 1);
2285 return NGX_CONF_ERROR; 2398
2286 } 2399 copy = ngx_array_push_n(conf->params, size);
2287 2400 if (copy == NULL) {
2288 copy->code = ngx_http_script_copy_code; 2401 return NGX_CONF_ERROR;
2289 copy->len = src[i].key.len + src[i].value.len; 2402 }
2290 2403
2291 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); 2404 copy->code = ngx_http_script_copy_code;
2292 2405 copy->len = src[i].key.len;
2293 p = ngx_cpymem(p, src[i].key.data, src[i].key.len); 2406
2294 ngx_memcpy(p, src[i].value.data, src[i].value.len); 2407 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2295 2408 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2296 } else { 2409
2297 copy = ngx_array_push_n(conf->params_len, 2410
2298 sizeof(ngx_http_script_copy_code_t)); 2411 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2299 if (copy == NULL) { 2412
2300 return NGX_CONF_ERROR; 2413 sc.cf = cf;
2301 } 2414 sc.source = &src[i].value;
2302 2415 sc.flushes = &conf->flushes;
2303 copy->code = (ngx_http_script_code_pt) 2416 sc.lengths = &conf->params_len;
2304 ngx_http_script_copy_len_code; 2417 sc.values = &conf->params;
2305 copy->len = src[i].key.len; 2418
2306 2419 if (ngx_http_script_compile(&sc) != NGX_OK) {
2307 2420 return NGX_CONF_ERROR;
2308 size = (sizeof(ngx_http_script_copy_code_t)
2309 + src[i].key.len + sizeof(uintptr_t) - 1)
2310 & ~(sizeof(uintptr_t) - 1);
2311
2312 copy = ngx_array_push_n(conf->params, size);
2313 if (copy == NULL) {
2314 return NGX_CONF_ERROR;
2315 }
2316
2317 copy->code = ngx_http_script_copy_code;
2318 copy->len = src[i].key.len;
2319
2320 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2321 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2322
2323
2324 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2325
2326 sc.cf = cf;
2327 sc.source = &src[i].value;
2328 sc.flushes = &conf->flushes;
2329 sc.lengths = &conf->params_len;
2330 sc.values = &conf->params;
2331
2332 if (ngx_http_script_compile(&sc) != NGX_OK) {
2333 return NGX_CONF_ERROR;
2334 }
2335 } 2421 }
2336 2422
2337 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); 2423 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
2338 if (code == NULL) { 2424 if (code == NULL) {
2339 return NGX_CONF_ERROR; 2425 return NGX_CONF_ERROR;
2354 if (code == NULL) { 2440 if (code == NULL) {
2355 return NGX_CONF_ERROR; 2441 return NGX_CONF_ERROR;
2356 } 2442 }
2357 2443
2358 *code = (uintptr_t) NULL; 2444 *code = (uintptr_t) NULL;
2445
2446
2447 conf->header_params = headers_names.nelts;
2448
2449 hash.hash = &conf->headers_hash;
2450 hash.key = ngx_hash_key_lc;
2451 hash.max_size = 512;
2452 hash.bucket_size = 64;
2453 hash.name = "fastcgi_params_hash";
2454 hash.pool = cf->pool;
2455 hash.temp_pool = NULL;
2456
2457 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
2458 {
2459 return NGX_CONF_ERROR;
2460 }
2359 2461
2360 return NGX_CONF_OK; 2462 return NGX_CONF_OK;
2361 } 2463 }
2362 2464
2363 2465
2458 2560
2459 n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3); 2561 n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
2460 2562
2461 if (n >= 0) { /* match */ 2563 if (n >= 0) { /* match */
2462 f->script_name.len = captures[3] - captures[2]; 2564 f->script_name.len = captures[3] - captures[2];
2463 f->script_name.data = r->uri.data; 2565 f->script_name.data = r->uri.data + captures[2];
2464 2566
2465 f->path_info.len = captures[5] - captures[4]; 2567 f->path_info.len = captures[5] - captures[4];
2466 f->path_info.data = r->uri.data + f->script_name.len; 2568 f->path_info.data = r->uri.data + captures[4];
2467 2569
2468 return f; 2570 return f;
2469 } 2571 }
2470 2572
2471 if (n == NGX_REGEX_NO_MATCHED) { 2573 if (n == NGX_REGEX_NO_MATCHED) {
2753 2855
2754 #endif 2856 #endif
2755 2857
2756 return NGX_CONF_OK; 2858 return NGX_CONF_OK;
2757 } 2859 }
2758
2759
2760 static char *
2761 ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
2762 ngx_command_t *cmd, void *conf)
2763 {
2764 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2765 "\"fastcgi_upstream_max_fails\" is not supported, "
2766 "use the \"max_fails\" parameter of the \"server\" directive ",
2767 "inside the \"upstream\" block");
2768
2769 return NGX_CONF_ERROR;
2770 }
2771
2772
2773 static char *
2774 ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
2775 ngx_command_t *cmd, void *conf)
2776 {
2777 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2778 "\"fastcgi_upstream_fail_timeout\" is not supported, "
2779 "use the \"fail_timeout\" parameter of the \"server\" directive ",
2780 "inside the \"upstream\" block");
2781
2782 return NGX_CONF_ERROR;
2783 }