Mercurial > hg > nginx
comparison src/http/modules/ngx_http_proxy_module.c @ 509:9b8c906f6e63 release-0.1.29
nginx-0.1.29-RELEASE import
*) Feature: the ngx_http_ssi_module supports "include virtual" command.
*) Feature: the ngx_http_ssi_module supports the condition command like
'if expr="$NAME"' and "else" and "endif" commands. Only one nested
level is supported.
*) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and
DATE_GMT variables and "config timefmt" command.
*) Feature: the "ssi_ignore_recycled_buffers" directive.
*) Bugfix: the "echo" command did not show the default value for the
empty QUERY_STRING variable.
*) Change: the ngx_http_proxy_module was rewritten.
*) Feature: the "proxy_redirect", "proxy_pass_request_headers",
"proxy_pass_request_body", and "proxy_method" directives.
*) Feature: the "proxy_set_header" directive. The "proxy_x_var" was
canceled and must be replaced with the proxy_set_header directive.
*) Change: the "proxy_preserve_host" is canceled and must be replaced
with the "proxy_set_header Host $host" and the "proxy_redirect off"
directives, the "proxy_set_header Host $host:$proxy_port" directive
and the appropriate proxy_redirect directives.
*) Change: the "proxy_set_x_real_ip" is canceled and must be replaced
with the "proxy_set_header X-Real-IP $remote_addr" directive.
*) Change: the "proxy_add_x_forwarded_for" is canceled and must be
replaced with
the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for"
directive.
*) Change: the "proxy_set_x_url" is canceled and must be replaced with
the "proxy_set_header X-URL http://$host:$server_port$request_uri"
directive.
*) Feature: the "fastcgi_param" directive.
*) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params"
directive are canceled and must be replaced with the fastcgi_param
directives.
*) Feature: the "index" directive can use the variables.
*) Feature: the "index" directive can be used at http and server levels.
*) Change: the last index only in the "index" directive can be absolute.
*) Feature: the "rewrite" directive can use the variables.
*) Feature: the "internal" directive.
*) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables.
*) Change: nginx now passes the invalid lines in a client request
headers or a backend response header.
*) Bugfix: if the backend did not transfer response for a long time and
the "send_timeout" was less than "proxy_read_timeout", then nginx
returned the 408 response.
*) Bugfix: the segmentation fault was occurred if the backend sent an
invalid line in response header; the bug had appeared in 0.1.26.
*) Bugfix: the segmentation fault may occurred in FastCGI fault
tolerance configuration.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" and "Cache-Control" headers.
*) Bugfix: nginx did not take into account trailing dot in "Host"
header line.
*) Bugfix: the ngx_http_auth_module did not work under Linux.
*) Bugfix: the rewrite directive worked incorrectly, if the arguments
were in a request.
*) Bugfix: nginx could not be built on MacOS X.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 12 May 2005 14:58:06 +0000 |
parents | cd3117ad9aab |
children | 417a087c9c4d |
comparison
equal
deleted
inserted
replaced
508:ca1020ce99ba | 509:9b8c906f6e63 |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_event.h> | 9 #include <ngx_event.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | 11 |
12 | 12 |
13 typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t; | |
14 | |
15 typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r, | |
16 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr); | |
17 | |
18 struct ngx_http_proxy_redirect_s { | |
19 ngx_http_proxy_redirect_pt handler; | |
20 ngx_str_t redirect; | |
21 | |
22 union { | |
23 ngx_str_t text; | |
24 | |
25 struct { | |
26 void *lengths; | |
27 void *values; | |
28 } vars; | |
29 | |
30 void *regex; | |
31 } replacement; | |
32 }; | |
33 | |
34 | |
13 typedef struct { | 35 typedef struct { |
14 ngx_http_upstream_conf_t upstream; | 36 ngx_http_upstream_conf_t upstream; |
15 | 37 |
16 ngx_peers_t *peers; | 38 ngx_peers_t *peers; |
17 | 39 |
18 ngx_array_t *headers_set_len; | 40 ngx_array_t *headers_set_len; |
19 ngx_array_t *headers_set; | 41 ngx_array_t *headers_set; |
20 ngx_hash_t *headers_set_hash; | 42 ngx_hash_t *headers_set_hash; |
21 | 43 |
22 ngx_flag_t preserve_host; | 44 ngx_array_t *headers_source; |
23 ngx_flag_t set_x_url; | 45 ngx_array_t *headers_names; |
24 ngx_flag_t set_x_real_ip; | 46 |
25 ngx_flag_t add_x_forwarded_for; | 47 ngx_array_t *redirects; |
26 ngx_flag_t pass_server; | 48 |
27 ngx_flag_t pass_x_accel_expires; | 49 ngx_str_t host_header; |
28 | 50 ngx_str_t port_text; |
29 ngx_str_t *location0; | 51 |
30 | 52 ngx_flag_t redirect; |
31 ngx_str_t host_header; | |
32 ngx_str_t uri0; | |
33 | |
34 ngx_array_t *headers_sources; | |
35 ngx_array_t *headers_names; | |
36 } ngx_http_proxy_loc_conf_t; | 53 } ngx_http_proxy_loc_conf_t; |
37 | 54 |
38 | 55 |
39 typedef struct { | 56 typedef struct { |
40 ngx_list_t headers; | 57 ngx_uint_t status; |
41 | 58 ngx_uint_t status_count; |
42 ngx_table_elt_t *date; | 59 u_char *status_start; |
43 ngx_table_elt_t *server; | 60 u_char *status_end; |
44 | 61 } ngx_http_proxy_ctx_t; |
45 ngx_table_elt_t *expires; | 62 |
46 ngx_table_elt_t *cache_control; | 63 |
47 ngx_table_elt_t *etag; | 64 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 |
48 ngx_table_elt_t *x_accel_expires; | |
49 | |
50 ngx_table_elt_t *connection; | |
51 ngx_table_elt_t *content_type; | |
52 ngx_table_elt_t *content_length; | |
53 | |
54 #if (NGX_HTTP_GZIP) | |
55 ngx_table_elt_t *content_encoding; | |
56 #endif | |
57 | |
58 ngx_table_elt_t *last_modified; | |
59 ngx_table_elt_t *location; | |
60 ngx_table_elt_t *accept_ranges; | |
61 ngx_table_elt_t *x_pad; | |
62 | |
63 off_t content_length_n; | |
64 } ngx_http_proxy_headers_in_t; | |
65 | 65 |
66 | 66 |
67 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); | 67 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); |
68 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); | 68 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); |
69 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r); | |
70 static ngx_int_t ngx_http_proxy_parse_status_line(ngx_http_request_t *r, | |
71 ngx_http_proxy_ctx_t *p); | |
69 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); | 72 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); |
70 static ngx_int_t ngx_http_proxy_send_header(ngx_http_request_t *r); | |
71 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); | 73 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); |
72 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, | 74 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, |
73 ngx_int_t rc); | 75 ngx_int_t rc); |
74 | 76 |
75 static ngx_int_t ngx_http_proxy_compile_header_start(ngx_table_elt_t *h, | 77 static ngx_http_variable_value_t * |
76 ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value); | 78 ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data); |
77 static ngx_int_t ngx_http_proxy_compile_header_end(ngx_array_t *lengths, | 79 static ngx_http_variable_value_t * |
78 ngx_array_t *values); | 80 ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data); |
79 | 81 static ngx_http_variable_value_t * |
80 static ngx_int_t ngx_http_proxy_init(ngx_cycle_t *cycle); | 82 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, |
81 static ngx_http_variable_value_t *ngx_http_proxy_host_variable | 83 uintptr_t data); |
82 (ngx_http_request_t *r, uintptr_t data); | 84 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, |
85 ngx_table_elt_t *h, size_t prefix); | |
86 | |
87 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); | |
83 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); | 88 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); |
84 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, | 89 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, |
85 void *parent, void *child); | 90 void *parent, void *child); |
86 | 91 |
87 static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 92 static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
88 void *conf); | 93 void *conf); |
89 | 94 static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, |
90 static char *ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd, | |
91 void *conf); | 95 void *conf); |
96 | |
92 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); | 97 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); |
93 | 98 |
99 | |
94 static ngx_conf_post_t ngx_http_proxy_lowat_post = | 100 static ngx_conf_post_t ngx_http_proxy_lowat_post = |
95 { ngx_http_proxy_lowat_check }; | 101 { ngx_http_proxy_lowat_check }; |
102 | |
103 static ngx_conf_enum_t ngx_http_proxy_set_methods[] = { | |
104 { ngx_string("get"), NGX_HTTP_GET }, | |
105 { ngx_null_string, 0 } | |
106 }; | |
96 | 107 |
97 static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { | 108 static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { |
98 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, | 109 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, |
99 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, | 110 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, |
100 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, | 111 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, |
111 ngx_http_proxy_pass, | 122 ngx_http_proxy_pass, |
112 NGX_HTTP_LOC_CONF_OFFSET, | 123 NGX_HTTP_LOC_CONF_OFFSET, |
113 0, | 124 0, |
114 NULL }, | 125 NULL }, |
115 | 126 |
127 { ngx_string("proxy_redirect"), | |
128 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, | |
129 ngx_http_proxy_redirect, | |
130 NGX_HTTP_LOC_CONF_OFFSET, | |
131 0, | |
132 NULL }, | |
133 | |
116 { ngx_string("proxy_connect_timeout"), | 134 { ngx_string("proxy_connect_timeout"), |
117 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 135 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
118 ngx_conf_set_msec_slot, | 136 ngx_conf_set_msec_slot, |
119 NGX_HTTP_LOC_CONF_OFFSET, | 137 NGX_HTTP_LOC_CONF_OFFSET, |
120 offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout), | 138 offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout), |
132 ngx_conf_set_size_slot, | 150 ngx_conf_set_size_slot, |
133 NGX_HTTP_LOC_CONF_OFFSET, | 151 NGX_HTTP_LOC_CONF_OFFSET, |
134 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat), | 152 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat), |
135 &ngx_http_proxy_lowat_post }, | 153 &ngx_http_proxy_lowat_post }, |
136 | 154 |
155 { ngx_string("proxy_redirect_errors"), | |
156 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
157 ngx_conf_set_flag_slot, | |
158 NGX_HTTP_LOC_CONF_OFFSET, | |
159 offsetof(ngx_http_proxy_loc_conf_t, upstream.redirect_errors), | |
160 NULL }, | |
161 | |
137 { ngx_string("proxy_pass_unparsed_uri"), | 162 { ngx_string("proxy_pass_unparsed_uri"), |
138 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 163 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
139 ngx_conf_set_flag_slot, | 164 ngx_conf_set_flag_slot, |
140 NGX_HTTP_LOC_CONF_OFFSET, | 165 NGX_HTTP_LOC_CONF_OFFSET, |
141 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_unparsed_uri), | 166 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_unparsed_uri), |
142 NULL }, | 167 NULL }, |
143 | 168 |
144 { ngx_string("proxy_preserve_host"), | 169 { ngx_string("proxy_set_header"), |
170 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
171 ngx_conf_set_table_elt_slot, | |
172 NGX_HTTP_LOC_CONF_OFFSET, | |
173 offsetof(ngx_http_proxy_loc_conf_t, headers_source), | |
174 NULL }, | |
175 | |
176 { ngx_string("proxy_method"), | |
177 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
178 ngx_conf_set_enum_slot, | |
179 NGX_HTTP_LOC_CONF_OFFSET, | |
180 offsetof(ngx_http_proxy_loc_conf_t, upstream.method), | |
181 ngx_http_proxy_set_methods }, | |
182 | |
183 { ngx_string("proxy_pass_request_headers"), | |
145 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 184 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
146 ngx_conf_set_flag_slot, | 185 ngx_conf_set_flag_slot, |
147 NGX_HTTP_LOC_CONF_OFFSET, | 186 NGX_HTTP_LOC_CONF_OFFSET, |
148 offsetof(ngx_http_proxy_loc_conf_t, preserve_host), | 187 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers), |
149 NULL }, | 188 NULL }, |
150 | 189 |
151 { ngx_string("proxy_set_x_url"), | 190 { ngx_string("proxy_pass_request_body"), |
152 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 191 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
153 ngx_conf_set_flag_slot, | 192 ngx_conf_set_flag_slot, |
154 NGX_HTTP_LOC_CONF_OFFSET, | 193 NGX_HTTP_LOC_CONF_OFFSET, |
155 offsetof(ngx_http_proxy_loc_conf_t, set_x_url), | 194 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body), |
156 NULL }, | |
157 | |
158 { ngx_string("proxy_set_x_real_ip"), | |
159 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
160 ngx_conf_set_flag_slot, | |
161 NGX_HTTP_LOC_CONF_OFFSET, | |
162 offsetof(ngx_http_proxy_loc_conf_t, set_x_real_ip), | |
163 NULL }, | |
164 | |
165 { ngx_string("proxy_set_x_var"), | |
166 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
167 ngx_http_proxy_set_x_var, | |
168 NGX_HTTP_LOC_CONF_OFFSET, | |
169 0, | |
170 NULL }, | |
171 | |
172 { ngx_string("proxy_add_x_forwarded_for"), | |
173 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
174 ngx_conf_set_flag_slot, | |
175 NGX_HTTP_LOC_CONF_OFFSET, | |
176 offsetof(ngx_http_proxy_loc_conf_t, add_x_forwarded_for), | |
177 NULL }, | 195 NULL }, |
178 | 196 |
179 { ngx_string("proxy_header_buffer_size"), | 197 { ngx_string("proxy_header_buffer_size"), |
180 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 198 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
181 ngx_conf_set_size_slot, | 199 ngx_conf_set_size_slot, |
230 ngx_conf_set_bitmask_slot, | 248 ngx_conf_set_bitmask_slot, |
231 NGX_HTTP_LOC_CONF_OFFSET, | 249 NGX_HTTP_LOC_CONF_OFFSET, |
232 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), | 250 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), |
233 &ngx_http_proxy_next_upstream_masks }, | 251 &ngx_http_proxy_next_upstream_masks }, |
234 | 252 |
253 { ngx_string("proxy_pass_x_powered_by"), | |
254 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
255 ngx_conf_set_flag_slot, | |
256 NGX_HTTP_LOC_CONF_OFFSET, | |
257 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_x_powered_by), | |
258 NULL }, | |
259 | |
235 { ngx_string("proxy_pass_server"), | 260 { ngx_string("proxy_pass_server"), |
236 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 261 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
237 ngx_conf_set_flag_slot, | 262 ngx_conf_set_flag_slot, |
238 NGX_HTTP_LOC_CONF_OFFSET, | 263 NGX_HTTP_LOC_CONF_OFFSET, |
239 offsetof(ngx_http_proxy_loc_conf_t, pass_server), | 264 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_server), |
240 NULL }, | 265 NULL }, |
241 | 266 |
242 { ngx_string("proxy_pass_x_accel_expires"), | 267 { ngx_string("proxy_pass_x_accel_expires"), |
243 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 268 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
244 ngx_conf_set_flag_slot, | 269 ngx_conf_set_flag_slot, |
245 NGX_HTTP_LOC_CONF_OFFSET, | 270 NGX_HTTP_LOC_CONF_OFFSET, |
246 offsetof(ngx_http_proxy_loc_conf_t, pass_x_accel_expires), | 271 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_x_accel_expires), |
247 NULL }, | 272 NULL }, |
248 | 273 |
249 ngx_null_command | 274 ngx_null_command |
250 }; | 275 }; |
251 | 276 |
252 | 277 |
253 ngx_http_module_t ngx_http_proxy_module_ctx = { | 278 ngx_http_module_t ngx_http_proxy_module_ctx = { |
254 NULL, /* pre conf */ | 279 ngx_http_proxy_add_variables, /* preconfiguration */ |
280 NULL, /* postconfiguration */ | |
255 | 281 |
256 NULL, /* create main configuration */ | 282 NULL, /* create main configuration */ |
257 NULL, /* init main configuration */ | 283 NULL, /* init main configuration */ |
258 | 284 |
259 NULL, /* create server configuration */ | 285 NULL, /* create server configuration */ |
263 ngx_http_proxy_merge_loc_conf /* merge location configration */ | 289 ngx_http_proxy_merge_loc_conf /* merge location configration */ |
264 }; | 290 }; |
265 | 291 |
266 | 292 |
267 ngx_module_t ngx_http_proxy_module = { | 293 ngx_module_t ngx_http_proxy_module = { |
268 NGX_MODULE, | 294 NGX_MODULE_V1, |
269 &ngx_http_proxy_module_ctx, /* module context */ | 295 &ngx_http_proxy_module_ctx, /* module context */ |
270 ngx_http_proxy_commands, /* module directives */ | 296 ngx_http_proxy_commands, /* module directives */ |
271 NGX_HTTP_MODULE, /* module type */ | 297 NGX_HTTP_MODULE, /* module type */ |
272 ngx_http_proxy_init, /* init module */ | 298 NULL, /* init module */ |
273 NULL /* init process */ | 299 NULL /* init process */ |
274 }; | 300 }; |
275 | 301 |
276 | 302 |
277 static ngx_str_t ngx_http_proxy_methods[] = { | 303 static ngx_str_t ngx_http_proxy_methods[] = { |
278 ngx_string("GET"), | 304 ngx_string("GET "), |
279 ngx_string("HEAD"), | 305 ngx_string("HEAD "), |
280 ngx_string("POST") | 306 ngx_string("POST ") |
281 }; | 307 }; |
282 | 308 |
283 | 309 |
284 static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF; | 310 static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF; |
285 | 311 |
286 static ngx_str_t ngx_http_proxy_host = ngx_string("PROXY_HOST"); | 312 |
313 static ngx_table_elt_t ngx_http_proxy_headers[] = { | |
314 { 0, ngx_string("Host"), ngx_string("$proxy_host"), }, | |
315 { 0, ngx_string("Connection"), ngx_string("close"), }, | |
316 { 0, ngx_null_string, ngx_null_string } | |
317 }; | |
318 | |
319 | |
320 static ngx_http_variable_t ngx_http_proxy_vars[] = { | |
321 | |
322 { ngx_string("proxy_host"), ngx_http_proxy_host_variable, 0, | |
323 NGX_HTTP_VAR_CHANGABLE }, | |
324 | |
325 { ngx_string("proxy_port"), ngx_http_proxy_port_variable, 0, | |
326 NGX_HTTP_VAR_CHANGABLE }, | |
327 | |
328 { ngx_string("proxy_add_x_forwarded_for"), | |
329 ngx_http_proxy_add_x_forwarded_for_variable, 0, 0 }, | |
330 | |
331 #if 0 | |
332 { ngx_string("proxy_add_via"), NULL, 0, 0 }, | |
333 #endif | |
334 | |
335 { ngx_null_string, NULL, 0, 0 } | |
336 }; | |
287 | 337 |
288 | 338 |
289 #if (NGX_PCRE) | 339 #if (NGX_PCRE) |
290 static ngx_str_t ngx_http_proxy_uri = ngx_string("/"); | 340 static ngx_str_t ngx_http_proxy_uri = ngx_string("/"); |
291 #endif | |
292 | |
293 | |
294 #if 0 | |
295 | |
296 ngx_http_header_t ngx_http_proxy_headers_in[] = { | |
297 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, | |
298 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, | |
299 | |
300 { ngx_string("Expires"), offsetof(ngx_http_proxy_headers_in_t, expires) }, | |
301 { ngx_string("Cache-Control"), | |
302 offsetof(ngx_http_proxy_headers_in_t, cache_control) }, | |
303 { ngx_string("ETag"), offsetof(ngx_http_proxy_headers_in_t, etag) }, | |
304 { ngx_string("X-Accel-Expires"), | |
305 offsetof(ngx_http_proxy_headers_in_t, x_accel_expires) }, | |
306 | |
307 { ngx_string("Connection"), | |
308 offsetof(ngx_http_proxy_headers_in_t, connection) }, | |
309 { ngx_string("Content-Type"), | |
310 offsetof(ngx_http_proxy_headers_in_t, content_type) }, | |
311 { ngx_string("Content-Length"), | |
312 offsetof(ngx_http_proxy_headers_in_t, content_length) }, | |
313 | |
314 #if (NGX_HTTP_GZIP) | |
315 { ngx_string("Content-Encoding"), | |
316 offsetof(ngx_http_proxy_headers_in_t, content_encoding) }, | |
317 #endif | |
318 | |
319 { ngx_string("Last-Modified"), | |
320 offsetof(ngx_http_proxy_headers_in_t, last_modified) }, | |
321 { ngx_string("Location"), | |
322 offsetof(ngx_http_proxy_headers_in_t, location) }, | |
323 { ngx_string("Accept-Ranges"), | |
324 offsetof(ngx_http_proxy_headers_in_t, accept_ranges) }, | |
325 { ngx_string("X-Pad"), offsetof(ngx_http_proxy_headers_in_t, x_pad) }, | |
326 | |
327 { ngx_null_string, 0 } | |
328 }; | |
329 | |
330 #endif | 341 #endif |
331 | 342 |
332 | 343 |
333 static ngx_int_t | 344 static ngx_int_t |
334 ngx_http_proxy_handler(ngx_http_request_t *r) | 345 ngx_http_proxy_handler(ngx_http_request_t *r) |
356 | 367 |
357 u->conf = &plcf->upstream; | 368 u->conf = &plcf->upstream; |
358 | 369 |
359 u->create_request = ngx_http_proxy_create_request; | 370 u->create_request = ngx_http_proxy_create_request; |
360 u->reinit_request = ngx_http_proxy_reinit_request; | 371 u->reinit_request = ngx_http_proxy_reinit_request; |
361 u->process_header = ngx_http_proxy_process_header; | 372 u->process_header = ngx_http_proxy_process_status_line; |
362 u->send_header = ngx_http_proxy_send_header; | |
363 u->abort_request = ngx_http_proxy_abort_request; | 373 u->abort_request = ngx_http_proxy_abort_request; |
364 u->finalize_request = ngx_http_proxy_finalize_request; | 374 u->finalize_request = ngx_http_proxy_finalize_request; |
365 | 375 |
376 if (plcf->redirects) { | |
377 u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; | |
378 } | |
379 | |
366 u->pipe.input_filter = ngx_event_pipe_copy_input_filter; | 380 u->pipe.input_filter = ngx_event_pipe_copy_input_filter; |
367 | 381 |
368 u->log_ctx = r->connection->log->data; | 382 u->accel = 1; |
369 u->log_handler = ngx_http_upstream_log_error; | |
370 | |
371 u->schema0.len = sizeof("http://") - 1; | |
372 u->schema0.data = (u_char *) "http://"; | |
373 u->uri0 = plcf->uri0; | |
374 u->location0 = plcf->location0; | |
375 | 383 |
376 r->upstream = u; | 384 r->upstream = u; |
377 | 385 |
378 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); | 386 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); |
379 | 387 |
386 | 394 |
387 | 395 |
388 static ngx_int_t | 396 static ngx_int_t |
389 ngx_http_proxy_create_request(ngx_http_request_t *r) | 397 ngx_http_proxy_create_request(ngx_http_request_t *r) |
390 { | 398 { |
391 size_t len; | 399 size_t len, loc_len; |
392 ngx_uint_t i, key; | 400 ngx_uint_t i, key; |
393 uintptr_t escape; | 401 uintptr_t escape; |
394 ngx_buf_t *b; | 402 ngx_buf_t *b; |
395 ngx_str_t *hh; | 403 ngx_str_t *hh; |
396 ngx_chain_t *cl; | 404 ngx_chain_t *cl, *body; |
397 ngx_list_part_t *part; | 405 ngx_list_part_t *part; |
398 ngx_table_elt_t *header; | 406 ngx_table_elt_t *header; |
399 ngx_http_upstream_t *u; | 407 ngx_http_upstream_t *u; |
400 ngx_http_proxy_loc_conf_t *plcf; | 408 ngx_http_script_code_pt code; |
401 ngx_http_script_code_pt code; | 409 ngx_http_script_engine_t e, le; |
402 ngx_http_script_len_code_pt lcode; | 410 ngx_http_proxy_loc_conf_t *plcf; |
403 ngx_http_script_lite_engine_t e; | 411 ngx_http_script_len_code_pt lcode; |
404 | 412 |
405 u = r->upstream; | 413 u = r->upstream; |
406 | 414 |
407 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 415 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
408 | 416 |
409 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; | 417 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; |
410 | 418 |
411 if (u->method) { | 419 if (u->method) { |
412 len += ngx_http_proxy_methods[u->method - 1].len + u->uri0.len; | 420 len += ngx_http_proxy_methods[u->method - 1].len + u->conf->uri.len; |
413 } else { | 421 } else { |
414 len += r->method_name.len + u->uri0.len; | 422 len += r->method_name.len + 1 + u->conf->uri.len; |
415 } | 423 } |
416 | 424 |
417 escape = 0; | 425 escape = 0; |
418 | 426 |
427 loc_len = r->valid_location ? u->conf->location->len : 1; | |
428 | |
419 if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) { | 429 if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) { |
420 len += r->unparsed_uri.len - 1; | 430 len += r->unparsed_uri.len - 1; |
421 | 431 |
422 } else { | 432 } else { |
423 if (r->quoted_uri) { | 433 if (r->quoted_uri) { |
424 escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len, | 434 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, |
425 r->uri.len - u->location0->len, | 435 r->uri.len - loc_len, NGX_ESCAPE_URI); |
426 NGX_ESCAPE_URI); | 436 } |
427 } | 437 |
428 | 438 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len; |
429 len += r->uri.len - u->location0->len + escape | 439 } |
430 + sizeof("?") - 1 + r->args.len; | 440 |
431 } | 441 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); |
432 | 442 |
433 | 443 le.ip = plcf->headers_set_len->elts; |
434 e.ip = plcf->headers_set_len->elts; | 444 le.request = r; |
435 e.request = r; | 445 |
436 | 446 while (*(uintptr_t *) le.ip) { |
437 while (*(uintptr_t *) e.ip) { | 447 while (*(uintptr_t *) le.ip) { |
438 lcode = *(ngx_http_script_len_code_pt *) e.ip; | 448 lcode = *(ngx_http_script_len_code_pt *) le.ip; |
439 len += lcode(&e); | 449 len += lcode(&le); |
440 } | 450 } |
441 | 451 le.ip += sizeof(uintptr_t); |
442 | 452 } |
443 part = &r->headers_in.headers.part; | 453 |
444 header = part->elts; | 454 |
445 hh = (ngx_str_t *) plcf->headers_set_hash->buckets; | 455 hh = (ngx_str_t *) plcf->headers_set_hash->buckets; |
446 | 456 |
447 for (i = 0; /* void */; i++) { | 457 if (plcf->upstream.pass_request_headers) { |
448 | 458 part = &r->headers_in.headers.part; |
449 if (i >= part->nelts) { | 459 header = part->elts; |
450 if (part->next == NULL) { | 460 |
451 break; | 461 for (i = 0; /* void */; i++) { |
452 } | 462 |
453 | 463 if (i >= part->nelts) { |
454 part = part->next; | 464 if (part->next == NULL) { |
455 header = part->elts; | 465 break; |
456 i = 0; | 466 } |
457 } | 467 |
458 | 468 part = part->next; |
459 key = header[i].hash % plcf->headers_set_hash->hash_size; | 469 header = part->elts; |
460 | 470 i = 0; |
461 if (hh[key].len == header[i].key.len | 471 } |
462 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0) | 472 |
463 { | 473 key = header[i].hash % plcf->headers_set_hash->hash_size; |
464 continue; | 474 |
465 } | 475 if (hh[key].len == header[i].key.len |
466 | 476 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0) |
467 len += header[i].key.len + sizeof(": ") - 1 | 477 { |
468 + header[i].value.len + sizeof(CRLF) - 1; | 478 continue; |
469 } | 479 } |
480 | |
481 len += header[i].key.len + sizeof(": ") - 1 | |
482 + header[i].value.len + sizeof(CRLF) - 1; | |
483 } | |
484 } | |
485 | |
470 | 486 |
471 b = ngx_create_temp_buf(r->pool, len); | 487 b = ngx_create_temp_buf(r->pool, len); |
472 if (b == NULL) { | 488 if (b == NULL) { |
473 return NGX_ERROR; | 489 return NGX_ERROR; |
474 } | 490 } |
477 if (cl == NULL) { | 493 if (cl == NULL) { |
478 return NGX_ERROR; | 494 return NGX_ERROR; |
479 } | 495 } |
480 | 496 |
481 cl->buf = b; | 497 cl->buf = b; |
482 cl->next = NULL; | |
483 | |
484 r->request_body->bufs = cl; | |
485 | 498 |
486 | 499 |
487 /* the request line */ | 500 /* the request line */ |
488 | 501 |
489 if (u->method) { | 502 if (u->method) { |
490 b->last = ngx_cpymem(b->last, | 503 b->last = ngx_cpymem(b->last, |
491 ngx_http_proxy_methods[u->method - 1].data, | 504 ngx_http_proxy_methods[u->method - 1].data, |
492 ngx_http_proxy_methods[u->method - 1].len); | 505 ngx_http_proxy_methods[u->method - 1].len); |
493 } else { | 506 } else { |
494 b->last = ngx_cpymem(b->last, r->method_name.data, r->method_name.len); | 507 b->last = ngx_cpymem(b->last, r->method_name.data, |
495 } | 508 r->method_name.len + 1); |
496 | 509 } |
497 b->last = ngx_cpymem(b->last, u->uri0.data, u->uri0.len); | 510 |
511 b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len); | |
498 | 512 |
499 if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) { | 513 if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) { |
500 b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1, | 514 b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1, |
501 r->unparsed_uri.len - 1); | 515 r->unparsed_uri.len - 1); |
502 } else { | 516 } else { |
503 if (escape) { | 517 if (escape) { |
504 ngx_escape_uri(b->last, r->uri.data + u->location0->len, | 518 ngx_escape_uri(b->last, r->uri.data + loc_len, |
505 r->uri.len - u->location0->len, NGX_ESCAPE_URI); | 519 r->uri.len - loc_len, NGX_ESCAPE_URI); |
506 b->last += r->uri.len - u->location0->len + escape; | 520 b->last += r->uri.len - loc_len + escape; |
507 | 521 |
508 } else { | 522 } else { |
509 b->last = ngx_cpymem(b->last, r->uri.data + u->location0->len, | 523 b->last = ngx_cpymem(b->last, r->uri.data + loc_len, |
510 r->uri.len - u->location0->len); | 524 r->uri.len - loc_len); |
511 } | 525 } |
512 | 526 |
513 if (r->args.len > 0) { | 527 if (r->args.len > 0) { |
514 *b->last++ = '?'; | 528 *b->last++ = '?'; |
515 b->last = ngx_cpymem(b->last, r->args.data, r->args.len); | 529 b->last = ngx_cpymem(b->last, r->args.data, r->args.len); |
520 sizeof(ngx_http_proxy_version) - 1); | 534 sizeof(ngx_http_proxy_version) - 1); |
521 | 535 |
522 | 536 |
523 e.ip = plcf->headers_set->elts; | 537 e.ip = plcf->headers_set->elts; |
524 e.pos = b->last; | 538 e.pos = b->last; |
525 | 539 e.request = r; |
526 while (*(uintptr_t *) e.ip) { | 540 |
527 code = *(ngx_http_script_code_pt *) e.ip; | 541 le.ip = plcf->headers_set_len->elts; |
528 code((ngx_http_script_engine_t *) &e); | 542 |
543 while (*(uintptr_t *) le.ip) { | |
544 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
545 lcode(&le); | |
546 | |
547 if (*(ngx_http_script_len_code_pt *) le.ip) { | |
548 | |
549 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { | |
550 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
551 } | |
552 | |
553 e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0; | |
554 | |
555 } else { | |
556 e.skip = 0; | |
557 } | |
558 | |
559 le.ip += sizeof(uintptr_t); | |
560 | |
561 while (*(uintptr_t *) e.ip) { | |
562 code = *(ngx_http_script_code_pt *) e.ip; | |
563 code((ngx_http_script_engine_t *) &e); | |
564 } | |
565 e.ip += sizeof(uintptr_t); | |
529 } | 566 } |
530 | 567 |
531 b->last = e.pos; | 568 b->last = e.pos; |
532 | 569 |
533 | 570 |
534 part = &r->headers_in.headers.part; | 571 if (plcf->upstream.pass_request_headers) { |
535 header = part->elts; | 572 part = &r->headers_in.headers.part; |
573 header = part->elts; | |
536 | 574 |
537 for (i = 0; /* void */; i++) { | 575 for (i = 0; /* void */; i++) { |
538 | 576 |
539 if (i >= part->nelts) { | 577 if (i >= part->nelts) { |
540 if (part->next == NULL) { | 578 if (part->next == NULL) { |
541 break; | 579 break; |
542 } | 580 } |
543 | 581 |
544 part = part->next; | 582 part = part->next; |
545 header = part->elts; | 583 header = part->elts; |
546 i = 0; | 584 i = 0; |
547 } | 585 } |
548 | 586 |
549 key = header[i].hash % plcf->headers_set_hash->hash_size; | 587 key = header[i].hash % plcf->headers_set_hash->hash_size; |
550 | 588 |
551 if (hh[key].len == header[i].key.len | 589 if (hh[key].len == header[i].key.len |
552 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0) | 590 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0) |
553 { | 591 { |
554 continue; | 592 continue; |
555 } | 593 } |
556 | 594 |
557 b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len); | 595 b->last = ngx_cpymem(b->last, header[i].key.data, |
558 | 596 header[i].key.len); |
559 *b->last++ = ':'; *b->last++ = ' '; | 597 |
560 | 598 *b->last++ = ':'; *b->last++ = ' '; |
561 b->last = ngx_cpymem(b->last, header[i].value.data, | 599 |
562 header[i].value.len); | 600 b->last = ngx_cpymem(b->last, header[i].value.data, |
563 | 601 header[i].value.len); |
564 *b->last++ = CR; *b->last++ = LF; | 602 |
565 | 603 *b->last++ = CR; *b->last++ = LF; |
566 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 604 |
567 "http proxy header: \"%V: %V\"", | 605 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
568 &header[i].key, &header[i].value); | 606 "http proxy header: \"%V: %V\"", |
607 &header[i].key, &header[i].value); | |
608 } | |
569 } | 609 } |
570 | 610 |
571 /* add "\r\n" at the header end */ | 611 /* add "\r\n" at the header end */ |
572 *b->last++ = CR; *b->last++ = LF; | 612 *b->last++ = CR; *b->last++ = LF; |
573 | 613 |
580 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 620 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
581 "http proxy header:\n\"%V\"", &s); | 621 "http proxy header:\n\"%V\"", &s); |
582 } | 622 } |
583 #endif | 623 #endif |
584 | 624 |
625 if (plcf->upstream.pass_request_body) { | |
626 | |
627 body = u->request_bufs; | |
628 u->request_bufs = cl; | |
629 | |
630 while (body) { | |
631 b = ngx_alloc_buf(r->pool); | |
632 if (b == NULL) { | |
633 return NGX_ERROR; | |
634 } | |
635 | |
636 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); | |
637 | |
638 cl->next = ngx_alloc_chain_link(r->pool); | |
639 if (cl->next == NULL) { | |
640 return NGX_ERROR; | |
641 } | |
642 | |
643 cl = cl->next; | |
644 cl->buf = b; | |
645 | |
646 body = body->next; | |
647 } | |
648 | |
649 } else { | |
650 u->request_bufs = cl; | |
651 } | |
652 | |
653 cl->next = NULL; | |
654 | |
585 return NGX_OK; | 655 return NGX_OK; |
586 } | 656 } |
587 | 657 |
588 | 658 |
589 static ngx_int_t | 659 static ngx_int_t |
590 ngx_http_proxy_reinit_request(ngx_http_request_t *r) | 660 ngx_http_proxy_reinit_request(ngx_http_request_t *r) |
591 { | 661 { |
662 ngx_http_proxy_ctx_t *p; | |
663 | |
664 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | |
665 | |
666 if (p == NULL) { | |
667 return NGX_OK; | |
668 } | |
669 | |
670 p->status = 0; | |
671 p->status_count = 0; | |
672 p->status_start = NULL; | |
673 p->status_end = NULL; | |
674 | |
675 r->upstream->process_header = ngx_http_proxy_process_status_line; | |
676 | |
677 return NGX_OK; | |
678 } | |
679 | |
680 | |
681 static ngx_int_t | |
682 ngx_http_proxy_process_status_line(ngx_http_request_t *r) | |
683 { | |
684 ngx_int_t rc; | |
685 ngx_http_upstream_t *u; | |
686 ngx_http_proxy_ctx_t *p; | |
687 | |
688 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | |
689 | |
690 if (p == NULL) { | |
691 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t)); | |
692 if (p == NULL) { | |
693 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
694 } | |
695 | |
696 ngx_http_set_ctx(r, p, ngx_http_proxy_module); | |
697 } | |
698 | |
699 rc = ngx_http_proxy_parse_status_line(r, p); | |
700 | |
701 if (rc == NGX_AGAIN) { | |
702 return rc; | |
703 } | |
704 | |
705 u = r->upstream; | |
706 | |
707 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | |
708 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
709 "upstream sent no valid HTTP/1.0 header"); | |
710 | |
711 if (u->accel) { | |
712 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
713 } | |
714 | |
715 r->http_version = NGX_HTTP_VERSION_9; | |
716 p->status = NGX_HTTP_OK; | |
717 | |
718 return NGX_OK; | |
719 } | |
720 | |
721 r->headers_out.status = p->status; | |
722 u->state->status = p->status; | |
723 | |
724 r->headers_out.status_line.len = p->status_end - p->status_start; | |
725 r->headers_out.status_line.data = ngx_palloc(r->pool, | |
726 r->headers_out.status_line.len); | |
727 if (r->headers_out.status_line.data == NULL) { | |
728 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
729 } | |
730 ngx_memcpy(r->headers_out.status_line.data, p->status_start, | |
731 r->headers_out.status_line.len); | |
732 | |
733 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
734 "http proxy status %ui \"%V\"", | |
735 r->headers_out.status, &r->headers_out.status_line); | |
736 | |
737 u->process_header = ngx_http_proxy_process_header; | |
738 | |
739 return ngx_http_proxy_process_header(r); | |
740 } | |
741 | |
742 | |
743 static ngx_int_t | |
744 ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) | |
745 { | |
746 u_char ch; | |
747 u_char *pos; | |
748 ngx_http_upstream_t *u; | |
749 enum { | |
750 sw_start = 0, | |
751 sw_H, | |
752 sw_HT, | |
753 sw_HTT, | |
754 sw_HTTP, | |
755 sw_first_major_digit, | |
756 sw_major_digit, | |
757 sw_first_minor_digit, | |
758 sw_minor_digit, | |
759 sw_status, | |
760 sw_space_after_status, | |
761 sw_status_text, | |
762 sw_almost_done | |
763 } state; | |
764 | |
765 u = r->upstream; | |
766 | |
767 state = r->state; | |
768 | |
769 for (pos = u->header_in.pos; pos < u->header_in.last; pos++) { | |
770 ch = *pos; | |
771 | |
772 switch (state) { | |
773 | |
774 /* "HTTP/" */ | |
775 case sw_start: | |
776 switch (ch) { | |
777 case 'H': | |
778 state = sw_H; | |
779 break; | |
780 default: | |
781 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
782 } | |
783 break; | |
784 | |
785 case sw_H: | |
786 switch (ch) { | |
787 case 'T': | |
788 state = sw_HT; | |
789 break; | |
790 default: | |
791 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
792 } | |
793 break; | |
794 | |
795 case sw_HT: | |
796 switch (ch) { | |
797 case 'T': | |
798 state = sw_HTT; | |
799 break; | |
800 default: | |
801 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
802 } | |
803 break; | |
804 | |
805 case sw_HTT: | |
806 switch (ch) { | |
807 case 'P': | |
808 state = sw_HTTP; | |
809 break; | |
810 default: | |
811 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
812 } | |
813 break; | |
814 | |
815 case sw_HTTP: | |
816 switch (ch) { | |
817 case '/': | |
818 state = sw_first_major_digit; | |
819 break; | |
820 default: | |
821 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
822 } | |
823 break; | |
824 | |
825 /* the first digit of major HTTP version */ | |
826 case sw_first_major_digit: | |
827 if (ch < '1' || ch > '9') { | |
828 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
829 } | |
830 | |
831 state = sw_major_digit; | |
832 break; | |
833 | |
834 /* the major HTTP version or dot */ | |
835 case sw_major_digit: | |
836 if (ch == '.') { | |
837 state = sw_first_minor_digit; | |
838 break; | |
839 } | |
840 | |
841 if (ch < '0' || ch > '9') { | |
842 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
843 } | |
844 | |
845 break; | |
846 | |
847 /* the first digit of minor HTTP version */ | |
848 case sw_first_minor_digit: | |
849 if (ch < '0' || ch > '9') { | |
850 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
851 } | |
852 | |
853 state = sw_minor_digit; | |
854 break; | |
855 | |
856 /* the minor HTTP version or the end of the request line */ | |
857 case sw_minor_digit: | |
858 if (ch == ' ') { | |
859 state = sw_status; | |
860 break; | |
861 } | |
862 | |
863 if (ch < '0' || ch > '9') { | |
864 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
865 } | |
866 | |
867 break; | |
868 | |
869 /* HTTP status code */ | |
870 case sw_status: | |
871 if (ch < '0' || ch > '9') { | |
872 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
873 } | |
874 | |
875 p->status = p->status * 10 + ch - '0'; | |
876 | |
877 if (++p->status_count == 3) { | |
878 state = sw_space_after_status; | |
879 p->status_start = pos - 2; | |
880 } | |
881 | |
882 break; | |
883 | |
884 /* space or end of line */ | |
885 case sw_space_after_status: | |
886 switch (ch) { | |
887 case ' ': | |
888 state = sw_status_text; | |
889 break; | |
890 case '.': /* IIS may send 403.1, 403.2, etc */ | |
891 state = sw_status_text; | |
892 break; | |
893 case CR: | |
894 state = sw_almost_done; | |
895 break; | |
896 case LF: | |
897 goto done; | |
898 default: | |
899 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
900 } | |
901 break; | |
902 | |
903 /* any text until end of line */ | |
904 case sw_status_text: | |
905 switch (ch) { | |
906 case CR: | |
907 state = sw_almost_done; | |
908 | |
909 break; | |
910 case LF: | |
911 goto done; | |
912 } | |
913 break; | |
914 | |
915 /* end of request line */ | |
916 case sw_almost_done: | |
917 p->status_end = pos - 1; | |
918 switch (ch) { | |
919 case LF: | |
920 goto done; | |
921 default: | |
922 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
923 } | |
924 } | |
925 } | |
926 | |
927 u->header_in.pos = pos + 1; | |
928 r->state = state; | |
929 | |
930 return NGX_AGAIN; | |
931 | |
932 done: | |
933 | |
934 u->header_in.pos = pos + 1; | |
935 | |
936 if (p->status_end == NULL) { | |
937 p->status_end = pos; | |
938 } | |
939 | |
940 r->state = sw_start; | |
941 | |
592 return NGX_OK; | 942 return NGX_OK; |
593 } | 943 } |
594 | 944 |
595 | 945 |
596 static ngx_int_t | 946 static ngx_int_t |
597 ngx_http_proxy_process_header(ngx_http_request_t *r) | 947 ngx_http_proxy_process_header(ngx_http_request_t *r) |
598 { | 948 { |
599 return NGX_OK; | 949 ngx_int_t rc; |
600 } | 950 ngx_uint_t key; |
601 | 951 ngx_table_elt_t *h; |
602 | 952 ngx_http_upstream_header_t *hh; |
603 static ngx_int_t | 953 ngx_http_upstream_main_conf_t *umcf; |
604 ngx_http_proxy_send_header(ngx_http_request_t *r) | 954 |
605 { | 955 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
606 return NGX_OK; | 956 hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets; |
957 | |
958 for ( ;; ) { | |
959 | |
960 rc = ngx_http_parse_header_line(r, &r->upstream->header_in); | |
961 | |
962 if (rc == NGX_OK) { | |
963 | |
964 /* a header line has been parsed successfully */ | |
965 | |
966 h = ngx_list_push(&r->upstream->headers_in.headers); | |
967 if (h == NULL) { | |
968 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
969 } | |
970 | |
971 h->hash = r->header_hash; | |
972 | |
973 h->key.len = r->header_name_end - r->header_name_start; | |
974 h->value.len = r->header_end - r->header_start; | |
975 | |
976 h->key.data = ngx_palloc(r->pool, | |
977 h->key.len + 1 + h->value.len + 1); | |
978 if (h->key.data == NULL) { | |
979 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
980 } | |
981 | |
982 h->value.data = h->key.data + h->key.len + 1; | |
983 | |
984 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
985 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
986 | |
987 key = h->hash % umcf->headers_in_hash.hash_size; | |
988 | |
989 if (hh[key].name.len == h->key.len | |
990 && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0) | |
991 { | |
992 if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) { | |
993 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
994 } | |
995 } | |
996 | |
997 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
998 "http proxy header: \"%V: %V\"", | |
999 &h->key, &h->value); | |
1000 | |
1001 continue; | |
1002 } | |
1003 | |
1004 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
1005 | |
1006 /* a whole header has been parsed successfully */ | |
1007 | |
1008 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1009 "http proxy header done"); | |
1010 | |
1011 return NGX_OK; | |
1012 } | |
1013 | |
1014 /* there was error while a header line parsing */ | |
1015 | |
1016 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1017 ngx_http_upstream_header_errors[rc | |
1018 - NGX_HTTP_PARSE_HEADER_ERROR]); | |
1019 | |
1020 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
1021 } | |
607 } | 1022 } |
608 | 1023 |
609 | 1024 |
610 static void | 1025 static void |
611 ngx_http_proxy_abort_request(ngx_http_request_t *r) | 1026 ngx_http_proxy_abort_request(ngx_http_request_t *r) |
625 | 1040 |
626 return; | 1041 return; |
627 } | 1042 } |
628 | 1043 |
629 | 1044 |
630 static ngx_int_t | |
631 ngx_http_proxy_init(ngx_cycle_t *cycle) | |
632 { | |
633 #if 0 | |
634 ngx_http_variable_t *var; | |
635 | |
636 var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 1); | |
637 if (var == NULL) { | |
638 return NGX_ERROR; | |
639 } | |
640 | |
641 var->handler = ngx_http_proxy_host_variable; | |
642 #endif | |
643 | |
644 return NGX_OK; | |
645 | |
646 #if 0 | |
647 ngx_http_log_op_name_t *op; | |
648 | |
649 for (op = ngx_http_proxy_log_fmt_ops; op->name.len; op++) { /* void */ } | |
650 op->run = NULL; | |
651 | |
652 for (op = ngx_http_log_fmt_ops; op->run; op++) { | |
653 if (op->name.len == 0) { | |
654 op = (ngx_http_log_op_name_t *) op->run; | |
655 } | |
656 } | |
657 | |
658 op->run = (ngx_http_log_op_run_pt) ngx_http_proxy_log_fmt_ops; | |
659 | |
660 #endif | |
661 } | |
662 | |
663 | |
664 static ngx_http_variable_value_t * | 1045 static ngx_http_variable_value_t * |
665 ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data) | 1046 ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data) |
666 { | 1047 { |
667 ngx_http_variable_value_t *var; | 1048 ngx_http_variable_value_t *vv; |
668 ngx_http_proxy_loc_conf_t *plcf; | 1049 ngx_http_proxy_loc_conf_t *plcf; |
669 | 1050 |
670 var = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | 1051 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); |
671 if (var == NULL) { | 1052 if (vv == NULL) { |
672 return NULL; | 1053 return NULL; |
673 } | 1054 } |
674 | 1055 |
675 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 1056 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
676 | 1057 |
677 var->value = 0; | 1058 vv->value = 0; |
678 var->text = plcf->host_header; | 1059 vv->text = plcf->host_header; |
679 | 1060 |
680 return var; | 1061 return vv; |
1062 } | |
1063 | |
1064 | |
1065 static ngx_http_variable_value_t * | |
1066 ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data) | |
1067 { | |
1068 ngx_http_variable_value_t *vv; | |
1069 ngx_http_proxy_loc_conf_t *plcf; | |
1070 | |
1071 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
1072 if (vv == NULL) { | |
1073 return NULL; | |
1074 } | |
1075 | |
1076 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | |
1077 | |
1078 vv->value = 0; | |
1079 vv->text = plcf->port_text; | |
1080 | |
1081 return vv; | |
1082 } | |
1083 | |
1084 | |
1085 static ngx_http_variable_value_t * | |
1086 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, | |
1087 uintptr_t data) | |
1088 { | |
1089 u_char *p; | |
1090 ngx_http_variable_value_t *vv; | |
1091 | |
1092 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
1093 if (vv == NULL) { | |
1094 return NULL; | |
1095 } | |
1096 | |
1097 vv->value = 0; | |
1098 | |
1099 if (r->headers_in.x_forwarded_for == NULL) { | |
1100 vv->text = r->connection->addr_text; | |
1101 return vv; | |
1102 } | |
1103 | |
1104 vv->text.len = r->headers_in.x_forwarded_for->value.len | |
1105 + sizeof(", ") - 1 + r->connection->addr_text.len; | |
1106 | |
1107 p = ngx_palloc(r->pool, vv->text.len); | |
1108 if (p == NULL) { | |
1109 return NULL; | |
1110 } | |
1111 | |
1112 vv->text.data = p; | |
1113 | |
1114 p = ngx_cpymem(p, r->headers_in.x_forwarded_for->value.data, | |
1115 r->headers_in.x_forwarded_for->value.len); | |
1116 | |
1117 *p++ = ','; *p++ = ' '; | |
1118 | |
1119 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); | |
1120 | |
1121 return vv; | |
1122 } | |
1123 | |
1124 | |
1125 static ngx_int_t | |
1126 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, | |
1127 size_t prefix) | |
1128 { | |
1129 ngx_int_t rc; | |
1130 ngx_uint_t i; | |
1131 ngx_http_proxy_loc_conf_t *plcf; | |
1132 ngx_http_proxy_redirect_t *pr; | |
1133 | |
1134 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | |
1135 | |
1136 pr = plcf->redirects->elts; | |
1137 | |
1138 if (pr == NULL) { | |
1139 return NGX_DECLINED; | |
1140 } | |
1141 | |
1142 for (i = 0; i < plcf->redirects->nelts; i++) { | |
1143 rc = pr->handler(r, h, prefix, pr); | |
1144 | |
1145 if (rc != NGX_DECLINED) { | |
1146 return rc; | |
1147 } | |
1148 } | |
1149 | |
1150 return NGX_DECLINED; | |
1151 } | |
1152 | |
1153 | |
1154 static ngx_int_t | |
1155 ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h, | |
1156 size_t prefix, ngx_http_proxy_redirect_t *pr) | |
1157 { | |
1158 size_t len; | |
1159 u_char *data, *p; | |
1160 | |
1161 if (pr->redirect.len > h->value.len - prefix | |
1162 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data, | |
1163 pr->redirect.len) != 0) | |
1164 { | |
1165 return NGX_DECLINED; | |
1166 } | |
1167 | |
1168 len = prefix + pr->replacement.text.len + h->value.len - pr->redirect.len; | |
1169 | |
1170 data = ngx_palloc(r->pool, len); | |
1171 if (data == NULL) { | |
1172 return NGX_ERROR; | |
1173 } | |
1174 | |
1175 p = data; | |
1176 | |
1177 if (prefix) { | |
1178 p = ngx_cpymem(p, h->value.data, prefix); | |
1179 } | |
1180 | |
1181 p = ngx_cpymem(p, pr->replacement.text.data, pr->replacement.text.len); | |
1182 | |
1183 ngx_memcpy(p, h->value.data + prefix + pr->redirect.len, | |
1184 h->value.len - pr->redirect.len - prefix); | |
1185 | |
1186 h->value.len = len; | |
1187 h->value.data = data; | |
1188 | |
1189 return NGX_OK; | |
1190 } | |
1191 | |
1192 | |
1193 static ngx_int_t | |
1194 ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h, | |
1195 size_t prefix, ngx_http_proxy_redirect_t *pr) | |
1196 { | |
1197 size_t len; | |
1198 u_char *data, *p; | |
1199 ngx_http_script_code_pt code; | |
1200 ngx_http_script_engine_t e; | |
1201 ngx_http_script_len_code_pt lcode; | |
1202 | |
1203 if (pr->redirect.len > h->value.len - prefix | |
1204 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data, | |
1205 pr->redirect.len) != 0) | |
1206 { | |
1207 return NGX_DECLINED; | |
1208 } | |
1209 | |
1210 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
1211 | |
1212 e.ip = pr->replacement.vars.lengths; | |
1213 e.request = r; | |
1214 | |
1215 for (len = prefix; *(uintptr_t *) e.ip; len += lcode(&e)) { | |
1216 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
1217 } | |
1218 | |
1219 data = ngx_palloc(r->pool, len); | |
1220 if (data == NULL) { | |
1221 return NGX_ERROR; | |
1222 } | |
1223 | |
1224 p = data; | |
1225 | |
1226 if (prefix) { | |
1227 p = ngx_cpymem(p, h->value.data, prefix); | |
1228 } | |
1229 | |
1230 e.ip = pr->replacement.vars.values; | |
1231 e.pos = p; | |
1232 | |
1233 while (*(uintptr_t *) e.ip) { | |
1234 code = *(ngx_http_script_code_pt *) e.ip; | |
1235 code(&e); | |
1236 } | |
1237 | |
1238 h->value.len = len; | |
1239 h->value.data = data; | |
1240 | |
1241 return NGX_OK; | |
1242 } | |
1243 | |
1244 | |
1245 static ngx_int_t | |
1246 ngx_http_proxy_add_variables(ngx_conf_t *cf) | |
1247 { | |
1248 ngx_http_variable_t *var, *v; | |
1249 | |
1250 for (v = ngx_http_proxy_vars; v->name.len; v++) { | |
1251 var = ngx_http_add_variable(cf, &v->name, v->flags); | |
1252 if (var == NULL) { | |
1253 return NGX_ERROR; | |
1254 } | |
1255 | |
1256 var->handler = v->handler; | |
1257 var->data = v->data; | |
1258 } | |
1259 | |
1260 return NGX_OK; | |
681 } | 1261 } |
682 | 1262 |
683 | 1263 |
684 static void * | 1264 static void * |
685 ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) | 1265 ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) |
696 * | 1276 * |
697 * conf->upstream.bufs.num = 0; | 1277 * conf->upstream.bufs.num = 0; |
698 * conf->upstream.path = NULL; | 1278 * conf->upstream.path = NULL; |
699 * conf->upstream.next_upstream = 0; | 1279 * conf->upstream.next_upstream = 0; |
700 * conf->upstream.temp_path = NULL; | 1280 * conf->upstream.temp_path = NULL; |
1281 * conf->upstream.schema = { 0, NULL }; | |
1282 * conf->upstream.uri = { 0, NULL }; | |
1283 * conf->upstream.location = NULL; | |
1284 * | |
1285 * conf->headers_source = NULL; | |
1286 * conf->headers_set_len = NULL; | |
1287 * conf->headers_set = NULL; | |
1288 * conf->headers_set_hash = NULL; | |
1289 * conf->rewrite_locations = NULL; | |
701 */ | 1290 */ |
702 | 1291 |
703 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | 1292 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
704 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | 1293 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
705 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | 1294 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
707 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; | 1296 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
708 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; | 1297 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; |
709 conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE; | 1298 conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE; |
710 conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; | 1299 conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; |
711 conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE; | 1300 conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE; |
1301 | |
1302 conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET; | |
1303 conf->upstream.method = NGX_CONF_UNSET_UINT; | |
1304 conf->upstream.pass_request_headers = NGX_CONF_UNSET; | |
1305 conf->upstream.pass_request_body = NGX_CONF_UNSET; | |
712 | 1306 |
713 conf->upstream.redirect_errors = NGX_CONF_UNSET; | 1307 conf->upstream.redirect_errors = NGX_CONF_UNSET; |
714 conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET; | |
715 conf->upstream.x_powered_by = NGX_CONF_UNSET; | |
716 | 1308 |
717 /* "proxy_cyclic_temp_file" is disabled */ | 1309 /* "proxy_cyclic_temp_file" is disabled */ |
718 conf->upstream.cyclic_temp_file = 0; | 1310 conf->upstream.cyclic_temp_file = 0; |
719 | 1311 |
720 conf->preserve_host = NGX_CONF_UNSET; | 1312 conf->upstream.pass_x_powered_by = NGX_CONF_UNSET; |
721 conf->set_x_url = NGX_CONF_UNSET; | 1313 conf->upstream.pass_server = NGX_CONF_UNSET; |
722 conf->set_x_real_ip = NGX_CONF_UNSET; | 1314 conf->upstream.pass_date = 0; |
723 conf->add_x_forwarded_for = NGX_CONF_UNSET; | 1315 conf->upstream.pass_x_accel_expires = NGX_CONF_UNSET; |
724 | 1316 |
725 conf->pass_server = NGX_CONF_UNSET; | 1317 conf->redirect = NGX_CONF_UNSET; |
726 conf->pass_x_accel_expires = NGX_CONF_UNSET; | |
727 | 1318 |
728 return conf; | 1319 return conf; |
729 } | 1320 } |
730 | 1321 |
731 | 1322 |
733 ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | 1324 ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |
734 { | 1325 { |
735 ngx_http_proxy_loc_conf_t *prev = parent; | 1326 ngx_http_proxy_loc_conf_t *prev = parent; |
736 ngx_http_proxy_loc_conf_t *conf = child; | 1327 ngx_http_proxy_loc_conf_t *conf = child; |
737 | 1328 |
738 size_t size; | 1329 u_char *p; |
739 ngx_str_t *name; | 1330 size_t size; |
740 ngx_table_elt_t *src; | 1331 uintptr_t *code; |
741 ngx_http_variable_t *var; | 1332 ngx_str_t *name; |
742 | 1333 ngx_uint_t i; |
1334 ngx_table_elt_t *src, *s, *h; | |
1335 ngx_http_proxy_redirect_t *pr; | |
1336 ngx_http_script_compile_t sc; | |
1337 ngx_http_script_copy_code_t *copy; | |
1338 | |
743 ngx_conf_merge_msec_value(conf->upstream.connect_timeout, | 1339 ngx_conf_merge_msec_value(conf->upstream.connect_timeout, |
744 prev->upstream.connect_timeout, 60000); | 1340 prev->upstream.connect_timeout, 60000); |
745 | 1341 |
746 ngx_conf_merge_msec_value(conf->upstream.send_timeout, | 1342 ngx_conf_merge_msec_value(conf->upstream.send_timeout, |
747 prev->upstream.send_timeout, 60000); | 1343 prev->upstream.send_timeout, 60000); |
839 prev->upstream.next_upstream, | 1435 prev->upstream.next_upstream, |
840 (NGX_CONF_BITMASK_SET | 1436 (NGX_CONF_BITMASK_SET |
841 |NGX_HTTP_UPSTREAM_FT_ERROR | 1437 |NGX_HTTP_UPSTREAM_FT_ERROR |
842 |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); | 1438 |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); |
843 | 1439 |
844 ngx_conf_merge_msec_value(conf->upstream.redirect_errors, | 1440 ngx_conf_merge_path_value(conf->upstream.temp_path, |
845 prev->upstream.redirect_errors, 0); | 1441 prev->upstream.temp_path, |
1442 NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0, | |
1443 ngx_garbage_collector_temp_handler, cf); | |
846 | 1444 |
847 ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri, | 1445 ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri, |
848 prev->upstream.pass_unparsed_uri, 0); | 1446 prev->upstream.pass_unparsed_uri, 0); |
849 | 1447 |
850 if (conf->upstream.pass_unparsed_uri && conf->location0->len > 1) { | 1448 if (conf->upstream.pass_unparsed_uri && conf->upstream.location->len > 1) { |
851 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | 1449 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, |
852 "\"proxy_pass_unparsed_uri\" can be set for " | 1450 "\"proxy_pass_unparsed_uri\" can be set for " |
853 "location \"/\" or given by regular expression."); | 1451 "location \"/\" or given by regular expression."); |
854 return NGX_CONF_ERROR; | 1452 return NGX_CONF_ERROR; |
855 } | 1453 } |
856 | 1454 |
857 ngx_conf_merge_msec_value(conf->upstream.x_powered_by, | 1455 if (conf->upstream.method == NGX_CONF_UNSET_UINT) { |
858 prev->upstream.x_powered_by, 1); | 1456 conf->upstream.method = prev->upstream.method; |
859 | 1457 } |
860 ngx_conf_merge_value(conf->preserve_host, prev->preserve_host, 0); | 1458 |
861 ngx_conf_merge_value(conf->set_x_url, prev->set_x_url, 0); | 1459 ngx_conf_merge_value(conf->upstream.pass_request_headers, |
862 ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0); | 1460 prev->upstream.pass_request_headers, 1); |
863 ngx_conf_merge_value(conf->add_x_forwarded_for, | 1461 ngx_conf_merge_value(conf->upstream.pass_request_body, |
864 prev->add_x_forwarded_for, 0); | 1462 prev->upstream.pass_request_body, 1); |
1463 | |
1464 ngx_conf_merge_msec_value(conf->upstream.redirect_errors, | |
1465 prev->upstream.redirect_errors, 0); | |
1466 | |
1467 ngx_conf_merge_msec_value(conf->upstream.pass_x_powered_by, | |
1468 prev->upstream.pass_x_powered_by, 1); | |
1469 ngx_conf_merge_msec_value(conf->upstream.pass_server, | |
1470 prev->upstream.pass_server, 0); | |
1471 ngx_conf_merge_msec_value(conf->upstream.pass_x_accel_expires, | |
1472 prev->upstream.pass_x_accel_expires, 0); | |
1473 | |
1474 | |
1475 ngx_conf_merge_value(conf->redirect, prev->redirect, 1); | |
1476 | |
1477 if (conf->redirect) { | |
1478 | |
1479 if (conf->redirects == NULL) { | |
1480 conf->redirects = prev->redirects; | |
1481 } | |
1482 | |
1483 if (conf->redirects == NULL && conf->upstream.url.data) { | |
1484 | |
1485 conf->redirects = ngx_array_create(cf->pool, 1, | |
1486 sizeof(ngx_http_proxy_redirect_t)); | |
1487 if (conf->redirects == NULL) { | |
1488 return NGX_CONF_ERROR; | |
1489 } | |
1490 | |
1491 pr = ngx_array_push(conf->redirects); | |
1492 if (pr == NULL) { | |
1493 return NGX_CONF_ERROR; | |
1494 } | |
1495 | |
1496 pr->handler = ngx_http_proxy_rewrite_redirect_text; | |
1497 pr->redirect = conf->upstream.url; | |
1498 pr->replacement.text = *conf->upstream.location; | |
1499 } | |
1500 } | |
1501 | |
865 | 1502 |
866 if (conf->peers == NULL) { | 1503 if (conf->peers == NULL) { |
867 conf->peers = prev->peers; | 1504 conf->peers = prev->peers; |
868 conf->upstream = prev->upstream; | 1505 conf->upstream = prev->upstream; |
869 } | 1506 } |
870 | 1507 |
871 if (conf->headers_set_hash == NULL) { | 1508 if (conf->headers_source == NULL) { |
1509 conf->headers_source = prev->headers_source; | |
872 conf->headers_set_len = prev->headers_set_len; | 1510 conf->headers_set_len = prev->headers_set_len; |
873 conf->headers_set = prev->headers_set; | 1511 conf->headers_set = prev->headers_set; |
874 conf->headers_set_hash = prev->headers_set_hash; | 1512 conf->headers_set_hash = prev->headers_set_hash; |
875 } | 1513 } |
876 | 1514 |
877 if (conf->headers_set_hash == NULL) { | 1515 if (conf->headers_set_hash) { |
878 | 1516 return NGX_CONF_OK; |
879 if (conf->headers_names == NULL) { | 1517 } |
880 conf->headers_names = ngx_array_create(cf->pool, 4, | 1518 |
881 sizeof(ngx_str_t)); | 1519 |
882 if (conf->headers_names == NULL) { | 1520 conf->headers_names = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); |
883 return NGX_CONF_ERROR; | 1521 if (conf->headers_names == NULL) { |
884 } | 1522 return NGX_CONF_ERROR; |
885 } | 1523 } |
886 | 1524 |
887 if (conf->headers_sources == NULL) { | 1525 if (conf->headers_source == NULL) { |
888 conf->headers_sources = ngx_array_create(cf->pool, 4, | 1526 conf->headers_source = ngx_array_create(cf->pool, 4, |
889 sizeof(ngx_table_elt_t)); | 1527 sizeof(ngx_table_elt_t)); |
890 if (conf->headers_sources == NULL) { | 1528 if (conf->headers_source == NULL) { |
891 return NGX_CONF_ERROR; | |
892 } | |
893 } | |
894 | |
895 /* STUB */ | |
896 var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 0); | |
897 if (var == NULL) { | |
898 return NGX_CONF_ERROR; | 1529 return NGX_CONF_ERROR; |
899 } | 1530 } |
900 | 1531 } |
901 var->handler = ngx_http_proxy_host_variable; | 1532 |
902 /**/ | 1533 conf->headers_set_len = ngx_array_create(cf->pool, 64, 1); |
903 | 1534 if (conf->headers_set_len == NULL) { |
1535 return NGX_CONF_ERROR; | |
1536 } | |
1537 | |
1538 conf->headers_set = ngx_array_create(cf->pool, 512, 1); | |
1539 if (conf->headers_set == NULL) { | |
1540 return NGX_CONF_ERROR; | |
1541 } | |
1542 | |
1543 | |
1544 src = conf->headers_source->elts; | |
1545 | |
1546 for (h = ngx_http_proxy_headers; h->key.len; h++) { | |
1547 | |
1548 for (i = 0; i < conf->headers_source->nelts; i++) { | |
1549 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { | |
1550 goto next; | |
1551 } | |
1552 } | |
1553 | |
1554 s = ngx_array_push(conf->headers_source); | |
1555 if (s == NULL) { | |
1556 return NGX_CONF_ERROR; | |
1557 } | |
1558 | |
1559 *s = *h; | |
1560 | |
1561 next: | |
1562 | |
1563 continue; | |
1564 } | |
1565 | |
1566 for (i = 0; i < conf->headers_source->nelts; i++) { | |
904 | 1567 |
905 name = ngx_array_push(conf->headers_names); | 1568 name = ngx_array_push(conf->headers_names); |
906 if (name == NULL) { | 1569 if (name == NULL) { |
907 return NGX_CONF_ERROR; | 1570 return NGX_CONF_ERROR; |
908 } | 1571 } |
909 | 1572 |
910 name->len = sizeof("Host") - 1; | 1573 *name = src[i].key; |
911 name->data = (u_char *) "Host"; | 1574 |
912 | 1575 if (ngx_http_script_variables_count(&src[i].value) == 0) { |
913 src = ngx_array_push(conf->headers_sources); | 1576 copy = ngx_array_push_n(conf->headers_set_len, |
914 if (src == NULL) { | 1577 sizeof(ngx_http_script_copy_code_t)); |
1578 if (copy == NULL) { | |
1579 return NGX_CONF_ERROR; | |
1580 } | |
1581 | |
1582 copy->code = (ngx_http_script_code_pt) | |
1583 ngx_http_script_copy_len_code; | |
1584 copy->len = src[i].key.len + sizeof(": ") - 1 | |
1585 + src[i].value.len + sizeof(CRLF) - 1; | |
1586 | |
1587 | |
1588 size = (sizeof(ngx_http_script_copy_code_t) | |
1589 + src[i].key.len + sizeof(": ") - 1 | |
1590 + src[i].value.len + sizeof(CRLF) - 1 | |
1591 + sizeof(uintptr_t) - 1) | |
1592 & ~(sizeof(uintptr_t) - 1); | |
1593 | |
1594 copy = ngx_array_push_n(conf->headers_set, size); | |
1595 if (copy == NULL) { | |
1596 return NGX_CONF_ERROR; | |
1597 } | |
1598 | |
1599 copy->code = ngx_http_script_copy_code; | |
1600 copy->len = src[i].key.len + sizeof(": ") - 1 | |
1601 + src[i].value.len + sizeof(CRLF) - 1; | |
1602 | |
1603 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1604 | |
1605 p = ngx_cpymem(p, src[i].key.data, src[i].key.len); | |
1606 *p++ = ':'; *p++ = ' '; | |
1607 p = ngx_cpymem(p, src[i].value.data, src[i].value.len); | |
1608 *p++ = CR; *p = LF; | |
1609 | |
1610 } else { | |
1611 copy = ngx_array_push_n(conf->headers_set_len, | |
1612 sizeof(ngx_http_script_copy_code_t)); | |
1613 if (copy == NULL) { | |
1614 return NGX_CONF_ERROR; | |
1615 } | |
1616 | |
1617 copy->code = (ngx_http_script_code_pt) | |
1618 ngx_http_script_copy_len_code; | |
1619 copy->len = src[i].key.len + sizeof(": ") - 1; | |
1620 | |
1621 | |
1622 size = (sizeof(ngx_http_script_copy_code_t) | |
1623 + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1) | |
1624 & ~(sizeof(uintptr_t) - 1); | |
1625 | |
1626 copy = ngx_array_push_n(conf->headers_set, size); | |
1627 if (copy == NULL) { | |
1628 return NGX_CONF_ERROR; | |
1629 } | |
1630 | |
1631 copy->code = ngx_http_script_copy_code; | |
1632 copy->len = src[i].key.len + sizeof(": ") - 1; | |
1633 | |
1634 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1635 p = ngx_cpymem(p, src[i].key.data, src[i].key.len); | |
1636 *p++ = ':'; *p = ' '; | |
1637 | |
1638 | |
1639 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1640 | |
1641 sc.cf = cf; | |
1642 sc.source = &src[i].value; | |
1643 sc.lengths = &conf->headers_set_len; | |
1644 sc.values = &conf->headers_set; | |
1645 | |
1646 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1647 return NGX_CONF_ERROR; | |
1648 } | |
1649 | |
1650 | |
1651 copy = ngx_array_push_n(conf->headers_set_len, | |
1652 sizeof(ngx_http_script_copy_code_t)); | |
1653 if (copy == NULL) { | |
1654 return NGX_CONF_ERROR; | |
1655 } | |
1656 | |
1657 copy->code = (ngx_http_script_code_pt) | |
1658 ngx_http_script_copy_len_code; | |
1659 copy->len = sizeof(CRLF) - 1; | |
1660 | |
1661 | |
1662 size = (sizeof(ngx_http_script_copy_code_t) | |
1663 + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) | |
1664 & ~(sizeof(uintptr_t) - 1); | |
1665 | |
1666 copy = ngx_array_push_n(conf->headers_set, size); | |
1667 if (copy == NULL) { | |
1668 return NGX_CONF_ERROR; | |
1669 } | |
1670 | |
1671 copy->code = ngx_http_script_copy_code; | |
1672 copy->len = sizeof(CRLF) - 1; | |
1673 | |
1674 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1675 *p++ = CR; *p = LF; | |
1676 } | |
1677 | |
1678 code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); | |
1679 if (code == NULL) { | |
915 return NGX_CONF_ERROR; | 1680 return NGX_CONF_ERROR; |
916 } | 1681 } |
917 | 1682 |
918 src->hash = 0; | 1683 *code = (uintptr_t) NULL; |
919 src->key.len = sizeof("Host") - 1; | 1684 |
920 src->key.data = (u_char *) "Host"; | 1685 code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t)); |
921 src->value.len = sizeof("$PROXY_HOST") - 1; | 1686 if (code == NULL) { |
922 src->value.data = (u_char *) "$PROXY_HOST"; | |
923 | |
924 | |
925 name = ngx_array_push(conf->headers_names); | |
926 if (name == NULL) { | |
927 return NGX_CONF_ERROR; | 1687 return NGX_CONF_ERROR; |
928 } | 1688 } |
929 | 1689 |
930 name->len = sizeof("Connection") - 1; | 1690 *code = (uintptr_t) NULL; |
931 name->data = (u_char *) "Connection"; | 1691 } |
932 | 1692 |
933 src = ngx_array_push(conf->headers_sources); | 1693 code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); |
934 if (src == NULL) { | 1694 if (code == NULL) { |
935 return NGX_CONF_ERROR; | 1695 return NGX_CONF_ERROR; |
936 } | 1696 } |
937 | 1697 |
938 src->hash = 0; | 1698 *code = (uintptr_t) NULL; |
939 src->key.len = sizeof("Connection") - 1; | 1699 |
940 src->key.data = (u_char *) "Connection"; | 1700 |
941 src->value.len = sizeof("close") - 1; | 1701 conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); |
942 src->value.data = (u_char *) "close"; | 1702 if (conf->headers_set_hash == NULL) { |
943 | 1703 return NGX_CONF_ERROR; |
944 | 1704 } |
945 name = ngx_array_push(conf->headers_names); | 1705 |
946 if (name == NULL) { | 1706 conf->headers_set_hash->max_size = 100; |
947 return NGX_CONF_ERROR; | 1707 conf->headers_set_hash->bucket_limit = 1; |
948 } | 1708 conf->headers_set_hash->bucket_size = sizeof(ngx_str_t); |
949 | 1709 conf->headers_set_hash->name = "proxy_headers"; |
950 name->len = 0; | 1710 |
951 name->data = NULL; | 1711 if (ngx_hash_init(conf->headers_set_hash, cf->pool, |
952 | 1712 conf->headers_names->elts, conf->headers_names->nelts) != NGX_OK) |
953 | 1713 { |
954 if (ngx_http_script_compile_lite(cf, conf->headers_sources, | 1714 return NGX_CONF_ERROR; |
955 &conf->headers_set_len, &conf->headers_set, | 1715 } |
956 ngx_http_proxy_compile_header_start, | 1716 |
957 ngx_http_proxy_compile_header_end) != NGX_OK) | 1717 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, |
958 { | 1718 "proxy_headers hash size: %ui, " |
959 return NGX_CONF_ERROR; | 1719 "max buckets per entry: %ui", |
960 } | 1720 conf->headers_set_hash->hash_size, |
961 | 1721 conf->headers_set_hash->min_buckets); |
962 | |
963 conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); | |
964 if (conf->headers_set_hash == NULL) { | |
965 return NGX_CONF_ERROR; | |
966 } | |
967 | |
968 conf->headers_set_hash->max_size = 100; | |
969 conf->headers_set_hash->bucket_limit = 1; | |
970 conf->headers_set_hash->bucket_size = sizeof(ngx_str_t); | |
971 conf->headers_set_hash->name = "proxy_headers"; | |
972 | |
973 if (ngx_hash_init(conf->headers_set_hash, cf->pool, | |
974 conf->headers_names->elts) != NGX_OK) | |
975 { | |
976 return NGX_CONF_ERROR; | |
977 } | |
978 | |
979 #if 0 | |
980 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, | |
981 #endif | |
982 ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, | |
983 "proxy_headers hash size: %ui, " | |
984 "max buckets per entry: %ui", | |
985 conf->headers_set_hash->hash_size, | |
986 conf->headers_set_hash->min_buckets); | |
987 } | |
988 | 1722 |
989 return NGX_CONF_OK; | 1723 return NGX_CONF_OK; |
990 } | |
991 | |
992 | |
993 static ngx_int_t | |
994 ngx_http_proxy_compile_header_start(ngx_table_elt_t *h, | |
995 ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value) | |
996 { | |
997 u_char *p; | |
998 size_t size; | |
999 ngx_http_script_copy_code_t *copy; | |
1000 | |
1001 copy = ngx_array_push_n(lengths, sizeof(ngx_http_script_copy_code_t)); | |
1002 if (copy == NULL) { | |
1003 return NGX_ERROR; | |
1004 } | |
1005 | |
1006 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len; | |
1007 copy->len = h->key.len + sizeof(": ") - 1; | |
1008 | |
1009 if (value) { | |
1010 copy->len += h->value.len + sizeof(CRLF) - 1; | |
1011 } | |
1012 | |
1013 size = (copy->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); | |
1014 | |
1015 copy = ngx_array_push_n(values, | |
1016 sizeof(ngx_http_script_copy_code_t) + size); | |
1017 if (copy == NULL) { | |
1018 return NGX_ERROR; | |
1019 } | |
1020 | |
1021 copy->code = ngx_http_script_copy; | |
1022 copy->len = h->key.len + sizeof(": ") - 1; | |
1023 | |
1024 if (value) { | |
1025 copy->len += h->value.len + sizeof(CRLF) - 1; | |
1026 } | |
1027 | |
1028 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1029 | |
1030 p = ngx_cpymem(p, h->key.data, h->key.len); | |
1031 p = ngx_cpymem(p, ": ", sizeof(": ") - 1); | |
1032 | |
1033 if (value) { | |
1034 p = ngx_cpymem(p, h->value.data, h->value.len); | |
1035 ngx_memcpy(p, CRLF, sizeof(CRLF) - 1); | |
1036 } | |
1037 | |
1038 return NGX_OK; | |
1039 } | |
1040 | |
1041 | |
1042 static ngx_int_t | |
1043 ngx_http_proxy_compile_header_end(ngx_array_t *lengths, ngx_array_t *values) | |
1044 { | |
1045 size_t size; | |
1046 ngx_http_script_copy_code_t *copy; | |
1047 | |
1048 copy = ngx_array_push_n(lengths, sizeof(ngx_http_script_copy_code_t)); | |
1049 if (copy == NULL) { | |
1050 return NGX_ERROR; | |
1051 } | |
1052 | |
1053 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len; | |
1054 copy->len = sizeof(CRLF) - 1; | |
1055 | |
1056 size = (sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) | |
1057 & ~(sizeof(uintptr_t) - 1); | |
1058 | |
1059 copy = ngx_array_push_n(values, | |
1060 sizeof(ngx_http_script_copy_code_t) + size); | |
1061 if (copy == NULL) { | |
1062 return NGX_ERROR; | |
1063 } | |
1064 | |
1065 copy->code = ngx_http_script_copy; | |
1066 copy->len = sizeof(CRLF) - 1; | |
1067 | |
1068 ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t), | |
1069 CRLF, sizeof(CRLF) - 1); | |
1070 | |
1071 return NGX_OK; | |
1072 } | 1724 } |
1073 | 1725 |
1074 | 1726 |
1075 static char * | 1727 static char * |
1076 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1728 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1077 { | 1729 { |
1078 ngx_http_proxy_loc_conf_t *lcf = conf; | 1730 ngx_http_proxy_loc_conf_t *plcf = conf; |
1079 | 1731 |
1080 ngx_uint_t i; | 1732 ngx_uint_t i; |
1081 ngx_str_t *value, *url; | 1733 ngx_str_t *value, *url; |
1082 ngx_inet_upstream_t inet_upstream; | 1734 ngx_inet_upstream_t inet_upstream; |
1083 ngx_http_core_loc_conf_t *clcf; | 1735 ngx_http_core_loc_conf_t *clcf; |
1103 unix_upstream.name = *url; | 1755 unix_upstream.name = *url; |
1104 unix_upstream.url.len = url->len - 7; | 1756 unix_upstream.url.len = url->len - 7; |
1105 unix_upstream.url.data = url->data + 7; | 1757 unix_upstream.url.data = url->data + 7; |
1106 unix_upstream.uri_part = 1; | 1758 unix_upstream.uri_part = 1; |
1107 | 1759 |
1108 lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); | 1760 plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); |
1109 if (lcf->peers == NULL) { | 1761 if (plcf->peers == NULL) { |
1110 return NGX_CONF_ERROR; | 1762 return NGX_CONF_ERROR; |
1111 } | 1763 } |
1112 | 1764 |
1113 lcf->peers->peer[0].uri_separator = ":"; | 1765 plcf->peers->peer[0].uri_separator = ":"; |
1114 | 1766 |
1115 lcf->host_header.len = sizeof("localhost") - 1; | 1767 plcf->host_header.len = sizeof("localhost") - 1; |
1116 lcf->host_header.data = (u_char *) "localhost"; | 1768 plcf->host_header.data = (u_char *) "localhost"; |
1117 lcf->uri0 = unix_upstream.uri; | 1769 plcf->upstream.uri = unix_upstream.uri; |
1118 #if 0 | |
1119 STUB | |
1120 lcf->upstream->default_port = 1; | |
1121 #endif | |
1122 | 1770 |
1123 #else | 1771 #else |
1124 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1772 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1125 "the unix domain sockets are not supported " | 1773 "the unix domain sockets are not supported " |
1126 "on this platform"); | 1774 "on this platform"); |
1135 inet_upstream.url.len = url->len - 7; | 1783 inet_upstream.url.len = url->len - 7; |
1136 inet_upstream.url.data = url->data + 7; | 1784 inet_upstream.url.data = url->data + 7; |
1137 inet_upstream.default_port_value = 80; | 1785 inet_upstream.default_port_value = 80; |
1138 inet_upstream.uri_part = 1; | 1786 inet_upstream.uri_part = 1; |
1139 | 1787 |
1140 lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); | 1788 plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); |
1141 if (lcf->peers == NULL) { | 1789 if (plcf->peers == NULL) { |
1142 return NGX_CONF_ERROR; | 1790 return NGX_CONF_ERROR; |
1143 } | 1791 } |
1144 | 1792 |
1145 for (i = 0; i < lcf->peers->number; i++) { | 1793 for (i = 0; i < plcf->peers->number; i++) { |
1146 lcf->peers->peer[i].uri_separator = ":"; | 1794 plcf->peers->peer[i].uri_separator = ":"; |
1147 } | 1795 } |
1148 | 1796 |
1149 lcf->host_header = inet_upstream.host_header; | 1797 plcf->host_header = inet_upstream.host_header; |
1150 lcf->uri0 = inet_upstream.uri; | 1798 plcf->port_text = inet_upstream.port_text; |
1151 #if 0 | 1799 plcf->upstream.uri = inet_upstream.uri; |
1152 STUB | 1800 } |
1153 lcf->port_text = inet_upstream.port_text; | 1801 |
1154 lcf->upstream->default_port = inet_upstream.default_port; | 1802 plcf->upstream.schema.len = sizeof("http://") - 1; |
1803 plcf->upstream.schema.data = (u_char *) "http://"; | |
1804 | |
1805 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
1806 | |
1807 clcf->handler = ngx_http_proxy_handler; | |
1808 | |
1809 #if (NGX_PCRE) | |
1810 plcf->upstream.location = clcf->regex ? &ngx_http_proxy_uri : &clcf->name; | |
1811 #else | |
1812 plcf->upstream.location = &clcf->name; | |
1155 #endif | 1813 #endif |
1156 } | 1814 |
1157 | 1815 plcf->upstream.url = *url; |
1158 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
1159 | |
1160 clcf->handler = ngx_http_proxy_handler; | |
1161 | |
1162 #if (NGX_PCRE) | |
1163 lcf->location0 = clcf->regex ? &ngx_http_proxy_uri : &clcf->name; | |
1164 #else | |
1165 lcf->location0 = &clcf->name; | |
1166 #endif | |
1167 | 1816 |
1168 if (clcf->name.data[clcf->name.len - 1] == '/') { | 1817 if (clcf->name.data[clcf->name.len - 1] == '/') { |
1169 clcf->auto_redirect = 1; | 1818 clcf->auto_redirect = 1; |
1170 } | 1819 } |
1171 | 1820 |
1172 return NGX_CONF_OK; | 1821 return NGX_CONF_OK; |
1173 } | 1822 } |
1174 | 1823 |
1175 | 1824 |
1176 static char * | 1825 static char * |
1177 ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1826 ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1178 { | 1827 { |
1828 ngx_http_proxy_loc_conf_t *plcf = conf; | |
1829 | |
1830 ngx_str_t *value; | |
1831 ngx_array_t *vars_lengths, *vars_values; | |
1832 ngx_http_script_compile_t sc; | |
1833 ngx_http_proxy_redirect_t *pr; | |
1834 | |
1835 if (plcf->redirect == 0) { | |
1836 return NGX_CONF_OK; | |
1837 } | |
1838 | |
1839 value = cf->args->elts; | |
1840 | |
1841 if (ngx_strcmp(value[1].data, "off") == 0) { | |
1842 plcf->redirect = 0; | |
1843 plcf->redirects = NULL; | |
1844 return NGX_CONF_OK; | |
1845 } | |
1846 | |
1847 if (plcf->redirects == NULL) { | |
1848 plcf->redirects = ngx_array_create(cf->pool, 1, | |
1849 sizeof(ngx_http_proxy_redirect_t)); | |
1850 if (plcf->redirects == NULL) { | |
1851 return NGX_CONF_ERROR; | |
1852 } | |
1853 } | |
1854 | |
1855 pr = ngx_array_push(plcf->redirects); | |
1856 if (pr == NULL) { | |
1857 return NGX_CONF_ERROR; | |
1858 } | |
1859 | |
1860 if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "default") == 0) { | |
1861 if (plcf->upstream.url.data == NULL) { | |
1862 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1863 "\"proxy_rewrite_location default\" must go " | |
1864 "after the \"proxy_pass\" directive"); | |
1865 return NGX_CONF_ERROR; | |
1866 } | |
1867 | |
1868 pr->handler = ngx_http_proxy_rewrite_redirect_text; | |
1869 pr->redirect = plcf->upstream.url; | |
1870 pr->replacement.text = *plcf->upstream.location; | |
1871 | |
1872 return NGX_CONF_OK; | |
1873 } | |
1874 | |
1875 if (ngx_http_script_variables_count(&value[2]) == 0) { | |
1876 pr->handler = ngx_http_proxy_rewrite_redirect_text; | |
1877 pr->redirect = value[1]; | |
1878 pr->replacement.text = value[2]; | |
1879 | |
1880 return NGX_CONF_OK; | |
1881 } | |
1882 | |
1883 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1884 | |
1885 vars_lengths = NULL; | |
1886 vars_values = NULL; | |
1887 | |
1888 sc.cf = cf; | |
1889 sc.source = &value[2]; | |
1890 sc.lengths = &vars_lengths; | |
1891 sc.values = &vars_values; | |
1892 sc.complete_lengths = 1; | |
1893 sc.complete_values = 1; | |
1894 | |
1895 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1896 return NGX_CONF_ERROR; | |
1897 } | |
1898 | |
1899 pr->handler = ngx_http_proxy_rewrite_redirect_vars; | |
1900 pr->redirect = value[1]; | |
1901 pr->replacement.vars.lengths = vars_lengths->elts; | |
1902 pr->replacement.vars.values = vars_values->elts; | |
1903 | |
1179 return NGX_CONF_OK; | 1904 return NGX_CONF_OK; |
1180 } | 1905 } |
1181 | 1906 |
1182 | 1907 |
1183 static char * | 1908 static char * |