comparison src/http/modules/ngx_http_fastcgi_module.c @ 665:0b460e61bdcd default tip

Merge with nginx 1.0.0.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:22:17 +0400
parents b9763778e212
children
comparison
equal deleted inserted replaced
572:06419a2298a9 665:0b460e61bdcd
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
60 u_char *last; 63 u_char *last;
61 ngx_uint_t type; 64 ngx_uint_t type;
62 size_t length; 65 size_t length;
63 size_t padding; 66 size_t padding;
64 67
65 ngx_uint_t fastcgi_stdout; /* unsigned :1 */ 68 unsigned fastcgi_stdout:1;
69 unsigned large_stderr:1;
66 70
67 ngx_array_t *split_parts; 71 ngx_array_t *split_parts;
68 72
69 ngx_str_t script_name; 73 ngx_str_t script_name;
70 ngx_str_t path_info; 74 ngx_str_t path_info;
159 #endif 163 #endif
160 164
161 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,
162 void *data); 166 void *data);
163 167
164 static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
165 ngx_command_t *cmd, void *conf);
166 static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
167 ngx_command_t *cmd, void *conf);
168
169 168
170 static ngx_conf_post_t ngx_http_fastcgi_lowat_post = 169 static ngx_conf_post_t ngx_http_fastcgi_lowat_post =
171 { ngx_http_fastcgi_lowat_check }; 170 { ngx_http_fastcgi_lowat_check };
172 171
173 172
182 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, 181 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
183 { ngx_null_string, 0 } 182 { ngx_null_string, 0 }
184 }; 183 };
185 184
186 185
187 static ngx_conf_bitmask_t ngx_http_fastcgi_ignore_headers_masks[] = {
188 { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
189 { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
190 { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
191 { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
192 { ngx_null_string, 0 }
193 };
194
195
196 ngx_module_t ngx_http_fastcgi_module; 186 ngx_module_t ngx_http_fastcgi_module;
197 187
198 188
199 static ngx_command_t ngx_http_fastcgi_commands[] = { 189 static ngx_command_t ngx_http_fastcgi_commands[] = {
200 190
238 ngx_conf_set_flag_slot, 228 ngx_conf_set_flag_slot,
239 NGX_HTTP_LOC_CONF_OFFSET, 229 NGX_HTTP_LOC_CONF_OFFSET,
240 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort), 230 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
241 NULL }, 231 NULL },
242 232
233 { ngx_string("fastcgi_bind"),
234 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
235 ngx_http_upstream_bind_set_slot,
236 NGX_HTTP_LOC_CONF_OFFSET,
237 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
238 NULL },
239
243 { ngx_string("fastcgi_connect_timeout"), 240 { ngx_string("fastcgi_connect_timeout"),
244 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 241 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
245 ngx_conf_set_msec_slot, 242 ngx_conf_set_msec_slot,
246 NGX_HTTP_LOC_CONF_OFFSET, 243 NGX_HTTP_LOC_CONF_OFFSET,
247 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout), 244 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout),
311 NULL }, 308 NULL },
312 309
313 #if (NGX_HTTP_CACHE) 310 #if (NGX_HTTP_CACHE)
314 311
315 { ngx_string("fastcgi_cache"), 312 { ngx_string("fastcgi_cache"),
316 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,
317 ngx_http_fastcgi_cache, 314 ngx_http_fastcgi_cache,
318 NGX_HTTP_LOC_CONF_OFFSET, 315 NGX_HTTP_LOC_CONF_OFFSET,
319 0, 316 0,
320 NULL }, 317 NULL },
321 318
322 { ngx_string("fastcgi_cache_key"), 319 { ngx_string("fastcgi_cache_key"),
323 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,
324 ngx_http_fastcgi_cache_key, 321 ngx_http_fastcgi_cache_key,
325 NGX_HTTP_LOC_CONF_OFFSET, 322 NGX_HTTP_LOC_CONF_OFFSET,
326 0, 323 0,
327 NULL }, 324 NULL },
328 325
331 ngx_http_file_cache_set_slot, 328 ngx_http_file_cache_set_slot,
332 0, 329 0,
333 0, 330 0,
334 &ngx_http_fastcgi_module }, 331 &ngx_http_fastcgi_module },
335 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
336 { ngx_string("fastcgi_cache_valid"), 347 { ngx_string("fastcgi_cache_valid"),
337 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,
338 ngx_http_file_cache_valid_set_slot, 349 ngx_http_file_cache_valid_set_slot,
339 NGX_HTTP_LOC_CONF_OFFSET, 350 NGX_HTTP_LOC_CONF_OFFSET,
340 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid), 351 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid),
389 ngx_conf_set_bitmask_slot, 400 ngx_conf_set_bitmask_slot,
390 NGX_HTTP_LOC_CONF_OFFSET, 401 NGX_HTTP_LOC_CONF_OFFSET,
391 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream), 402 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
392 &ngx_http_fastcgi_next_upstream_masks }, 403 &ngx_http_fastcgi_next_upstream_masks },
393 404
394 { ngx_string("fastcgi_upstream_max_fails"),
395 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
396 ngx_http_fastcgi_upstream_max_fails_unsupported,
397 0,
398 0,
399 NULL },
400
401 { ngx_string("fastcgi_upstream_fail_timeout"),
402 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
403 ngx_http_fastcgi_upstream_fail_timeout_unsupported,
404 0,
405 0,
406 NULL },
407
408 { ngx_string("fastcgi_param"), 405 { ngx_string("fastcgi_param"),
409 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,
410 ngx_conf_set_keyval_slot, 407 ngx_conf_set_keyval_slot,
411 NGX_HTTP_LOC_CONF_OFFSET, 408 NGX_HTTP_LOC_CONF_OFFSET,
412 offsetof(ngx_http_fastcgi_loc_conf_t, params_source), 409 offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
413 NULL }, 410 NULL },
414 411
415 { ngx_string("fastcgi_pass_header"), 412 { ngx_string("fastcgi_pass_header"),
416 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,
417 ngx_conf_set_str_array_slot, 414 ngx_conf_set_str_array_slot,
418 NGX_HTTP_LOC_CONF_OFFSET, 415 NGX_HTTP_LOC_CONF_OFFSET,
419 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers), 416 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
420 NULL }, 417 NULL },
421 418
422 { ngx_string("fastcgi_hide_header"), 419 { ngx_string("fastcgi_hide_header"),
423 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,
424 ngx_conf_set_str_array_slot, 421 ngx_conf_set_str_array_slot,
425 NGX_HTTP_LOC_CONF_OFFSET, 422 NGX_HTTP_LOC_CONF_OFFSET,
426 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers), 423 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
427 NULL }, 424 NULL },
428 425
429 { ngx_string("fastcgi_ignore_headers"), 426 { ngx_string("fastcgi_ignore_headers"),
430 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,
431 ngx_conf_set_bitmask_slot, 428 ngx_conf_set_bitmask_slot,
432 NGX_HTTP_LOC_CONF_OFFSET, 429 NGX_HTTP_LOC_CONF_OFFSET,
433 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers), 430 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
434 &ngx_http_fastcgi_ignore_headers_masks }, 431 &ngx_http_upstream_ignore_headers_masks },
435 432
436 { ngx_string("fastcgi_catch_stderr"), 433 { ngx_string("fastcgi_catch_stderr"),
437 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,
438 ngx_conf_set_str_array_slot, 435 ngx_conf_set_str_array_slot,
439 NGX_HTTP_LOC_CONF_OFFSET, 436 NGX_HTTP_LOC_CONF_OFFSET,
521 ngx_string("X-Accel-Charset"), 518 ngx_string("X-Accel-Charset"),
522 ngx_null_string 519 ngx_null_string
523 }; 520 };
524 521
525 522
523 #if (NGX_HTTP_CACHE)
524
525 static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
526 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
527 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
528 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
529 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
530 { ngx_string("HTTP_RANGE"), ngx_string("") },
531 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
532 { ngx_null_string, ngx_null_string }
533 };
534
535 #endif
536
537
526 static ngx_path_init_t ngx_http_fastcgi_temp_path = { 538 static ngx_path_init_t ngx_http_fastcgi_temp_path = {
527 ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 } 539 ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
528 }; 540 };
529 541
530 542
562 } 574 }
563 } 575 }
564 576
565 u = r->upstream; 577 u = r->upstream;
566 578
567 u->schema.len = sizeof("fastcgi://") - 1; 579 ngx_str_set(&u->schema, "fastcgi://");
568 u->schema.data = (u_char *) "fastcgi://";
569
570 u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module; 580 u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
571 581
572 u->conf = &flcf->upstream; 582 u->conf = &flcf->upstream;
573 583
574 #if (NGX_HTTP_CACHE) 584 #if (NGX_HTTP_CACHE)
601 611
602 612
603 static ngx_int_t 613 static ngx_int_t
604 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)
605 { 615 {
606 ngx_url_t u; 616 ngx_url_t url;
607 617 ngx_http_upstream_t *u;
608 ngx_memzero(&u, sizeof(ngx_url_t)); 618
609 619 ngx_memzero(&url, sizeof(ngx_url_t));
610 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,
611 flcf->fastcgi_values->elts) 622 flcf->fastcgi_values->elts)
612 == NULL) 623 == NULL)
613 { 624 {
614 return NGX_ERROR; 625 return NGX_ERROR;
615 } 626 }
616 627
617 u.no_resolve = 1; 628 url.no_resolve = 1;
618 629
619 if (ngx_parse_url(r->pool, &u) != NGX_OK) { 630 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
620 if (u.err) { 631 if (url.err) {
621 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 632 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
622 "%s in upstream \"%V\"", u.err, &u.url); 633 "%s in upstream \"%V\"", url.err, &url.url);
623 } 634 }
624 635
625 return NGX_ERROR; 636 return NGX_ERROR;
626 } 637 }
627 638
628 if (u.no_port) { 639 u = r->upstream;
629 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 640
630 "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) {
631 return NGX_ERROR; 643 return NGX_ERROR;
632 } 644 }
633 645
634 r->upstream->resolved = ngx_pcalloc(r->pool, 646 if (url.addrs && url.addrs[0].sockaddr) {
635 sizeof(ngx_http_upstream_resolved_t)); 647 u->resolved->sockaddr = url.addrs[0].sockaddr;
636 if (r->upstream->resolved == NULL) { 648 u->resolved->socklen = url.addrs[0].socklen;
637 return NGX_ERROR; 649 u->resolved->naddrs = 1;
638 } 650 u->resolved->host = url.addrs[0].name;
639
640 if (u.addrs && u.addrs[0].sockaddr) {
641 r->upstream->resolved->sockaddr = u.addrs[0].sockaddr;
642 r->upstream->resolved->socklen = u.addrs[0].socklen;
643 r->upstream->resolved->naddrs = 1;
644 r->upstream->resolved->host = u.addrs[0].name;
645 651
646 } else { 652 } else {
647 r->upstream->resolved->host = u.host; 653 u->resolved->host = url.host;
648 r->upstream->resolved->port = u.port; 654 u->resolved->port = url.port;
655 u->resolved->no_port = url.no_port;
649 } 656 }
650 657
651 return NGX_OK; 658 return NGX_OK;
652 } 659 }
653 660
679 686
680 static ngx_int_t 687 static ngx_int_t
681 ngx_http_fastcgi_create_request(ngx_http_request_t *r) 688 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
682 { 689 {
683 off_t file_pos; 690 off_t file_pos;
684 u_char ch, *pos; 691 u_char ch, *pos, *lowcase_key;
685 size_t size, len, key_len, val_len, padding; 692 size_t size, len, key_len, val_len, padding,
686 ngx_uint_t i, n, next; 693 allocated;
694 ngx_uint_t i, n, next, hash, header_params;
687 ngx_buf_t *b; 695 ngx_buf_t *b;
688 ngx_chain_t *cl, *body; 696 ngx_chain_t *cl, *body;
689 ngx_list_part_t *part; 697 ngx_list_part_t *part;
690 ngx_table_elt_t *header; 698 ngx_table_elt_t *header, **ignored;
691 ngx_http_script_code_pt code; 699 ngx_http_script_code_pt code;
692 ngx_http_script_engine_t e, le; 700 ngx_http_script_engine_t e, le;
693 ngx_http_fastcgi_header_t *h; 701 ngx_http_fastcgi_header_t *h;
694 ngx_http_fastcgi_loc_conf_t *flcf; 702 ngx_http_fastcgi_loc_conf_t *flcf;
695 ngx_http_script_len_code_pt lcode; 703 ngx_http_script_len_code_pt lcode;
696 704
697 len = 0; 705 len = 0;
706 header_params = 0;
707 ignored = NULL;
698 708
699 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);
700 710
701 if (flcf->params_len) { 711 if (flcf->params_len) {
702 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); 712 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
720 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; 730 len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
721 } 731 }
722 } 732 }
723 733
724 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 }
725 745
726 part = &r->headers_in.headers.part; 746 part = &r->headers_in.headers.part;
727 header = part->elts; 747 header = part->elts;
728 748
729 for (i = 0; /* void */; i++) { 749 for (i = 0; /* void */; i++) {
736 part = part->next; 756 part = part->next;
737 header = part->elts; 757 header = part->elts;
738 i = 0; 758 i = 0;
739 } 759 }
740 760
741 len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1) 761 if (flcf->header_params) {
742 + ((header[i].value.len > 127) ? 4 : 1) 762 if (allocated < header[i].key.len) {
743 + 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;
744 } 799 }
745 } 800 }
746 801
747 802
748 if (len > 65535) { 803 if (len > 65535) {
858 part = part->next; 913 part = part->next;
859 header = part->elts; 914 header = part->elts;
860 i = 0; 915 i = 0;
861 } 916 }
862 917
863 len = sizeof("HTTP_") - 1 + header[i].key.len; 918 for (n = 0; n < header_params; n++) {
864 if (len > 127) { 919 if (&header[i] == ignored[n]) {
865 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 920 goto next;
866 *b->last++ = (u_char) ((len >> 16) & 0xff); 921 }
867 *b->last++ = (u_char) ((len >> 8) & 0xff); 922 }
868 *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);
869 930
870 } else { 931 } else {
871 *b->last++ = (u_char) len; 932 *b->last++ = (u_char) key_len;
872 } 933 }
873 934
874 len = header[i].value.len; 935 val_len = header[i].value.len;
875 if (len > 127) { 936 if (val_len > 127) {
876 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); 937 *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
877 *b->last++ = (u_char) ((len >> 16) & 0xff); 938 *b->last++ = (u_char) ((val_len >> 16) & 0xff);
878 *b->last++ = (u_char) ((len >> 8) & 0xff); 939 *b->last++ = (u_char) ((val_len >> 8) & 0xff);
879 *b->last++ = (u_char) (len & 0xff); 940 *b->last++ = (u_char) (val_len & 0xff);
880 941
881 } else { 942 } else {
882 *b->last++ = (u_char) len; 943 *b->last++ = (u_char) val_len;
883 } 944 }
884 945
885 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); 946 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
886 947
887 for (n = 0; n < header[i].key.len; n++) { 948 for (n = 0; n < header[i].key.len; n++) {
895 } 956 }
896 957
897 *b->last++ = ch; 958 *b->last++ = ch;
898 } 959 }
899 960
900 b->last = ngx_copy(b->last, header[i].value.data, 961 b->last = ngx_copy(b->last, header[i].value.data, val_len);
901 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;
902 } 970 }
903 } 971 }
904 972
905 973
906 if (padding) { 974 if (padding) {
1055 return NGX_OK; 1123 return NGX_OK;
1056 } 1124 }
1057 1125
1058 f->state = ngx_http_fastcgi_st_version; 1126 f->state = ngx_http_fastcgi_st_version;
1059 f->fastcgi_stdout = 0; 1127 f->fastcgi_stdout = 0;
1128 f->large_stderr = 0;
1060 1129
1061 return NGX_OK; 1130 return NGX_OK;
1062 } 1131 }
1063 1132
1064 1133
1197 /* 1266 /*
1198 * the special handling the large number 1267 * the special handling the large number
1199 * of the PHP warnings to not allocate memory 1268 * of the PHP warnings to not allocate memory
1200 */ 1269 */
1201 1270
1271 #if (NGX_HTTP_CACHE)
1272 if (r->cache) {
1273 u->buffer.pos = u->buffer.start
1274 + r->cache->header_start;
1275 } else {
1276 u->buffer.pos = u->buffer.start;
1277 }
1278 #else
1202 u->buffer.pos = u->buffer.start; 1279 u->buffer.pos = u->buffer.start;
1203 u->buffer.last = u->buffer.start; 1280 #endif
1281 u->buffer.last = u->buffer.pos;
1282 f->large_stderr = 1;
1204 } 1283 }
1205 1284
1206 return NGX_AGAIN; 1285 return NGX_AGAIN;
1207 } 1286 }
1208 1287
1213 continue; 1292 continue;
1214 } 1293 }
1215 1294
1216 1295
1217 /* f->type == NGX_HTTP_FASTCGI_STDOUT */ 1296 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1297
1298 #if (NGX_HTTP_CACHE)
1299
1300 if (f->large_stderr && r->cache) {
1301 u_char *start;
1302 ssize_t len;
1303 ngx_http_fastcgi_header_t *fh;
1304
1305 start = u->buffer.start + r->cache->header_start;
1306
1307 len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
1308
1309 /*
1310 * A tail of large stderr output before HTTP header is placed
1311 * in a cache file without a FastCGI record header.
1312 * To workaround it we put a dummy FastCGI record header at the
1313 * start of the stderr output or update r->cache_header_start,
1314 * if there is no enough place for the record header.
1315 */
1316
1317 if (len >= 0) {
1318 fh = (ngx_http_fastcgi_header_t *) start;
1319 fh->version = 1;
1320 fh->type = NGX_HTTP_FASTCGI_STDERR;
1321 fh->request_id_hi = 0;
1322 fh->request_id_lo = 1;
1323 fh->content_length_hi = (u_char) ((len >> 8) & 0xff);
1324 fh->content_length_lo = (u_char) (len & 0xff);
1325 fh->padding_length = 0;
1326 fh->reserved = 0;
1327
1328 } else {
1329 r->cache->header_start += u->buffer.pos - start
1330 - sizeof(ngx_http_fastcgi_header_t);
1331 }
1332
1333 f->large_stderr = 0;
1334 }
1335
1336 #endif
1218 1337
1219 f->fastcgi_stdout = 1; 1338 f->fastcgi_stdout = 1;
1220 1339
1221 start = u->buffer.pos; 1340 start = u->buffer.pos;
1222 1341
1372 u->headers_in.status_n = status; 1491 u->headers_in.status_n = status;
1373 u->headers_in.status_line = *status_line; 1492 u->headers_in.status_line = *status_line;
1374 1493
1375 } else if (u->headers_in.location) { 1494 } else if (u->headers_in.location) {
1376 u->headers_in.status_n = 302; 1495 u->headers_in.status_n = 302;
1377 u->headers_in.status_line.len = 1496 ngx_str_set(&u->headers_in.status_line,
1378 sizeof("302 Moved Temporarily") - 1; 1497 "302 Moved Temporarily");
1379 u->headers_in.status_line.data =
1380 (u_char *) "302 Moved Temporarily";
1381 1498
1382 } else { 1499 } else {
1383 u->headers_in.status_n = 200; 1500 u->headers_in.status_n = 200;
1384 u->headers_in.status_line.len = sizeof("200 OK") - 1; 1501 ngx_str_set(&u->headers_in.status_line, "200 OK");
1385 u->headers_in.status_line.data = (u_char *) "200 OK";
1386 } 1502 }
1387 1503
1388 if (u->state) { 1504 if (u->state) {
1389 u->state->status = u->headers_in.status_n; 1505 u->state->status = u->headers_in.status_n;
1390 } 1506 }
1845 * conf->upstream.uri = { 0, NULL }; 1961 * conf->upstream.uri = { 0, NULL };
1846 * conf->upstream.location = NULL; 1962 * conf->upstream.location = NULL;
1847 * conf->upstream.store_lengths = NULL; 1963 * conf->upstream.store_lengths = NULL;
1848 * conf->upstream.store_values = NULL; 1964 * conf->upstream.store_values = NULL;
1849 * 1965 *
1850 * conf->index.len = 0; 1966 * conf->index.len = { 0, NULL };
1851 * conf->index.data = NULL;
1852 */ 1967 */
1853 1968
1854 conf->upstream.store = NGX_CONF_UNSET; 1969 conf->upstream.store = NGX_CONF_UNSET;
1855 conf->upstream.store_access = NGX_CONF_UNSET_UINT; 1970 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
1856 conf->upstream.buffering = NGX_CONF_UNSET; 1971 conf->upstream.buffering = NGX_CONF_UNSET;
1871 conf->upstream.pass_request_body = NGX_CONF_UNSET; 1986 conf->upstream.pass_request_body = NGX_CONF_UNSET;
1872 1987
1873 #if (NGX_HTTP_CACHE) 1988 #if (NGX_HTTP_CACHE)
1874 conf->upstream.cache = NGX_CONF_UNSET_PTR; 1989 conf->upstream.cache = NGX_CONF_UNSET_PTR;
1875 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;
1876 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; 1993 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1877 #endif 1994 #endif
1878 1995
1879 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; 1996 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
1880 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; 1997 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
1898 2015
1899 u_char *p; 2016 u_char *p;
1900 size_t size; 2017 size_t size;
1901 uintptr_t *code; 2018 uintptr_t *code;
1902 ngx_uint_t i; 2019 ngx_uint_t i;
2020 ngx_array_t headers_names;
1903 ngx_keyval_t *src; 2021 ngx_keyval_t *src;
2022 ngx_hash_key_t *hk;
1904 ngx_hash_init_t hash; 2023 ngx_hash_init_t hash;
2024 ngx_http_core_loc_conf_t *clcf;
1905 ngx_http_script_compile_t sc; 2025 ngx_http_script_compile_t sc;
1906 ngx_http_script_copy_code_t *copy; 2026 ngx_http_script_copy_code_t *copy;
1907 2027
1908 if (conf->upstream.store != 0) { 2028 if (conf->upstream.store != 0) {
1909 ngx_conf_merge_value(conf->upstream.store, 2029 ngx_conf_merge_value(conf->upstream.store,
2091 conf->upstream.cache_methods = prev->upstream.cache_methods; 2211 conf->upstream.cache_methods = prev->upstream.cache_methods;
2092 } 2212 }
2093 2213
2094 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; 2214 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
2095 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
2096 ngx_conf_merge_ptr_value(conf->upstream.cache_valid, 2228 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
2097 prev->upstream.cache_valid, NULL); 2229 prev->upstream.cache_valid, NULL);
2098 2230
2099 if (conf->cache_key.value.data == NULL) { 2231 if (conf->cache_key.value.data == NULL) {
2100 conf->cache_key = prev->cache_key; 2232 conf->cache_key = prev->cache_key;
2118 hash.max_size = 512; 2250 hash.max_size = 512;
2119 hash.bucket_size = ngx_align(64, ngx_cacheline_size); 2251 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
2120 hash.name = "fastcgi_hide_headers_hash"; 2252 hash.name = "fastcgi_hide_headers_hash";
2121 2253
2122 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, 2254 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
2123 &prev->upstream, 2255 &prev->upstream, ngx_http_fastcgi_hide_headers, &hash)
2124 ngx_http_fastcgi_hide_headers,
2125 &hash)
2126 != NGX_OK) 2256 != NGX_OK)
2127 { 2257 {
2128 return NGX_CONF_ERROR; 2258 return NGX_CONF_ERROR;
2129 } 2259 }
2130 2260
2133 } 2263 }
2134 2264
2135 if (conf->fastcgi_lengths == NULL) { 2265 if (conf->fastcgi_lengths == NULL) {
2136 conf->fastcgi_lengths = prev->fastcgi_lengths; 2266 conf->fastcgi_lengths = prev->fastcgi_lengths;
2137 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 }
2138 } 2275 }
2139 2276
2140 #if (NGX_PCRE) 2277 #if (NGX_PCRE)
2141 if (conf->split_regex == NULL) { 2278 if (conf->split_regex == NULL) {
2142 conf->split_regex = prev->split_regex; 2279 conf->split_regex = prev->split_regex;
2147 if (conf->params_source == NULL) { 2284 if (conf->params_source == NULL) {
2148 conf->flushes = prev->flushes; 2285 conf->flushes = prev->flushes;
2149 conf->params_len = prev->params_len; 2286 conf->params_len = prev->params_len;
2150 conf->params = prev->params; 2287 conf->params = prev->params;
2151 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
2152 2309
2153 if (conf->params_source == NULL) { 2310 if (conf->params_source == NULL) {
2154 return NGX_CONF_OK; 2311 return NGX_CONF_OK;
2155 } 2312 }
2313
2314 #endif
2156 } 2315 }
2157 2316
2158 conf->params_len = ngx_array_create(cf->pool, 64, 1); 2317 conf->params_len = ngx_array_create(cf->pool, 64, 1);
2159 if (conf->params_len == NULL) { 2318 if (conf->params_len == NULL) {
2160 return NGX_CONF_ERROR; 2319 return NGX_CONF_ERROR;
2163 conf->params = ngx_array_create(cf->pool, 512, 1); 2322 conf->params = ngx_array_create(cf->pool, 512, 1);
2164 if (conf->params == NULL) { 2323 if (conf->params == NULL) {
2165 return NGX_CONF_ERROR; 2324 return NGX_CONF_ERROR;
2166 } 2325 }
2167 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
2168 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
2169 for (i = 0; i < conf->params_source->nelts; i++) { 2365 for (i = 0; i < conf->params_source->nelts; i++) {
2170 2366
2171 if (ngx_http_script_variables_count(&src[i].value) == 0) { 2367 if (src[i].key.len > sizeof("HTTP_") - 1
2172 copy = ngx_array_push_n(conf->params_len, 2368 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
2173 sizeof(ngx_http_script_copy_code_t)); 2369 {
2174 if (copy == NULL) { 2370 hk = ngx_array_push(&headers_names);
2371 if (hk == NULL) {
2175 return NGX_CONF_ERROR; 2372 return NGX_CONF_ERROR;
2176 } 2373 }
2177 2374
2178 copy->code = (ngx_http_script_code_pt) 2375 hk->key.len = src[i].key.len - 5;
2179 ngx_http_script_copy_len_code; 2376 hk->key.data = src[i].key.data + 5;
2180 copy->len = src[i].key.len; 2377 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
2181 2378 hk->value = (void *) 1;
2182 2379
2183 copy = ngx_array_push_n(conf->params_len, 2380 if (src[i].value.len == 0) {
2184 sizeof(ngx_http_script_copy_code_t)); 2381 continue;
2185 if (copy == NULL) { 2382 }
2186 return NGX_CONF_ERROR; 2383 }
2187 } 2384
2188 2385 copy = ngx_array_push_n(conf->params_len,
2189 copy->code = (ngx_http_script_code_pt) 2386 sizeof(ngx_http_script_copy_code_t));
2190 ngx_http_script_copy_len_code; 2387 if (copy == NULL) {
2191 copy->len = src[i].value.len; 2388 return NGX_CONF_ERROR;
2192 2389 }
2193 2390
2194 size = (sizeof(ngx_http_script_copy_code_t) 2391 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
2195 + src[i].key.len + src[i].value.len 2392 copy->len = src[i].key.len;
2196 + sizeof(uintptr_t) - 1) 2393
2197 & ~(sizeof(uintptr_t) - 1); 2394
2198 2395 size = (sizeof(ngx_http_script_copy_code_t)
2199 copy = ngx_array_push_n(conf->params, size); 2396 + src[i].key.len + sizeof(uintptr_t) - 1)
2200 if (copy == NULL) { 2397 & ~(sizeof(uintptr_t) - 1);
2201 return NGX_CONF_ERROR; 2398
2202 } 2399 copy = ngx_array_push_n(conf->params, size);
2203 2400 if (copy == NULL) {
2204 copy->code = ngx_http_script_copy_code; 2401 return NGX_CONF_ERROR;
2205 copy->len = src[i].key.len + src[i].value.len; 2402 }
2206 2403
2207 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); 2404 copy->code = ngx_http_script_copy_code;
2208 2405 copy->len = src[i].key.len;
2209 p = ngx_cpymem(p, src[i].key.data, src[i].key.len); 2406
2210 ngx_memcpy(p, src[i].value.data, src[i].value.len); 2407 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2211 2408 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2212 } else { 2409
2213 copy = ngx_array_push_n(conf->params_len, 2410
2214 sizeof(ngx_http_script_copy_code_t)); 2411 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2215 if (copy == NULL) { 2412
2216 return NGX_CONF_ERROR; 2413 sc.cf = cf;
2217 } 2414 sc.source = &src[i].value;
2218 2415 sc.flushes = &conf->flushes;
2219 copy->code = (ngx_http_script_code_pt) 2416 sc.lengths = &conf->params_len;
2220 ngx_http_script_copy_len_code; 2417 sc.values = &conf->params;
2221 copy->len = src[i].key.len; 2418
2222 2419 if (ngx_http_script_compile(&sc) != NGX_OK) {
2223 2420 return NGX_CONF_ERROR;
2224 size = (sizeof(ngx_http_script_copy_code_t)
2225 + src[i].key.len + sizeof(uintptr_t) - 1)
2226 & ~(sizeof(uintptr_t) - 1);
2227
2228 copy = ngx_array_push_n(conf->params, size);
2229 if (copy == NULL) {
2230 return NGX_CONF_ERROR;
2231 }
2232
2233 copy->code = ngx_http_script_copy_code;
2234 copy->len = src[i].key.len;
2235
2236 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2237 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2238
2239
2240 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2241
2242 sc.cf = cf;
2243 sc.source = &src[i].value;
2244 sc.flushes = &conf->flushes;
2245 sc.lengths = &conf->params_len;
2246 sc.values = &conf->params;
2247
2248 if (ngx_http_script_compile(&sc) != NGX_OK) {
2249 return NGX_CONF_ERROR;
2250 }
2251 } 2421 }
2252 2422
2253 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); 2423 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
2254 if (code == NULL) { 2424 if (code == NULL) {
2255 return NGX_CONF_ERROR; 2425 return NGX_CONF_ERROR;
2270 if (code == NULL) { 2440 if (code == NULL) {
2271 return NGX_CONF_ERROR; 2441 return NGX_CONF_ERROR;
2272 } 2442 }
2273 2443
2274 *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 }
2275 2461
2276 return NGX_CONF_OK; 2462 return NGX_CONF_OK;
2277 } 2463 }
2278 2464
2279 2465
2372 return f; 2558 return f;
2373 } 2559 }
2374 2560
2375 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);
2376 2562
2563 if (n >= 0) { /* match */
2564 f->script_name.len = captures[3] - captures[2];
2565 f->script_name.data = r->uri.data + captures[2];
2566
2567 f->path_info.len = captures[5] - captures[4];
2568 f->path_info.data = r->uri.data + captures[4];
2569
2570 return f;
2571 }
2572
2377 if (n == NGX_REGEX_NO_MATCHED) { 2573 if (n == NGX_REGEX_NO_MATCHED) {
2378 f->script_name = r->uri; 2574 f->script_name = r->uri;
2379 return f; 2575 return f;
2380 } 2576 }
2381 2577
2382 if (n < 0) { 2578 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
2383 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, 2579 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
2384 ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", 2580 n, &r->uri, &flcf->split_name);
2385 n, &r->uri, &flcf->split_name); 2581 return NULL;
2386 return NULL;
2387 }
2388
2389 /* match */
2390
2391 f->script_name.len = captures[3] - captures[2];
2392 f->script_name.data = r->uri.data;
2393
2394 f->path_info.len = captures[5] - captures[4];
2395 f->path_info.data = r->uri.data + f->script_name.len;
2396
2397 return f;
2398 2582
2399 #else 2583 #else
2400 2584
2401 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); 2585 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
2402 2586
2483 ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 2667 ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2484 { 2668 {
2485 #if (NGX_PCRE) 2669 #if (NGX_PCRE)
2486 ngx_http_fastcgi_loc_conf_t *flcf = conf; 2670 ngx_http_fastcgi_loc_conf_t *flcf = conf;
2487 2671
2488 ngx_int_t n; 2672 ngx_str_t *value;
2489 ngx_str_t *value, err; 2673 ngx_regex_compile_t rc;
2490 u_char errstr[NGX_MAX_CONF_ERRSTR]; 2674 u_char errstr[NGX_MAX_CONF_ERRSTR];
2491 2675
2492 value = cf->args->elts; 2676 value = cf->args->elts;
2493 2677
2494 flcf->split_name = value[1]; 2678 flcf->split_name = value[1];
2495 2679
2496 err.len = NGX_MAX_CONF_ERRSTR; 2680 ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
2497 err.data = errstr; 2681
2498 2682 rc.pattern = value[1];
2499 flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); 2683 rc.pool = cf->pool;
2500 2684 rc.err.len = NGX_MAX_CONF_ERRSTR;
2501 if (flcf->split_regex == NULL) { 2685 rc.err.data = errstr;
2502 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); 2686
2687 if (ngx_regex_compile(&rc) != NGX_OK) {
2688 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
2503 return NGX_CONF_ERROR; 2689 return NGX_CONF_ERROR;
2504 } 2690 }
2505 2691
2506 n = ngx_regex_capture_count(flcf->split_regex); 2692 if (rc.captures != 2) {
2507
2508 if (n < 0) {
2509 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2510 ngx_regex_capture_count_n " failed for "
2511 "pattern \"%V\"", &value[1]);
2512 return NGX_CONF_ERROR;
2513 }
2514
2515 if (n != 2) {
2516 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2693 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2517 "pattern \"%V\" must have 2 captures", &value[1]); 2694 "pattern \"%V\" must have 2 captures", &value[1]);
2518 return NGX_CONF_ERROR; 2695 return NGX_CONF_ERROR;
2519 } 2696 }
2697
2698 flcf->split_regex = rc.regex;
2520 2699
2521 return NGX_CONF_OK; 2700 return NGX_CONF_OK;
2522 2701
2523 #else 2702 #else
2524 2703
2676 2855
2677 #endif 2856 #endif
2678 2857
2679 return NGX_CONF_OK; 2858 return NGX_CONF_OK;
2680 } 2859 }
2681
2682
2683 static char *
2684 ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
2685 ngx_command_t *cmd, void *conf)
2686 {
2687 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2688 "\"fastcgi_upstream_max_fails\" is not supported, "
2689 "use the \"max_fails\" parameter of the \"server\" directive ",
2690 "inside the \"upstream\" block");
2691
2692 return NGX_CONF_ERROR;
2693 }
2694
2695
2696 static char *
2697 ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
2698 ngx_command_t *cmd, void *conf)
2699 {
2700 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2701 "\"fastcgi_upstream_fail_timeout\" is not supported, "
2702 "use the \"fail_timeout\" parameter of the \"server\" directive ",
2703 "inside the \"upstream\" block");
2704
2705 return NGX_CONF_ERROR;
2706 }