comparison src/http/modules/ngx_http_proxy_module.c @ 126:df17fbafec8f NGINX_0_3_10

nginx 0.3.10 *) Change: the "valid_referers" directive and the "$invalid_referer" variable were moved to the new ngx_http_referer_module from the ngx_http_rewrite_module. *) Change: the "$apache_bytes_sent" variable name was changed to "$body_bytes_sent". *) Feature: the "$sent_http_..." variables. *) Feature: the "if" directive supports the "=" and "!=" operations. *) Feature: the "proxy_pass" directive supports the HTTPS protocol. *) Feature: the "proxy_set_body" directive. *) Feature: the "post_action" directive. *) Feature: the ngx_http_empty_gif_module. *) Feature: the "worker_cpu_affinity" directive for Linux. *) Bugfix: the "rewrite" directive did not unescape URI part in redirect, now it is unescaped except the %00-%25 and %7F-%FF characters. *) Bugfix: nginx could not be built by the icc 9.0 compiler. *) Bugfix: if the SSI was enabled for zero size static file, then the chunked response was encoded incorrectly.
author Igor Sysoev <http://sysoev.ru>
date Tue, 15 Nov 2005 00:00:00 +0300
parents d25a1d6034f1
children f1ad9023c312
comparison
equal deleted inserted replaced
125:97504de1f89e 126:df17fbafec8f
1 1
2 /* 2 /*
3 * Copyright (C) Igor Sysoev 3 * Copyright (C) Igor Sysoev
4 */ 4 */
5 5
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
36 ngx_http_upstream_conf_t upstream; 36 ngx_http_upstream_conf_t upstream;
37 37
38 ngx_peers_t *peers; 38 ngx_peers_t *peers;
39 39
40 ngx_array_t *flushes; 40 ngx_array_t *flushes;
41 ngx_array_t *body_set_len;
42 ngx_array_t *body_set;
41 ngx_array_t *headers_set_len; 43 ngx_array_t *headers_set_len;
42 ngx_array_t *headers_set; 44 ngx_array_t *headers_set;
43 ngx_hash_t *headers_set_hash; 45 ngx_hash_t *headers_set_hash;
44 46
45 ngx_array_t *headers_source; 47 ngx_array_t *headers_source;
46 ngx_array_t *headers_names; 48 ngx_array_t *headers_names;
47 49
48 ngx_array_t *redirects; 50 ngx_array_t *redirects;
51
52 ngx_str_t body_source;
49 53
50 ngx_str_t method; 54 ngx_str_t method;
51 ngx_str_t host_header; 55 ngx_str_t host_header;
52 ngx_str_t port_text; 56 ngx_str_t port_text;
53 57
58 typedef struct { 62 typedef struct {
59 ngx_uint_t status; 63 ngx_uint_t status;
60 ngx_uint_t status_count; 64 ngx_uint_t status_count;
61 u_char *status_start; 65 u_char *status_start;
62 u_char *status_end; 66 u_char *status_end;
67
68 size_t internal_body_length;
63 } ngx_http_proxy_ctx_t; 69 } ngx_http_proxy_ctx_t;
64 70
65 71
66 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 72 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
67 73
81 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r, 87 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
82 ngx_http_variable_value_t *v, uintptr_t data); 88 ngx_http_variable_value_t *v, uintptr_t data);
83 static ngx_int_t 89 static ngx_int_t
84 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, 90 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
85 ngx_http_variable_value_t *v, uintptr_t data); 91 ngx_http_variable_value_t *v, uintptr_t data);
92 static ngx_int_t
93 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
94 ngx_http_variable_value_t *v, uintptr_t data);
86 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, 95 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
87 ngx_table_elt_t *h, size_t prefix); 96 ngx_table_elt_t *h, size_t prefix);
88 97
89 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); 98 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
90 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); 99 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
160 { ngx_string("proxy_set_header"), 169 { ngx_string("proxy_set_header"),
161 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, 170 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
162 ngx_conf_set_table_elt_slot, 171 ngx_conf_set_table_elt_slot,
163 NGX_HTTP_LOC_CONF_OFFSET, 172 NGX_HTTP_LOC_CONF_OFFSET,
164 offsetof(ngx_http_proxy_loc_conf_t, headers_source), 173 offsetof(ngx_http_proxy_loc_conf_t, headers_source),
174 NULL },
175
176 { ngx_string("proxy_set_body"),
177 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
178 ngx_conf_set_str_slot,
179 NGX_HTTP_LOC_CONF_OFFSET,
180 offsetof(ngx_http_proxy_loc_conf_t, body_source),
165 NULL }, 181 NULL },
166 182
167 { ngx_string("proxy_method"), 183 { ngx_string("proxy_method"),
168 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 184 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
169 ngx_conf_set_str_slot, 185 ngx_conf_set_str_slot,
334 350
335 #if 0 351 #if 0
336 { ngx_string("proxy_add_via"), NULL, 0, 0, 0 }, 352 { ngx_string("proxy_add_via"), NULL, 0, 0, 0 },
337 #endif 353 #endif
338 354
355 { ngx_string("proxy_internal_body_length"),
356 ngx_http_proxy_internal_body_length_variable, 0, 0, 0 },
357
339 { ngx_null_string, NULL, 0, 0, 0 } 358 { ngx_null_string, NULL, 0, 0, 0 }
340 }; 359 };
341 360
342 361
343 static ngx_int_t 362 static ngx_int_t
344 ngx_http_proxy_handler(ngx_http_request_t *r) 363 ngx_http_proxy_handler(ngx_http_request_t *r)
345 { 364 {
346 ngx_int_t rc; 365 ngx_int_t rc;
347 ngx_http_upstream_t *u; 366 ngx_http_upstream_t *u;
348 ngx_http_proxy_loc_conf_t *plcf; 367 ngx_http_proxy_loc_conf_t *plcf;
349 368
350 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 369 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
351 370
352 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); 371 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
353 if (u == NULL) { 372 if (u == NULL) {
354 return NGX_HTTP_INTERNAL_SERVER_ERROR; 373 return NGX_HTTP_INTERNAL_SERVER_ERROR;
355 } 374 }
356 375
357 u->peer.log = r->connection->log; 376 u->peer.log = r->connection->log;
358 u->peer.log_error = NGX_ERROR_ERR; 377 u->peer.log_error = NGX_ERROR_ERR;
359 u->peer.peers = plcf->peers; 378 u->peer.peers = plcf->peers;
360 u->peer.tries = plcf->peers->number; 379 u->peer.tries = plcf->peers->number;
361 #if (NGX_THREADS) 380 #if (NGX_THREADS)
377 } 396 }
378 397
379 u->pipe.input_filter = ngx_event_pipe_copy_input_filter; 398 u->pipe.input_filter = ngx_event_pipe_copy_input_filter;
380 399
381 u->accel = 1; 400 u->accel = 1;
382 401
383 r->upstream = u; 402 r->upstream = u;
384 403
385 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); 404 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
386 405
387 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 406 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
393 412
394 413
395 static ngx_int_t 414 static ngx_int_t
396 ngx_http_proxy_create_request(ngx_http_request_t *r) 415 ngx_http_proxy_create_request(ngx_http_request_t *r)
397 { 416 {
398 size_t len, loc_len; 417 size_t len, loc_len, body_len;
399 ngx_uint_t i, key; 418 ngx_uint_t i, key;
400 uintptr_t escape; 419 uintptr_t escape;
401 ngx_buf_t *b; 420 ngx_buf_t *b;
402 ngx_str_t *hh, method; 421 ngx_str_t *hh, method;
403 ngx_chain_t *cl, *body; 422 ngx_chain_t *cl, *body;
404 ngx_list_part_t *part; 423 ngx_list_part_t *part;
405 ngx_table_elt_t *header; 424 ngx_table_elt_t *header;
406 ngx_http_upstream_t *u; 425 ngx_http_upstream_t *u;
426 ngx_http_proxy_ctx_t *p;
407 ngx_http_script_code_pt code; 427 ngx_http_script_code_pt code;
408 ngx_http_script_engine_t e, le; 428 ngx_http_script_engine_t e, le;
409 ngx_http_proxy_loc_conf_t *plcf; 429 ngx_http_proxy_loc_conf_t *plcf;
410 ngx_http_script_len_code_pt lcode; 430 ngx_http_script_len_code_pt lcode;
411 431
412 u = r->upstream; 432 u = r->upstream;
413 433
414 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 434 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
415 435
436 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
437 if (p == NULL) {
438 return NGX_HTTP_INTERNAL_SERVER_ERROR;
439 }
440
441 ngx_http_set_ctx(r, p, ngx_http_proxy_module);
442
416 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; 443 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
417 444
418 if (u->method.len) { 445 if (u->method.len) {
419 /* HEAD was changed to GET to cache response */ 446 /* HEAD was changed to GET to cache response */
420 method = u->method; 447 method = u->method;
444 } 471 }
445 472
446 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len; 473 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
447 } 474 }
448 475
449 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
450
451 ngx_http_script_flush_no_cachable_variables(r, plcf->flushes); 476 ngx_http_script_flush_no_cachable_variables(r, plcf->flushes);
477
478 if (plcf->body_set_len) {
479 le.ip = plcf->body_set_len->elts;
480 le.request = r;
481 le.flushed = 1;
482 body_len = 0;
483
484 while (*(uintptr_t *) le.ip) {
485 lcode = *(ngx_http_script_len_code_pt *) le.ip;
486 body_len += lcode(&le);
487 }
488
489 p->internal_body_length = body_len;
490 len += body_len;
491 }
452 492
453 le.ip = plcf->headers_set_len->elts; 493 le.ip = plcf->headers_set_len->elts;
454 le.request = r; 494 le.request = r;
455 le.flushed = 1; 495 le.flushed = 1;
456 496
476 break; 516 break;
477 } 517 }
478 518
479 part = part->next; 519 part = part->next;
480 header = part->elts; 520 header = part->elts;
481 i = 0; 521 i = 0;
482 } 522 }
483 523
484 key = header[i].hash % plcf->headers_set_hash->hash_size; 524 key = header[i].hash % plcf->headers_set_hash->hash_size;
485 525
486 if (hh[key].len == header[i].key.len 526 if (hh[key].len == header[i].key.len
525 if (escape) { 565 if (escape) {
526 ngx_escape_uri(b->last, r->uri.data + loc_len, 566 ngx_escape_uri(b->last, r->uri.data + loc_len,
527 r->uri.len - loc_len, NGX_ESCAPE_URI); 567 r->uri.len - loc_len, NGX_ESCAPE_URI);
528 b->last += r->uri.len - loc_len + escape; 568 b->last += r->uri.len - loc_len + escape;
529 569
530 } else { 570 } else {
531 b->last = ngx_copy(b->last, r->uri.data + loc_len, 571 b->last = ngx_copy(b->last, r->uri.data + loc_len,
532 r->uri.len - loc_len); 572 r->uri.len - loc_len);
533 } 573 }
534 574
535 if (r->args.len > 0) { 575 if (r->args.len > 0) {
541 u->uri.len = b->last - u->uri.data; 581 u->uri.len = b->last - u->uri.data;
542 582
543 b->last = ngx_cpymem(b->last, ngx_http_proxy_version, 583 b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
544 sizeof(ngx_http_proxy_version) - 1); 584 sizeof(ngx_http_proxy_version) - 1);
545 585
586 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
546 587
547 e.ip = plcf->headers_set->elts; 588 e.ip = plcf->headers_set->elts;
548 e.pos = b->last; 589 e.pos = b->last;
549 e.request = r; 590 e.request = r;
550 e.flushed = 1; 591 e.flushed = 1;
572 le.ip += sizeof(uintptr_t); 613 le.ip += sizeof(uintptr_t);
573 614
574 while (*(uintptr_t *) e.ip) { 615 while (*(uintptr_t *) e.ip) {
575 code = *(ngx_http_script_code_pt *) e.ip; 616 code = *(ngx_http_script_code_pt *) e.ip;
576 code((ngx_http_script_engine_t *) &e); 617 code((ngx_http_script_engine_t *) &e);
577 } 618 }
578 e.ip += sizeof(uintptr_t); 619 e.ip += sizeof(uintptr_t);
579 } 620 }
580 621
581 b->last = e.pos; 622 b->last = e.pos;
582 623
583 624
584 if (plcf->upstream.pass_request_headers) { 625 if (plcf->upstream.pass_request_headers) {
585 part = &r->headers_in.headers.part; 626 part = &r->headers_in.headers.part;
586 header = part->elts; 627 header = part->elts;
587 628
588 for (i = 0; /* void */; i++) { 629 for (i = 0; /* void */; i++) {
589 630
590 if (i >= part->nelts) { 631 if (i >= part->nelts) {
591 if (part->next == NULL) { 632 if (part->next == NULL) {
592 break; 633 break;
593 } 634 }
594 635
595 part = part->next; 636 part = part->next;
596 header = part->elts; 637 header = part->elts;
597 i = 0; 638 i = 0;
598 } 639 }
599 640
600 key = header[i].hash % plcf->headers_set_hash->hash_size; 641 key = header[i].hash % plcf->headers_set_hash->hash_size;
601 642
602 if (hh[key].len == header[i].key.len 643 if (hh[key].len == header[i].key.len
618 "http proxy header: \"%V: %V\"", 659 "http proxy header: \"%V: %V\"",
619 &header[i].key, &header[i].value); 660 &header[i].key, &header[i].value);
620 } 661 }
621 } 662 }
622 663
664
623 /* add "\r\n" at the header end */ 665 /* add "\r\n" at the header end */
624 *b->last++ = CR; *b->last++ = LF; 666 *b->last++ = CR; *b->last++ = LF;
667
668 if (plcf->body_set) {
669 e.ip = plcf->body_set->elts;
670 e.pos = b->last;
671
672 while (*(uintptr_t *) e.ip) {
673 code = *(ngx_http_script_code_pt *) e.ip;
674 code((ngx_http_script_engine_t *) &e);
675 }
676 }
677
678 b->last = e.pos;
625 679
626 #if (NGX_DEBUG) 680 #if (NGX_DEBUG)
627 { 681 {
628 ngx_str_t s; 682 ngx_str_t s;
629 683
632 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 686 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
633 "http proxy header:\n\"%V\"", &s); 687 "http proxy header:\n\"%V\"", &s);
634 } 688 }
635 #endif 689 #endif
636 690
637 if (plcf->upstream.pass_request_body) { 691 if (plcf->body_set == NULL && plcf->upstream.pass_request_body) {
638 692
639 body = u->request_bufs; 693 body = u->request_bufs;
640 u->request_bufs = cl; 694 u->request_bufs = cl;
641 695
642 while (body) { 696 while (body) {
698 ngx_http_proxy_ctx_t *p; 752 ngx_http_proxy_ctx_t *p;
699 753
700 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); 754 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
701 755
702 if (p == NULL) { 756 if (p == NULL) {
703 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t)); 757 return NGX_HTTP_INTERNAL_SERVER_ERROR;
704 if (p == NULL) {
705 return NGX_HTTP_INTERNAL_SERVER_ERROR;
706 }
707
708 ngx_http_set_ctx(r, p, ngx_http_proxy_module);
709 } 758 }
710 759
711 rc = ngx_http_proxy_parse_status_line(r, p); 760 rc = ngx_http_proxy_parse_status_line(r, p);
712 761
713 if (rc == NGX_AGAIN) { 762 if (rc == NGX_AGAIN) {
716 765
717 u = r->upstream; 766 u = r->upstream;
718 767
719 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { 768 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
720 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 769 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
721 "upstream sent no valid HTTP/1.0 header"); 770 "upstream sent no valid HTTP/1.0 header");
722 771
723 if (u->accel) { 772 if (u->accel) {
724 return NGX_HTTP_UPSTREAM_INVALID_HEADER; 773 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
725 } 774 }
726 775
727 r->http_version = NGX_HTTP_VERSION_9; 776 r->http_version = NGX_HTTP_VERSION_9;
728 p->status = NGX_HTTP_OK; 777 p->status = NGX_HTTP_OK;
729 778
730 return NGX_OK; 779 return NGX_OK;
731 } 780 }
732 781
733 u->headers_in.status_n = p->status; 782 u->headers_in.status_n = p->status;
734 u->state->status = p->status; 783 u->state->status = p->status;
771 sw_minor_digit, 820 sw_minor_digit,
772 sw_status, 821 sw_status,
773 sw_space_after_status, 822 sw_space_after_status,
774 sw_status_text, 823 sw_status_text,
775 sw_almost_done 824 sw_almost_done
776 } state; 825 } state;
777 826
778 u = r->upstream; 827 u = r->upstream;
779 828
780 state = r->state; 829 state = r->state;
781 830
785 switch (state) { 834 switch (state) {
786 835
787 /* "HTTP/" */ 836 /* "HTTP/" */
788 case sw_start: 837 case sw_start:
789 switch (ch) { 838 switch (ch) {
790 case 'H': 839 case 'H':
791 state = sw_H; 840 state = sw_H;
792 break; 841 break;
793 default: 842 default:
794 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 843 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
795 } 844 }
796 break; 845 break;
797 846
798 case sw_H: 847 case sw_H:
799 switch (ch) { 848 switch (ch) {
800 case 'T': 849 case 'T':
801 state = sw_HT; 850 state = sw_HT;
802 break; 851 break;
803 default: 852 default:
804 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 853 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
805 } 854 }
806 break; 855 break;
807 856
808 case sw_HT: 857 case sw_HT:
809 switch (ch) { 858 switch (ch) {
810 case 'T': 859 case 'T':
811 state = sw_HTT; 860 state = sw_HTT;
812 break; 861 break;
813 default: 862 default:
814 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 863 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
815 } 864 }
816 break; 865 break;
817 866
818 case sw_HTT: 867 case sw_HTT:
819 switch (ch) { 868 switch (ch) {
820 case 'P': 869 case 'P':
821 state = sw_HTTP; 870 state = sw_HTTP;
822 break; 871 break;
823 default: 872 default:
824 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 873 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
825 } 874 }
826 break; 875 break;
827 876
828 case sw_HTTP: 877 case sw_HTTP:
829 switch (ch) { 878 switch (ch) {
830 case '/': 879 case '/':
831 state = sw_first_major_digit; 880 state = sw_first_major_digit;
832 break; 881 break;
833 default: 882 default:
834 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 883 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
835 } 884 }
895 break; 944 break;
896 945
897 /* space or end of line */ 946 /* space or end of line */
898 case sw_space_after_status: 947 case sw_space_after_status:
899 switch (ch) { 948 switch (ch) {
900 case ' ': 949 case ' ':
901 state = sw_status_text; 950 state = sw_status_text;
902 break; 951 break;
903 case '.': /* IIS may send 403.1, 403.2, etc */ 952 case '.': /* IIS may send 403.1, 403.2, etc */
904 state = sw_status_text; 953 state = sw_status_text;
905 break; 954 break;
1042 static void 1091 static void
1043 ngx_http_proxy_abort_request(ngx_http_request_t *r) 1092 ngx_http_proxy_abort_request(ngx_http_request_t *r)
1044 { 1093 {
1045 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1094 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1046 "abort http proxy request"); 1095 "abort http proxy request");
1047 1096
1048 return; 1097 return;
1049 } 1098 }
1050 1099
1051 1100
1052 static void 1101 static void
1053 ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) 1102 ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1054 { 1103 {
1055 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1104 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1056 "finalize http proxy request"); 1105 "finalize http proxy request");
1057 1106
1058 return; 1107 return;
1059 } 1108 }
1066 ngx_http_proxy_loc_conf_t *plcf; 1115 ngx_http_proxy_loc_conf_t *plcf;
1067 1116
1068 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1117 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1069 1118
1070 v->len = plcf->host_header.len; 1119 v->len = plcf->host_header.len;
1071 v->valid = 1; 1120 v->valid = 1;
1072 v->no_cachable = 0; 1121 v->no_cachable = 0;
1073 v->not_found = 0; 1122 v->not_found = 0;
1074 v->data = plcf->host_header.data; 1123 v->data = plcf->host_header.data;
1075 1124
1076 return NGX_OK; 1125 return NGX_OK;
1084 ngx_http_proxy_loc_conf_t *plcf; 1133 ngx_http_proxy_loc_conf_t *plcf;
1085 1134
1086 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1135 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1087 1136
1088 v->len = plcf->port_text.len; 1137 v->len = plcf->port_text.len;
1089 v->valid = 1; 1138 v->valid = 1;
1090 v->no_cachable = 0; 1139 v->no_cachable = 0;
1091 v->not_found = 0; 1140 v->not_found = 0;
1092 v->data = plcf->port_text.data; 1141 v->data = plcf->port_text.data;
1093 1142
1094 return NGX_OK; 1143 return NGX_OK;
1095 } 1144 }
1096 1145
1097 1146
1098 static ngx_int_t 1147 static ngx_int_t
1099 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, 1148 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
1100
1101 ngx_http_variable_value_t *v, uintptr_t data) 1149 ngx_http_variable_value_t *v, uintptr_t data)
1102 { 1150 {
1103 u_char *p; 1151 u_char *p;
1104 1152
1105 v->valid = 1; 1153 v->valid = 1;
1106 v->no_cachable = 0; 1154 v->no_cachable = 0;
1107 v->not_found = 0; 1155 v->not_found = 0;
1108 1156
1109 if (r->headers_in.x_forwarded_for == NULL) { 1157 if (r->headers_in.x_forwarded_for == NULL) {
1110 v->len = r->connection->addr_text.len; 1158 v->len = r->connection->addr_text.len;
1126 r->headers_in.x_forwarded_for->value.len); 1174 r->headers_in.x_forwarded_for->value.len);
1127 1175
1128 *p++ = ','; *p++ = ' '; 1176 *p++ = ','; *p++ = ' ';
1129 1177
1130 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); 1178 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
1179
1180 return NGX_OK;
1181 }
1182
1183
1184 static ngx_int_t
1185 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
1186 ngx_http_variable_value_t *v, uintptr_t data)
1187 {
1188 ngx_http_proxy_ctx_t *p;
1189
1190 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1191
1192 if (p == NULL) {
1193 v->not_found = 1;
1194 return NGX_OK;
1195 }
1196
1197 v->valid = 1;
1198 v->no_cachable = 0;
1199 v->not_found = 0;
1200
1201 v->data = ngx_palloc(r->connection->pool, NGX_SIZE_T_LEN);
1202
1203 if (v->data == NULL) {
1204 return NGX_ERROR;
1205 }
1206
1207 v->len = ngx_sprintf(v->data, "%uz", p->internal_body_length) - v->data;
1131 1208
1132 return NGX_OK; 1209 return NGX_OK;
1133 } 1210 }
1134 1211
1135 1212
1292 * conf->method = NULL; 1369 * conf->method = NULL;
1293 * conf->headers_source = NULL; 1370 * conf->headers_source = NULL;
1294 * conf->headers_set_len = NULL; 1371 * conf->headers_set_len = NULL;
1295 * conf->headers_set = NULL; 1372 * conf->headers_set = NULL;
1296 * conf->headers_set_hash = NULL; 1373 * conf->headers_set_hash = NULL;
1374 * conf->body_set_len = NULL;
1375 * conf->body_set = NULL;
1376 * conf->body_source = { 0, NULL };
1297 * conf->rewrite_locations = NULL; 1377 * conf->rewrite_locations = NULL;
1298 */ 1378 */
1299 1379
1300 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; 1380 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
1301 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; 1381 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
1302 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; 1382 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
1303 1383
1304 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; 1384 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
1305 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; 1385 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE;
1306 1386
1307 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; 1387 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
1308 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; 1388 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
1309 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; 1389 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
1310 1390
1311 conf->upstream.max_fails = NGX_CONF_UNSET_UINT; 1391 conf->upstream.max_fails = NGX_CONF_UNSET_UINT;
1312 conf->upstream.fail_timeout = NGX_CONF_UNSET; 1392 conf->upstream.fail_timeout = NGX_CONF_UNSET;
1313 1393
1364 1444
1365 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, 1445 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
1366 8, ngx_pagesize); 1446 8, ngx_pagesize);
1367 1447
1368 if (conf->upstream.bufs.num < 2) { 1448 if (conf->upstream.bufs.num < 2) {
1369 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1449 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1370 "there must be at least 2 \"proxy_buffers\""); 1450 "there must be at least 2 \"proxy_buffers\"");
1371 return NGX_CONF_ERROR; 1451 return NGX_CONF_ERROR;
1372 } 1452 }
1373 1453
1374 1454
1375 size = conf->upstream.header_buffer_size; 1455 size = conf->upstream.header_buffer_size;
1376 if (size < conf->upstream.bufs.size) { 1456 if (size < conf->upstream.bufs.size) {
1377 size = conf->upstream.bufs.size; 1457 size = conf->upstream.bufs.size;
1378 } 1458 }
1379 1459
1380 1460
1381 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, 1461 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
1386 conf->upstream.busy_buffers_size = 2 * size; 1466 conf->upstream.busy_buffers_size = 2 * size;
1387 } else { 1467 } else {
1388 conf->upstream.busy_buffers_size = 1468 conf->upstream.busy_buffers_size =
1389 conf->upstream.busy_buffers_size_conf; 1469 conf->upstream.busy_buffers_size_conf;
1390 } 1470 }
1391 1471
1392 if (conf->upstream.busy_buffers_size < size) { 1472 if (conf->upstream.busy_buffers_size < size) {
1393 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1473 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1394 "\"proxy_busy_buffers_size\" must be equal or bigger than " 1474 "\"proxy_busy_buffers_size\" must be equal or bigger than "
1395 "maximum of the value of \"proxy_header_buffer_size\" and " 1475 "maximum of the value of \"proxy_header_buffer_size\" and "
1396 "one of the \"proxy_buffers\""); 1476 "one of the \"proxy_buffers\"");
1417 conf->upstream.temp_file_write_size = 2 * size; 1497 conf->upstream.temp_file_write_size = 2 * size;
1418 } else { 1498 } else {
1419 conf->upstream.temp_file_write_size = 1499 conf->upstream.temp_file_write_size =
1420 conf->upstream.temp_file_write_size_conf; 1500 conf->upstream.temp_file_write_size_conf;
1421 } 1501 }
1422 1502
1423 if (conf->upstream.temp_file_write_size < size) { 1503 if (conf->upstream.temp_file_write_size < size) {
1424 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1504 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1425 "\"proxy_temp_file_write_size\" must be equal or bigger than " 1505 "\"proxy_temp_file_write_size\" must be equal or bigger than "
1426 "maximum of the value of \"proxy_header_buffer_size\" and " 1506 "maximum of the value of \"proxy_header_buffer_size\" and "
1427 "one of the \"proxy_buffers\""); 1507 "one of the \"proxy_buffers\"");
1532 1612
1533 if (conf->peers == NULL) { 1613 if (conf->peers == NULL) {
1534 conf->peers = prev->peers; 1614 conf->peers = prev->peers;
1535 } 1615 }
1536 1616
1617
1618 if (conf->body_source.data == NULL) {
1619 conf->body_source = prev->body_source;
1620 conf->body_set_len = prev->body_set_len;
1621 conf->body_set = prev->body_set;
1622 }
1623
1624 if (conf->body_set_len == 0) {
1625
1626 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1627
1628 sc.cf = cf;
1629 sc.source = &conf->body_source;
1630 sc.flushes = &conf->flushes;
1631 sc.lengths = &conf->body_set_len;
1632 sc.values = &conf->body_set;
1633 sc.complete_lengths = 1;
1634 sc.complete_values = 1;
1635
1636 if (ngx_http_script_compile(&sc) != NGX_OK) {
1637 return NGX_CONF_ERROR;
1638 }
1639
1640 if (conf->headers_source == NULL) {
1641 conf->headers_source = ngx_array_create(cf->pool, 4,
1642 sizeof(ngx_table_elt_t));
1643 if (conf->headers_source == NULL) {
1644 return NGX_CONF_ERROR;
1645 }
1646 }
1647
1648 s = ngx_array_push(conf->headers_source);
1649 if (s == NULL) {
1650 return NGX_CONF_ERROR;
1651 }
1652
1653 s->hash = 0;
1654 s->key.len = sizeof("Content-Length") - 1;
1655 s->key.data = (u_char *) "Content-Length";
1656 s->value.len = sizeof("$proxy_internal_body_length") - 1;
1657 s->value.data = (u_char *) "$proxy_internal_body_length";
1658 }
1659
1660
1537 if (conf->headers_source == NULL) { 1661 if (conf->headers_source == NULL) {
1538 conf->flushes = prev->flushes; 1662 conf->flushes = prev->flushes;
1539 conf->headers_set_len = prev->headers_set_len; 1663 conf->headers_set_len = prev->headers_set_len;
1540 conf->headers_set = prev->headers_set; 1664 conf->headers_set = prev->headers_set;
1541 conf->headers_set_hash = prev->headers_set_hash; 1665 conf->headers_set_hash = prev->headers_set_hash;
1593 next: 1717 next:
1594 1718
1595 continue; 1719 continue;
1596 } 1720 }
1597 1721
1722
1723 src = conf->headers_source->elts;
1598 for (i = 0; i < conf->headers_source->nelts; i++) { 1724 for (i = 0; i < conf->headers_source->nelts; i++) {
1599 1725
1600 name = ngx_array_push(conf->headers_names); 1726 name = ngx_array_push(conf->headers_names);
1601 if (name == NULL) { 1727 if (name == NULL) {
1602 return NGX_CONF_ERROR; 1728 return NGX_CONF_ERROR;
1764 static char * 1890 static char *
1765 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 1891 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1766 { 1892 {
1767 ngx_http_proxy_loc_conf_t *plcf = conf; 1893 ngx_http_proxy_loc_conf_t *plcf = conf;
1768 1894
1895 size_t add;
1769 ngx_str_t *value, *url; 1896 ngx_str_t *value, *url;
1770 ngx_inet_upstream_t inet_upstream; 1897 ngx_inet_upstream_t inet_upstream;
1771 ngx_http_core_loc_conf_t *clcf; 1898 ngx_http_core_loc_conf_t *clcf;
1899 #if (NGX_HTTP_SSL)
1900 ngx_pool_cleanup_t *cln;
1901 #endif
1772 #if (NGX_HAVE_UNIX_DOMAIN) 1902 #if (NGX_HAVE_UNIX_DOMAIN)
1773 ngx_unix_domain_upstream_t unix_upstream; 1903 ngx_unix_domain_upstream_t unix_upstream;
1774 #endif 1904 #endif
1775 1905
1776 if (plcf->upstream.schema.len) { 1906 if (plcf->upstream.schema.len) {
1779 1909
1780 value = cf->args->elts; 1910 value = cf->args->elts;
1781 1911
1782 url = &value[1]; 1912 url = &value[1];
1783 1913
1784 if (ngx_strncasecmp(url->data, "http://", 7) != 0) { 1914 if (ngx_strncasecmp(url->data, "http://", 7) == 0) {
1915 add = 7;
1916
1917 } else if (ngx_strncasecmp(url->data, "https://", 8) == 0) {
1918
1919 #if (NGX_HTTP_SSL)
1920
1921 add = 8;
1922
1923 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
1924 if (plcf->upstream.ssl == NULL) {
1925 return NGX_CONF_ERROR;
1926 }
1927
1928 plcf->upstream.ssl->log = cf->log;
1929
1930 if (ngx_ssl_create(plcf->upstream.ssl,
1931 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1)
1932 != NGX_OK)
1933 {
1934 return NGX_CONF_ERROR;
1935 }
1936
1937 cln = ngx_pool_cleanup_add(cf->pool, 0);
1938 if (cln == NULL) {
1939 return NGX_CONF_ERROR;
1940 }
1941
1942 cln->handler = ngx_ssl_cleanup_ctx;
1943 cln->data = plcf->upstream.ssl;
1944
1945 #else
1946 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1947 "https protocol requires SSL support");
1948 return NGX_CONF_ERROR;
1949 #endif
1950
1951 } else {
1785 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix"); 1952 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
1786 return NGX_CONF_ERROR; 1953 return NGX_CONF_ERROR;
1787 } 1954 }
1788 1955
1789 if (ngx_strncasecmp(url->data + 7, "unix:", 5) == 0) { 1956 if (ngx_strncasecmp(url->data + add, "unix:", 5) == 0) {
1790 1957
1791 #if (NGX_HAVE_UNIX_DOMAIN) 1958 #if (NGX_HAVE_UNIX_DOMAIN)
1792 1959
1793 ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t)); 1960 ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
1794 1961
1795 unix_upstream.name = *url; 1962 unix_upstream.name = *url;
1796 unix_upstream.url.len = url->len - 7; 1963 unix_upstream.url.len = url->len - add;
1797 unix_upstream.url.data = url->data + 7; 1964 unix_upstream.url.data = url->data + add;
1798 unix_upstream.uri_part = 1; 1965 unix_upstream.uri_part = 1;
1799 1966
1800 plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); 1967 plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
1801 if (plcf->peers == NULL) { 1968 if (plcf->peers == NULL) {
1802 return NGX_CONF_ERROR; 1969 return NGX_CONF_ERROR;
1816 1983
1817 } else { 1984 } else {
1818 ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t)); 1985 ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
1819 1986
1820 inet_upstream.name = *url; 1987 inet_upstream.name = *url;
1821 inet_upstream.url.len = url->len - 7; 1988 inet_upstream.url.len = url->len - add;
1822 inet_upstream.url.data = url->data + 7; 1989 inet_upstream.url.data = url->data + add;
1823 inet_upstream.default_port_value = 80; 1990 inet_upstream.default_port_value = 80;
1824 inet_upstream.uri_part = 1; 1991 inet_upstream.uri_part = 1;
1825 1992
1826 plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); 1993 plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
1827 if (plcf->peers == NULL) { 1994 if (plcf->peers == NULL) {