comparison src/http/modules/ngx_http_proxy_module.c @ 348:e10168d6e371 NGINX_0_6_18

nginx 0.6.18 *) Change: now the ngx_http_userid_module adds start time microseconds to the cookie field contains a pid value. *) Change: now the full request line instead of URI only is written to error_log. *) Feature: variables support in the "proxy_pass" directive. *) Feature: the "resolver" and "resolver_timeout" directives. *) Feature: now the directive "add_header last-modified ''" deletes a "Last-Modified" response header line. *) Bugfix: the "limit_rate" directive did not allow to use full throughput, even if limit value was very high.
author Igor Sysoev <http://sysoev.ru>
date Tue, 27 Nov 2007 00:00:00 +0300
parents 05693816539c
children 84b8345f70d5
comparison
equal deleted inserted replaced
347:d53199b68e17 348:e10168d6e371
28 } vars; 28 } vars;
29 29
30 void *regex; 30 void *regex;
31 } replacement; 31 } replacement;
32 }; 32 };
33
34
35 typedef struct {
36 ngx_str_t host_header;
37 ngx_str_t port;
38 ngx_str_t uri;
39 } ngx_http_proxy_vars_t;
33 40
34 41
35 typedef struct { 42 typedef struct {
36 ngx_http_upstream_conf_t upstream; 43 ngx_http_upstream_conf_t upstream;
37 44
43 ngx_hash_t headers_set_hash; 50 ngx_hash_t headers_set_hash;
44 51
45 ngx_array_t *headers_source; 52 ngx_array_t *headers_source;
46 ngx_array_t *headers_names; 53 ngx_array_t *headers_names;
47 54
55 ngx_array_t *proxy_lengths;
56 ngx_array_t *proxy_values;
57
48 ngx_array_t *redirects; 58 ngx_array_t *redirects;
49 59
50 ngx_str_t body_source; 60 ngx_str_t body_source;
51 61
52 ngx_str_t method; 62 ngx_str_t method;
53 ngx_str_t host_header; 63 ngx_str_t location;
54 ngx_str_t port; 64 ngx_str_t url;
65
66 ngx_http_proxy_vars_t vars;
55 67
56 ngx_flag_t redirect; 68 ngx_flag_t redirect;
57 69
58 ngx_uint_t headers_hash_max_size; 70 ngx_uint_t headers_hash_max_size;
59 ngx_uint_t headers_hash_bucket_size; 71 ngx_uint_t headers_hash_bucket_size;
64 ngx_uint_t status; 76 ngx_uint_t status;
65 ngx_uint_t status_count; 77 ngx_uint_t status_count;
66 u_char *status_start; 78 u_char *status_start;
67 u_char *status_end; 79 u_char *status_end;
68 80
81 ngx_http_proxy_vars_t vars;
82
69 size_t internal_body_length; 83 size_t internal_body_length;
70 } ngx_http_proxy_ctx_t; 84 } ngx_http_proxy_ctx_t;
71 85
72 86
73 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 87 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
74 88
75 89
90 static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
91 ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
76 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); 92 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
77 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); 93 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
78 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r); 94 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
79 static ngx_int_t ngx_http_proxy_parse_status_line(ngx_http_request_t *r, 95 static ngx_int_t ngx_http_proxy_parse_status_line(ngx_http_request_t *r,
80 ngx_http_proxy_ctx_t *p); 96 ngx_http_proxy_ctx_t *ctx);
81 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); 97 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
82 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); 98 static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
83 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, 99 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
84 ngx_int_t rc); 100 ngx_int_t rc);
85 101
112 128
113 static char *ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t *cf, 129 static char *ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t *cf,
114 ngx_command_t *cmd, void *conf); 130 ngx_command_t *cmd, void *conf);
115 static char *ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t *cf, 131 static char *ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
116 ngx_command_t *cmd, void *conf); 132 ngx_command_t *cmd, void *conf);
133
134 #if (NGX_HTTP_SSL)
135 static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
136 ngx_http_proxy_loc_conf_t *plcf);
137 #endif
138 static ngx_int_t ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
139 ngx_http_proxy_vars_t *v);
117 140
118 141
119 static ngx_conf_post_t ngx_http_proxy_lowat_post = 142 static ngx_conf_post_t ngx_http_proxy_lowat_post =
120 { ngx_http_proxy_lowat_check }; 143 { ngx_http_proxy_lowat_check };
121 144
442 static ngx_int_t 465 static ngx_int_t
443 ngx_http_proxy_handler(ngx_http_request_t *r) 466 ngx_http_proxy_handler(ngx_http_request_t *r)
444 { 467 {
445 ngx_int_t rc; 468 ngx_int_t rc;
446 ngx_http_upstream_t *u; 469 ngx_http_upstream_t *u;
470 ngx_http_proxy_ctx_t *ctx;
447 ngx_http_proxy_loc_conf_t *plcf; 471 ngx_http_proxy_loc_conf_t *plcf;
448
449 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
450 472
451 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); 473 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
452 if (u == NULL) { 474 if (u == NULL) {
453 return NGX_HTTP_INTERNAL_SERVER_ERROR; 475 return NGX_HTTP_INTERNAL_SERVER_ERROR;
476 }
477
478 r->upstream = u;
479
480 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
481 if (ctx == NULL) {
482 return NGX_ERROR;
483 }
484
485 ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
486
487 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
488
489 if (plcf->proxy_lengths == 0) {
490 ctx->vars = plcf->vars;
491 u->schema = plcf->upstream.schema;
492 #if (NGX_HTTP_SSL)
493 u->ssl = (plcf->upstream.ssl != NULL);
494 #endif
495
496 } else {
497 if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
498 return NGX_HTTP_INTERNAL_SERVER_ERROR;
499 }
454 } 500 }
455 501
456 u->peer.log = r->connection->log; 502 u->peer.log = r->connection->log;
457 u->peer.log_error = NGX_ERROR_ERR; 503 u->peer.log_error = NGX_ERROR_ERR;
458 #if (NGX_THREADS) 504 #if (NGX_THREADS)
482 528
483 u->pipe->input_filter = ngx_event_pipe_copy_input_filter; 529 u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
484 530
485 u->accel = 1; 531 u->accel = 1;
486 532
487 r->upstream = u;
488
489 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); 533 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
490 534
491 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 535 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
492 return rc; 536 return rc;
493 } 537 }
494 538
495 return NGX_DONE; 539 return NGX_DONE;
540 }
541
542
543 static ngx_int_t
544 ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
545 ngx_http_proxy_loc_conf_t *plcf)
546 {
547 size_t add;
548 u_short port;
549 ngx_str_t proxy;
550 ngx_url_t u;
551
552 if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
553 plcf->proxy_values->elts)
554 == NULL)
555 {
556 return NGX_ERROR;
557 }
558
559 if (ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0) {
560
561 add = 7;
562 port = 80;
563
564 #if (NGX_HTTP_SSL)
565
566 } else if (ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0) {
567
568 add = 8;
569 port = 443;
570 r->upstream->ssl = 1;
571
572 #endif
573
574 } else {
575 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
576 "invalid URL prefix in \"%V\"", &proxy);
577 return NGX_ERROR;
578 }
579
580 r->upstream->schema.len = add;
581 r->upstream->schema.data = proxy.data;
582
583 ngx_memzero(&u, sizeof(ngx_url_t));
584
585 u.url.len = proxy.len - add;
586 u.url.data = proxy.data + add;
587 u.default_port = port;
588 u.uri_part = 1;
589 u.no_resolve = 1;
590
591 if (ngx_parse_url(r->pool, &u) != NGX_OK) {
592 if (u.err) {
593 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
594 "%s in upstream \"%V\"", u.err, &u.url);
595 }
596
597 return NGX_ERROR;
598 }
599
600 if (ngx_http_proxy_set_vars(r->pool, &u, &ctx->vars) != NGX_OK) {
601 return NGX_ERROR;
602 }
603
604 r->upstream->resolved = ngx_pcalloc(r->pool,
605 sizeof(ngx_http_upstream_resolved_t));
606 if (r->upstream->resolved == NULL) {
607 return NGX_ERROR;
608 }
609
610 r->upstream->resolved->host = u.host;
611 r->upstream->resolved->port = (in_port_t) (u.no_port ? u.default_port:
612 u.port);
613
614 return NGX_OK;
496 } 615 }
497 616
498 617
499 static ngx_int_t 618 static ngx_int_t
500 ngx_http_proxy_create_request(ngx_http_request_t *r) 619 ngx_http_proxy_create_request(ngx_http_request_t *r)
506 ngx_uint_t i, unparsed_uri; 625 ngx_uint_t i, unparsed_uri;
507 ngx_chain_t *cl, *body; 626 ngx_chain_t *cl, *body;
508 ngx_list_part_t *part; 627 ngx_list_part_t *part;
509 ngx_table_elt_t *header; 628 ngx_table_elt_t *header;
510 ngx_http_upstream_t *u; 629 ngx_http_upstream_t *u;
511 ngx_http_proxy_ctx_t *p; 630 ngx_http_proxy_ctx_t *ctx;
512 ngx_http_script_code_pt code; 631 ngx_http_script_code_pt code;
513 ngx_http_script_engine_t e, le; 632 ngx_http_script_engine_t e, le;
514 ngx_http_proxy_loc_conf_t *plcf; 633 ngx_http_proxy_loc_conf_t *plcf;
515 ngx_http_script_len_code_pt lcode; 634 ngx_http_script_len_code_pt lcode;
516 635
517 u = r->upstream; 636 u = r->upstream;
518 637
519 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 638 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
520 639
521 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
522 if (p == NULL) {
523 return NGX_HTTP_INTERNAL_SERVER_ERROR;
524 }
525
526 ngx_http_set_ctx(r, p, ngx_http_proxy_module);
527
528 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; 640 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
529 641
530 if (u->method.len) { 642 if (u->method.len) {
531 /* HEAD was changed to GET to cache response */ 643 /* HEAD was changed to GET to cache response */
532 method = u->method; 644 method = u->method;
538 } else { 650 } else {
539 method = r->method_name; 651 method = r->method_name;
540 method.len++; 652 method.len++;
541 } 653 }
542 654
543 len += method.len + u->conf->uri.len;
544
545 escape = 0; 655 escape = 0;
546 656 loc_len = 0;
547 loc_len = (r->valid_location && u->conf->uri.len) ? u->conf->location.len: 657 unparsed_uri = 0;
548 0; 658
549 659 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
550 if (u->conf->uri.len == 0 && r->valid_unparsed_uri && r == r->main) { 660
661 if (plcf->proxy_lengths) {
662 len += method.len + ctx->vars.uri.len;
663
664 } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
665 {
551 unparsed_uri = 1; 666 unparsed_uri = 1;
552 len += r->unparsed_uri.len; 667 len += method.len + r->unparsed_uri.len;
553 668
554 } else { 669 } else {
555 unparsed_uri = 0; 670 loc_len = (r->valid_location && ctx->vars.uri.len) ?
671 plcf->location.len : 0;
672
556 if (r->quoted_uri || r->internal) { 673 if (r->quoted_uri || r->internal) {
557 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, 674 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
558 r->uri.len - loc_len, NGX_ESCAPE_URI); 675 r->uri.len - loc_len, NGX_ESCAPE_URI);
559 } 676 }
560 677
572 while (*(uintptr_t *) le.ip) { 689 while (*(uintptr_t *) le.ip) {
573 lcode = *(ngx_http_script_len_code_pt *) le.ip; 690 lcode = *(ngx_http_script_len_code_pt *) le.ip;
574 body_len += lcode(&le); 691 body_len += lcode(&le);
575 } 692 }
576 693
577 p->internal_body_length = body_len; 694 ctx->internal_body_length = body_len;
578 len += body_len; 695 len += body_len;
579 } 696 }
580 697
581 le.ip = plcf->headers_set_len->elts; 698 le.ip = plcf->headers_set_len->elts;
582 le.request = r; 699 le.request = r;
636 753
637 b->last = ngx_copy(b->last, method.data, method.len); 754 b->last = ngx_copy(b->last, method.data, method.len);
638 755
639 u->uri.data = b->last; 756 u->uri.data = b->last;
640 757
641 if (unparsed_uri) { 758 if (plcf->proxy_lengths) {
759 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
760
761 } else if (unparsed_uri) {
642 b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len); 762 b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
643 763
644 } else { 764 } else {
645 if (r->valid_location) { 765 if (r->valid_location) {
646 b->last = ngx_copy(b->last, u->conf->uri.data, u->conf->uri.len); 766 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
647 } 767 }
648 768
649 if (escape) { 769 if (escape) {
650 ngx_escape_uri(b->last, r->uri.data + loc_len, 770 ngx_escape_uri(b->last, r->uri.data + loc_len,
651 r->uri.len - loc_len, NGX_ESCAPE_URI); 771 r->uri.len - loc_len, NGX_ESCAPE_URI);
807 927
808 928
809 static ngx_int_t 929 static ngx_int_t
810 ngx_http_proxy_reinit_request(ngx_http_request_t *r) 930 ngx_http_proxy_reinit_request(ngx_http_request_t *r)
811 { 931 {
812 ngx_http_proxy_ctx_t *p; 932 ngx_http_proxy_ctx_t *ctx;
813 933
814 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); 934 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
815 935
816 if (p == NULL) { 936 if (ctx == NULL) {
817 return NGX_OK; 937 return NGX_OK;
818 } 938 }
819 939
820 p->status = 0; 940 ctx->status = 0;
821 p->status_count = 0; 941 ctx->status_count = 0;
822 p->status_start = NULL; 942 ctx->status_start = NULL;
823 p->status_end = NULL; 943 ctx->status_end = NULL;
824 944
825 r->upstream->process_header = ngx_http_proxy_process_status_line; 945 r->upstream->process_header = ngx_http_proxy_process_status_line;
826 946
827 return NGX_OK; 947 return NGX_OK;
828 } 948 }
831 static ngx_int_t 951 static ngx_int_t
832 ngx_http_proxy_process_status_line(ngx_http_request_t *r) 952 ngx_http_proxy_process_status_line(ngx_http_request_t *r)
833 { 953 {
834 ngx_int_t rc; 954 ngx_int_t rc;
835 ngx_http_upstream_t *u; 955 ngx_http_upstream_t *u;
836 ngx_http_proxy_ctx_t *p; 956 ngx_http_proxy_ctx_t *ctx;
837 957
838 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); 958 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
839 959
840 if (p == NULL) { 960 if (ctx == NULL) {
841 return NGX_HTTP_INTERNAL_SERVER_ERROR; 961 return NGX_HTTP_INTERNAL_SERVER_ERROR;
842 } 962 }
843 963
844 rc = ngx_http_proxy_parse_status_line(r, p); 964 rc = ngx_http_proxy_parse_status_line(r, ctx);
845 965
846 if (rc == NGX_AGAIN) { 966 if (rc == NGX_AGAIN) {
847 return rc; 967 return rc;
848 } 968 }
849 969
864 u->state->status = NGX_HTTP_OK; 984 u->state->status = NGX_HTTP_OK;
865 985
866 return NGX_OK; 986 return NGX_OK;
867 } 987 }
868 988
869 u->headers_in.status_n = p->status; 989 u->headers_in.status_n = ctx->status;
870 u->state->status = p->status; 990 u->state->status = ctx->status;
871 991
872 u->headers_in.status_line.len = p->status_end - p->status_start; 992 u->headers_in.status_line.len = ctx->status_end - ctx->status_start;
873 u->headers_in.status_line.data = ngx_palloc(r->pool, 993 u->headers_in.status_line.data = ngx_palloc(r->pool,
874 u->headers_in.status_line.len); 994 u->headers_in.status_line.len);
875 if (u->headers_in.status_line.data == NULL) { 995 if (u->headers_in.status_line.data == NULL) {
876 return NGX_HTTP_INTERNAL_SERVER_ERROR; 996 return NGX_HTTP_INTERNAL_SERVER_ERROR;
877 } 997 }
878 998
879 ngx_memcpy(u->headers_in.status_line.data, p->status_start, 999 ngx_memcpy(u->headers_in.status_line.data, ctx->status_start,
880 u->headers_in.status_line.len); 1000 u->headers_in.status_line.len);
881 1001
882 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1002 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
883 "http proxy status %ui \"%V\"", 1003 "http proxy status %ui \"%V\"",
884 u->headers_in.status_n, &u->headers_in.status_line); 1004 u->headers_in.status_n, &u->headers_in.status_line);
888 return ngx_http_proxy_process_header(r); 1008 return ngx_http_proxy_process_header(r);
889 } 1009 }
890 1010
891 1011
892 static ngx_int_t 1012 static ngx_int_t
893 ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) 1013 ngx_http_proxy_parse_status_line(ngx_http_request_t *r,
1014 ngx_http_proxy_ctx_t *ctx)
894 { 1015 {
895 u_char ch; 1016 u_char ch;
896 u_char *pos; 1017 u_char *p;
897 ngx_http_upstream_t *u; 1018 ngx_http_upstream_t *u;
898 enum { 1019 enum {
899 sw_start = 0, 1020 sw_start = 0,
900 sw_H, 1021 sw_H,
901 sw_HT, 1022 sw_HT,
913 1034
914 u = r->upstream; 1035 u = r->upstream;
915 1036
916 state = r->state; 1037 state = r->state;
917 1038
918 for (pos = u->buffer.pos; pos < u->buffer.last; pos++) { 1039 for (p = u->buffer.pos; p < u->buffer.last; p++) {
919 ch = *pos; 1040 ch = *p;
920 1041
921 switch (state) { 1042 switch (state) {
922 1043
923 /* "HTTP/" */ 1044 /* "HTTP/" */
924 case sw_start: 1045 case sw_start:
1023 1144
1024 if (ch < '0' || ch > '9') { 1145 if (ch < '0' || ch > '9') {
1025 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 1146 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
1026 } 1147 }
1027 1148
1028 p->status = p->status * 10 + ch - '0'; 1149 ctx->status = ctx->status * 10 + ch - '0';
1029 1150
1030 if (++p->status_count == 3) { 1151 if (++ctx->status_count == 3) {
1031 state = sw_space_after_status; 1152 state = sw_space_after_status;
1032 p->status_start = pos - 2; 1153 ctx->status_start = p - 2;
1033 } 1154 }
1034 1155
1035 break; 1156 break;
1036 1157
1037 /* space or end of line */ 1158 /* space or end of line */
1065 } 1186 }
1066 break; 1187 break;
1067 1188
1068 /* end of status line */ 1189 /* end of status line */
1069 case sw_almost_done: 1190 case sw_almost_done:
1070 p->status_end = pos - 1; 1191 ctx->status_end = p - 1;
1071 switch (ch) { 1192 switch (ch) {
1072 case LF: 1193 case LF:
1073 goto done; 1194 goto done;
1074 default: 1195 default:
1075 return NGX_HTTP_PROXY_PARSE_NO_HEADER; 1196 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
1076 } 1197 }
1077 } 1198 }
1078 } 1199 }
1079 1200
1080 u->buffer.pos = pos; 1201 u->buffer.pos = p;
1081 r->state = state; 1202 r->state = state;
1082 1203
1083 return NGX_AGAIN; 1204 return NGX_AGAIN;
1084 1205
1085 done: 1206 done:
1086 1207
1087 u->buffer.pos = pos + 1; 1208 u->buffer.pos = p + 1;
1088 1209
1089 if (p->status_end == NULL) { 1210 if (ctx->status_end == NULL) {
1090 p->status_end = pos; 1211 ctx->status_end = p;
1091 } 1212 }
1092 1213
1093 r->state = sw_start; 1214 r->state = sw_start;
1094 1215
1095 return NGX_OK; 1216 return NGX_OK;
1242 1363
1243 static ngx_int_t 1364 static ngx_int_t
1244 ngx_http_proxy_host_variable(ngx_http_request_t *r, 1365 ngx_http_proxy_host_variable(ngx_http_request_t *r,
1245 ngx_http_variable_value_t *v, uintptr_t data) 1366 ngx_http_variable_value_t *v, uintptr_t data)
1246 { 1367 {
1247 ngx_http_proxy_loc_conf_t *plcf; 1368 ngx_http_proxy_ctx_t *ctx;
1248 1369
1249 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1370 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1250 1371
1251 v->len = plcf->host_header.len; 1372 if (ctx == NULL) {
1373 v->not_found = 1;
1374 return NGX_OK;
1375 }
1376
1377 v->len = ctx->vars.host_header.len;
1252 v->valid = 1; 1378 v->valid = 1;
1253 v->no_cacheable = 0; 1379 v->no_cacheable = 0;
1254 v->not_found = 0; 1380 v->not_found = 0;
1255 v->data = plcf->host_header.data; 1381 v->data = ctx->vars.host_header.data;
1256 1382
1257 return NGX_OK; 1383 return NGX_OK;
1258 } 1384 }
1259 1385
1260 1386
1261 static ngx_int_t 1387 static ngx_int_t
1262 ngx_http_proxy_port_variable(ngx_http_request_t *r, 1388 ngx_http_proxy_port_variable(ngx_http_request_t *r,
1263 ngx_http_variable_value_t *v, uintptr_t data) 1389 ngx_http_variable_value_t *v, uintptr_t data)
1264 { 1390 {
1265 ngx_http_proxy_loc_conf_t *plcf; 1391 ngx_http_proxy_ctx_t *ctx;
1266 1392
1267 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1393 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1268 1394
1269 v->len = plcf->port.len; 1395 if (ctx == NULL) {
1396 v->not_found = 1;
1397 return NGX_OK;
1398 }
1399
1400 v->len = ctx->vars.port.len;
1270 v->valid = 1; 1401 v->valid = 1;
1271 v->no_cacheable = 0; 1402 v->no_cacheable = 0;
1272 v->not_found = 0; 1403 v->not_found = 0;
1273 v->data = plcf->port.data; 1404 v->data = ctx->vars.port.data;
1274 1405
1275 return NGX_OK; 1406 return NGX_OK;
1276 } 1407 }
1277 1408
1278 1409
1315 1446
1316 static ngx_int_t 1447 static ngx_int_t
1317 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, 1448 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
1318 ngx_http_variable_value_t *v, uintptr_t data) 1449 ngx_http_variable_value_t *v, uintptr_t data)
1319 { 1450 {
1320 ngx_http_proxy_ctx_t *p; 1451 ngx_http_proxy_ctx_t *ctx;
1321 1452
1322 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); 1453 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1323 1454
1324 if (p == NULL) { 1455 if (ctx == NULL) {
1325 v->not_found = 1; 1456 v->not_found = 1;
1326 return NGX_OK; 1457 return NGX_OK;
1327 } 1458 }
1328 1459
1329 v->valid = 1; 1460 v->valid = 1;
1334 1465
1335 if (v->data == NULL) { 1466 if (v->data == NULL) {
1336 return NGX_ERROR; 1467 return NGX_ERROR;
1337 } 1468 }
1338 1469
1339 v->len = ngx_sprintf(v->data, "%uz", p->internal_body_length) - v->data; 1470 v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
1340 1471
1341 return NGX_OK; 1472 return NGX_OK;
1342 } 1473 }
1343 1474
1344 1475
1738 1869
1739 if (conf->redirects == NULL) { 1870 if (conf->redirects == NULL) {
1740 conf->redirects = prev->redirects; 1871 conf->redirects = prev->redirects;
1741 } 1872 }
1742 1873
1743 if (conf->redirects == NULL && conf->upstream.url.data) { 1874 if (conf->redirects == NULL && conf->url.data) {
1744 1875
1745 conf->redirects = ngx_array_create(cf->pool, 1, 1876 conf->redirects = ngx_array_create(cf->pool, 1,
1746 sizeof(ngx_http_proxy_redirect_t)); 1877 sizeof(ngx_http_proxy_redirect_t));
1747 if (conf->redirects == NULL) { 1878 if (conf->redirects == NULL) {
1748 return NGX_CONF_ERROR; 1879 return NGX_CONF_ERROR;
1752 if (pr == NULL) { 1883 if (pr == NULL) {
1753 return NGX_CONF_ERROR; 1884 return NGX_CONF_ERROR;
1754 } 1885 }
1755 1886
1756 pr->handler = ngx_http_proxy_rewrite_redirect_text; 1887 pr->handler = ngx_http_proxy_rewrite_redirect_text;
1757 pr->redirect = conf->upstream.url; 1888 pr->redirect = conf->url;
1758 1889
1759 if (conf->upstream.uri.len) { 1890 if (conf->vars.uri.len) {
1760 pr->replacement.text = conf->upstream.location; 1891 pr->replacement.text = conf->location;
1761 1892
1762 } else { 1893 } else {
1763 pr->replacement.text.len = 0; 1894 pr->replacement.text.len = 0;
1764 pr->replacement.text.data = NULL; 1895 pr->replacement.text.data = NULL;
1765 } 1896 }
1766 } 1897 }
1898 }
1899
1900 /* STUB */
1901 if (prev->proxy_lengths) {
1902 conf->proxy_lengths = prev->proxy_lengths;
1903 conf->proxy_values = prev->proxy_values;
1767 } 1904 }
1768 1905
1769 ngx_conf_merge_uint_value(conf->headers_hash_max_size, 1906 ngx_conf_merge_uint_value(conf->headers_hash_max_size,
1770 prev->headers_hash_max_size, 512); 1907 prev->headers_hash_max_size, 512);
1771 1908
1877 peers: 2014 peers:
1878 2015
1879 if (conf->upstream.upstream == NULL) { 2016 if (conf->upstream.upstream == NULL) {
1880 conf->upstream.upstream = prev->upstream.upstream; 2017 conf->upstream.upstream = prev->upstream.upstream;
1881 2018
1882 conf->host_header = prev->host_header; 2019 conf->vars = prev->vars;
1883 conf->port = prev->port;
1884 conf->upstream.schema = prev->upstream.schema; 2020 conf->upstream.schema = prev->upstream.schema;
1885 } 2021 }
1886 2022
1887 2023
1888 if (conf->body_source.data == NULL) { 2024 if (conf->body_source.data == NULL) {
2154 static char * 2290 static char *
2155 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 2291 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2156 { 2292 {
2157 ngx_http_proxy_loc_conf_t *plcf = conf; 2293 ngx_http_proxy_loc_conf_t *plcf = conf;
2158 2294
2159 u_char *p; 2295 size_t add;
2160 size_t add; 2296 u_short port;
2161 u_short port; 2297 ngx_str_t *value, *url;
2162 ngx_str_t *value, *url; 2298 ngx_url_t u;
2163 ngx_url_t u; 2299 ngx_uint_t n;
2164 ngx_http_core_loc_conf_t *clcf; 2300 ngx_http_core_loc_conf_t *clcf;
2165 #if (NGX_HTTP_SSL) 2301 ngx_http_script_compile_t sc;
2166 ngx_pool_cleanup_t *cln;
2167 #endif
2168 2302
2169 if (plcf->upstream.schema.len) { 2303 if (plcf->upstream.schema.len) {
2170 return "is duplicate"; 2304 return "is duplicate";
2171 } 2305 }
2172 2306
2307 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2308
2173 value = cf->args->elts; 2309 value = cf->args->elts;
2174 2310
2175 url = &value[1]; 2311 url = &value[1];
2312
2313 n = ngx_http_script_variables_count(url);
2314
2315 if (n) {
2316
2317 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2318
2319 sc.cf = cf;
2320 sc.source = url;
2321 sc.lengths = &plcf->proxy_lengths;
2322 sc.values = &plcf->proxy_values;
2323 sc.variables = n;
2324 sc.complete_lengths = 1;
2325 sc.complete_values = 1;
2326
2327 if (ngx_http_script_compile(&sc) != NGX_OK) {
2328 return NGX_CONF_ERROR;
2329 }
2330
2331 #if (NGX_HTTP_SSL)
2332 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
2333 return NGX_CONF_ERROR;
2334 }
2335 #endif
2336
2337 clcf->handler = ngx_http_proxy_handler;
2338
2339 return NGX_CONF_OK;
2340 }
2176 2341
2177 if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) { 2342 if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
2178 add = 7; 2343 add = 7;
2179 port = 80; 2344 port = 80;
2180 2345
2181 } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) { 2346 } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
2182 2347
2183 #if (NGX_HTTP_SSL) 2348 #if (NGX_HTTP_SSL)
2349 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
2350 return NGX_CONF_ERROR;
2351 }
2184 2352
2185 add = 8; 2353 add = 8;
2186 port = 443; 2354 port = 443;
2187
2188 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2189 if (plcf->upstream.ssl == NULL) {
2190 return NGX_CONF_ERROR;
2191 }
2192
2193 plcf->upstream.ssl->log = cf->log;
2194
2195 if (ngx_ssl_create(plcf->upstream.ssl,
2196 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
2197 != NGX_OK)
2198 {
2199 return NGX_CONF_ERROR;
2200 }
2201
2202 cln = ngx_pool_cleanup_add(cf->pool, 0);
2203 if (cln == NULL) {
2204 return NGX_CONF_ERROR;
2205 }
2206
2207 cln->handler = ngx_ssl_cleanup_ctx;
2208 cln->data = plcf->upstream.ssl;
2209
2210 #else 2355 #else
2211 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2356 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2212 "https protocol requires SSL support"); 2357 "https protocol requires SSL support");
2213 return NGX_CONF_ERROR; 2358 return NGX_CONF_ERROR;
2214 #endif 2359 #endif
2229 plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); 2374 plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
2230 if (plcf->upstream.upstream == NULL) { 2375 if (plcf->upstream.upstream == NULL) {
2231 return NGX_CONF_ERROR; 2376 return NGX_CONF_ERROR;
2232 } 2377 }
2233 2378
2234 if (!u.unix_socket) { 2379 if (ngx_http_proxy_set_vars(cf->pool, &u, &plcf->vars) != NGX_OK) {
2235 if (u.no_port || u.port == port) { 2380 return NGX_CONF_ERROR;
2236 plcf->host_header = u.host; 2381 }
2237
2238 if (port == 80) {
2239 plcf->port.len = sizeof("80") - 1;
2240 plcf->port.data = (u_char *) "80";
2241
2242 } else {
2243 plcf->port.len = sizeof("443") - 1;
2244 plcf->port.data = (u_char *) "443";
2245 }
2246
2247 } else {
2248 p = ngx_palloc(cf->pool, u.host.len + sizeof(":65536") - 1);
2249 if (p == NULL) {
2250 return NGX_CONF_ERROR;
2251 }
2252
2253 plcf->host_header.len = ngx_sprintf(p, "%V:%d", &u.host, u.port)
2254 - p;
2255 plcf->host_header.data = p;
2256
2257 plcf->port.len = plcf->host_header.len - u.host.len - 1;
2258 plcf->port.data = p + u.host.len + 1;
2259 }
2260
2261
2262 } else {
2263 plcf->host_header.len = sizeof("localhost") - 1;
2264 plcf->host_header.data = (u_char *) "localhost";
2265 plcf->port.len = 0;
2266 plcf->port.data = (u_char *) "";
2267 }
2268
2269 plcf->upstream.uri = u.uri;
2270 2382
2271 plcf->upstream.schema.len = add; 2383 plcf->upstream.schema.len = add;
2272 plcf->upstream.schema.data = url->data; 2384 plcf->upstream.schema.data = url->data;
2273 2385 plcf->location = clcf->name;
2274 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2275 2386
2276 clcf->handler = ngx_http_proxy_handler; 2387 clcf->handler = ngx_http_proxy_handler;
2277
2278 plcf->upstream.location = clcf->name;
2279 2388
2280 if (clcf->named 2389 if (clcf->named
2281 #if (NGX_PCRE) 2390 #if (NGX_PCRE)
2282 || clcf->regex 2391 || clcf->regex
2283 #endif 2392 #endif
2284 || clcf->noname) 2393 || clcf->noname)
2285 { 2394 {
2286 if (plcf->upstream.uri.len) { 2395 if (plcf->vars.uri.len) {
2287 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2396 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2288 "\"proxy_pass\" may not have URI part in " 2397 "\"proxy_pass\" may not have URI part in "
2289 "location given by regular expression, " 2398 "location given by regular expression, "
2290 "or inside named location, " 2399 "or inside named location, "
2291 "or inside the \"if\" statement, " 2400 "or inside the \"if\" statement, "
2292 "or inside the \"limit_except\" block"); 2401 "or inside the \"limit_except\" block");
2293 return NGX_CONF_ERROR; 2402 return NGX_CONF_ERROR;
2294 } 2403 }
2295 2404
2296 plcf->upstream.location.len = 0; 2405 plcf->location.len = 0;
2297 } 2406 }
2298 2407
2299 plcf->upstream.url = *url; 2408 plcf->url = *url;
2300 2409
2301 if (clcf->name.data[clcf->name.len - 1] == '/') { 2410 if (clcf->name.data[clcf->name.len - 1] == '/') {
2302 clcf->auto_redirect = 1; 2411 clcf->auto_redirect = 1;
2303 } 2412 }
2304 2413
2340 if (pr == NULL) { 2449 if (pr == NULL) {
2341 return NGX_CONF_ERROR; 2450 return NGX_CONF_ERROR;
2342 } 2451 }
2343 2452
2344 if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "default") == 0) { 2453 if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "default") == 0) {
2345 if (plcf->upstream.url.data == NULL) { 2454 if (plcf->url.data == NULL) {
2346 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2455 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2347 "\"proxy_rewrite_location default\" must go " 2456 "\"proxy_rewrite_location default\" must go "
2348 "after the \"proxy_pass\" directive"); 2457 "after the \"proxy_pass\" directive");
2349 return NGX_CONF_ERROR; 2458 return NGX_CONF_ERROR;
2350 } 2459 }
2351 2460
2352 pr->handler = ngx_http_proxy_rewrite_redirect_text; 2461 pr->handler = ngx_http_proxy_rewrite_redirect_text;
2353 pr->redirect = plcf->upstream.url; 2462 pr->redirect = plcf->url;
2354 2463
2355 if (plcf->upstream.uri.len) { 2464 if (plcf->vars.uri.len) {
2356 pr->replacement.text = plcf->upstream.location; 2465 pr->replacement.text = plcf->location;
2357 2466
2358 } else { 2467 } else {
2359 pr->replacement.text.len = 0; 2468 pr->replacement.text.len = 0;
2360 pr->replacement.text.data = NULL; 2469 pr->replacement.text.data = NULL;
2361 } 2470 }
2493 "use the \"fail_timeout\" parameter of the \"server\" directive ", 2602 "use the \"fail_timeout\" parameter of the \"server\" directive ",
2494 "inside the \"upstream\" block"); 2603 "inside the \"upstream\" block");
2495 2604
2496 return NGX_CONF_ERROR; 2605 return NGX_CONF_ERROR;
2497 } 2606 }
2607
2608
2609 #if (NGX_HTTP_SSL)
2610
2611 static ngx_int_t
2612 ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
2613 {
2614 ngx_pool_cleanup_t *cln;
2615
2616 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2617 if (plcf->upstream.ssl == NULL) {
2618 return NGX_ERROR;
2619 }
2620
2621 plcf->upstream.ssl->log = cf->log;
2622
2623 if (ngx_ssl_create(plcf->upstream.ssl,
2624 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
2625 != NGX_OK)
2626 {
2627 return NGX_ERROR;
2628 }
2629
2630 cln = ngx_pool_cleanup_add(cf->pool, 0);
2631 if (cln == NULL) {
2632 return NGX_ERROR;
2633 }
2634
2635 cln->handler = ngx_ssl_cleanup_ctx;
2636 cln->data = plcf->upstream.ssl;
2637
2638 return NGX_OK;
2639 }
2640
2641 #endif
2642
2643
2644 static ngx_int_t
2645 ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
2646 ngx_http_proxy_vars_t *v)
2647 {
2648 u_char *p;
2649
2650 if (!u->unix_socket) {
2651 if (u->no_port || u->port == u->default_port) {
2652 v->host_header = u->host;
2653
2654 if (u->default_port == 80) {
2655 v->port.len = sizeof("80") - 1;
2656 v->port.data = (u_char *) "80";
2657
2658 } else {
2659 v->port.len = sizeof("443") - 1;
2660 v->port.data = (u_char *) "443";
2661 }
2662
2663 } else {
2664 p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
2665 if (p == NULL) {
2666 return NGX_ERROR;
2667 }
2668
2669 v->host_header.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
2670 v->host_header.data = p;
2671
2672 v->port.len = v->host_header.len - u->host.len - 1;
2673 v->port.data = p + u->host.len + 1;
2674 }
2675
2676 } else {
2677 v->host_header.len = sizeof("localhost") - 1;
2678 v->host_header.data = (u_char *) "localhost";
2679 v->port.len = 0;
2680 v->port.data = (u_char *) "";
2681 }
2682
2683 v->uri = u->uri;
2684
2685 return NGX_OK;
2686 }