1 | | Enable verification of the SSL certificate presented to the http_proxy_module. |
2 | | |
3 | | |
4 | | {{{ |
5 | | diff -uNr ../nginx-0.8.55/src/event/ngx_event_openssl.c src/event/ngx_event_openssl.c |
6 | | --- ../nginx-0.8.55/src/event/ngx_event_openssl.c 2010-07-29 02:30:15.000000000 -0700 |
7 | | +++ src/event/ngx_event_openssl.c 2011-09-13 15:27:08.000000000 -0700 |
8 | | @@ -157,6 +157,12 @@ |
9 | | SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG); |
10 | | SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); |
11 | | |
12 | | + /* verification options */ |
13 | | + |
14 | | + SSL_CTX_load_verify_locations(ssl->ctx, (const char *)ssl->ca_certificate.data, NULL); |
15 | | + SSL_CTX_set_verify(ssl->ctx, ssl->verify, NULL); |
16 | | + SSL_CTX_set_verify_depth(ssl->ctx, ssl->verify_depth); |
17 | | + |
18 | | /* server side options */ |
19 | | |
20 | | SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); |
21 | | diff -uNr ../nginx-0.8.55/src/event/ngx_event_openssl.h src/event/ngx_event_openssl.h |
22 | | --- ../nginx-0.8.55/src/event/ngx_event_openssl.h 2010-03-03 08:23:14.000000000 -0800 |
23 | | +++ src/event/ngx_event_openssl.h 2011-09-13 15:27:08.000000000 -0700 |
24 | | @@ -27,6 +27,9 @@ |
25 | | typedef struct { |
26 | | SSL_CTX *ctx; |
27 | | ngx_log_t *log; |
28 | | + ngx_uint_t verify; |
29 | | + ngx_uint_t verify_depth; |
30 | | + ngx_str_t ca_certificate; |
31 | | } ngx_ssl_t; |
32 | | |
33 | | |
34 | | diff -uNr ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_proxy_module.c |
35 | | --- ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c 2010-08-03 05:59:14.000000000 -0700 |
36 | | +++ src/http/modules/ngx_http_proxy_module.c 2011-09-13 15:27:08.000000000 -0700 |
37 | | @@ -441,6 +441,27 @@ |
38 | | offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse), |
39 | | NULL }, |
40 | | |
41 | | + { ngx_string("proxy_ssl_verify"), |
42 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
43 | | + ngx_conf_set_num_slot, |
44 | | + NGX_HTTP_LOC_CONF_OFFSET, |
45 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify), |
46 | | + NULL }, |
47 | | + |
48 | | + { ngx_string("proxy_ssl_verify_depth"), |
49 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
50 | | + ngx_conf_set_num_slot, |
51 | | + NGX_HTTP_LOC_CONF_OFFSET, |
52 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_depth), |
53 | | + NULL }, |
54 | | + |
55 | | + { ngx_string("proxy_ssl_ca_certificate"), |
56 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
57 | | + ngx_conf_set_str_slot, |
58 | | + NGX_HTTP_LOC_CONF_OFFSET, |
59 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_ca_certificate), |
60 | | + NULL }, |
61 | | + |
62 | | #endif |
63 | | |
64 | | ngx_null_command |
65 | | @@ -1696,6 +1717,8 @@ |
66 | | conf->upstream.intercept_errors = NGX_CONF_UNSET; |
67 | | #if (NGX_HTTP_SSL) |
68 | | conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; |
69 | | + conf->upstream.ssl_verify = NGX_CONF_UNSET_UINT; |
70 | | + conf->upstream.ssl_verify_depth = NGX_CONF_UNSET_UINT; |
71 | | #endif |
72 | | |
73 | | /* "proxy_cyclic_temp_file" is disabled */ |
74 | | @@ -1951,6 +1974,22 @@ |
75 | | #if (NGX_HTTP_SSL) |
76 | | ngx_conf_merge_value(conf->upstream.ssl_session_reuse, |
77 | | prev->upstream.ssl_session_reuse, 1); |
78 | | + ngx_conf_merge_uint_value(conf->upstream.ssl_verify, |
79 | | + prev->upstream.ssl_verify, 0); |
80 | | + ngx_conf_merge_uint_value(conf->upstream.ssl_verify_depth, |
81 | | + prev->upstream.ssl_verify_depth, 1); |
82 | | + ngx_conf_merge_str_value(conf->upstream.ssl_ca_certificate, |
83 | | + prev->upstream.ssl_ca_certificate, ""); |
84 | | + |
85 | | + if (conf->upstream.ssl_verify) { |
86 | | + if (conf->upstream.ssl_ca_certificate.len == 0) { |
87 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
88 | | + "no \"proxy_ssl_ca_certificate\" is defined for " |
89 | | + "the \"proxy_ssl_verify\" directive"); |
90 | | + |
91 | | + return NGX_CONF_ERROR; |
92 | | + } |
93 | | + } |
94 | | #endif |
95 | | |
96 | | ngx_conf_merge_value(conf->redirect, prev->redirect, 1); |
97 | | @@ -2727,6 +2766,12 @@ |
98 | | |
99 | | plcf->upstream.ssl->log = cf->log; |
100 | | |
101 | | + plcf->upstream.ssl->ca_certificate.len = plcf->upstream.ssl_ca_certificate.len; |
102 | | + plcf->upstream.ssl->ca_certificate.data = plcf->upstream.ssl_ca_certificate.data; |
103 | | + |
104 | | + plcf->upstream.ssl->verify = plcf->upstream.ssl_verify; |
105 | | + plcf->upstream.ssl->verify_depth = plcf->upstream.ssl_verify_depth; |
106 | | + |
107 | | if (ngx_ssl_create(plcf->upstream.ssl, |
108 | | NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL) |
109 | | != NGX_OK) |
110 | | diff -uNr ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c.orig src/http/modules/ngx_http_proxy_module.c.orig |
111 | | --- ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c.orig 1969-12-31 16:00:00.000000000 -0800 |
112 | | +++ src/http/modules/ngx_http_proxy_module.c.orig 2010-08-03 05:59:14.000000000 -0700 |
113 | | @@ -0,0 +1,2782 @@ |
114 | | + |
115 | | +/* |
116 | | + * Copyright (C) Igor Sysoev |
117 | | + */ |
118 | | + |
119 | | + |
120 | | +#include <ngx_config.h> |
121 | | +#include <ngx_core.h> |
122 | | +#include <ngx_http.h> |
123 | | + |
124 | | + |
125 | | +typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t; |
126 | | + |
127 | | +typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r, |
128 | | + ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr); |
129 | | + |
130 | | +struct ngx_http_proxy_redirect_s { |
131 | | + ngx_http_proxy_redirect_pt handler; |
132 | | + ngx_str_t redirect; |
133 | | + |
134 | | + union { |
135 | | + ngx_str_t text; |
136 | | + |
137 | | + struct { |
138 | | + void *lengths; |
139 | | + void *values; |
140 | | + } vars; |
141 | | + |
142 | | + void *regex; |
143 | | + } replacement; |
144 | | +}; |
145 | | + |
146 | | + |
147 | | +typedef struct { |
148 | | + ngx_str_t key_start; |
149 | | + ngx_str_t schema; |
150 | | + ngx_str_t host_header; |
151 | | + ngx_str_t port; |
152 | | + ngx_str_t uri; |
153 | | +} ngx_http_proxy_vars_t; |
154 | | + |
155 | | + |
156 | | +typedef struct { |
157 | | + ngx_http_upstream_conf_t upstream; |
158 | | + |
159 | | + ngx_array_t *flushes; |
160 | | + ngx_array_t *body_set_len; |
161 | | + ngx_array_t *body_set; |
162 | | + ngx_array_t *headers_set_len; |
163 | | + ngx_array_t *headers_set; |
164 | | + ngx_hash_t headers_set_hash; |
165 | | + |
166 | | + ngx_array_t *headers_source; |
167 | | + |
168 | | + ngx_array_t *proxy_lengths; |
169 | | + ngx_array_t *proxy_values; |
170 | | + |
171 | | + ngx_array_t *redirects; |
172 | | + |
173 | | + ngx_str_t body_source; |
174 | | + |
175 | | + ngx_str_t method; |
176 | | + ngx_str_t location; |
177 | | + ngx_str_t url; |
178 | | + |
179 | | +#if (NGX_HTTP_CACHE) |
180 | | + ngx_http_complex_value_t cache_key; |
181 | | +#endif |
182 | | + |
183 | | + ngx_http_proxy_vars_t vars; |
184 | | + |
185 | | + ngx_flag_t redirect; |
186 | | + |
187 | | + ngx_uint_t headers_hash_max_size; |
188 | | + ngx_uint_t headers_hash_bucket_size; |
189 | | +} ngx_http_proxy_loc_conf_t; |
190 | | + |
191 | | + |
192 | | +typedef struct { |
193 | | + ngx_http_status_t status; |
194 | | + ngx_http_proxy_vars_t vars; |
195 | | + size_t internal_body_length; |
196 | | +} ngx_http_proxy_ctx_t; |
197 | | + |
198 | | + |
199 | | +static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r, |
200 | | + ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf); |
201 | | +#if (NGX_HTTP_CACHE) |
202 | | +static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r); |
203 | | +#endif |
204 | | +static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r); |
205 | | +static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r); |
206 | | +static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r); |
207 | | +static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); |
208 | | +static void ngx_http_proxy_abort_request(ngx_http_request_t *r); |
209 | | +static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, |
210 | | + ngx_int_t rc); |
211 | | + |
212 | | +static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r, |
213 | | + ngx_http_variable_value_t *v, uintptr_t data); |
214 | | +static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r, |
215 | | + ngx_http_variable_value_t *v, uintptr_t data); |
216 | | +static ngx_int_t |
217 | | + ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, |
218 | | + ngx_http_variable_value_t *v, uintptr_t data); |
219 | | +static ngx_int_t |
220 | | + ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, |
221 | | + ngx_http_variable_value_t *v, uintptr_t data); |
222 | | +static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, |
223 | | + ngx_table_elt_t *h, size_t prefix); |
224 | | + |
225 | | +static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); |
226 | | +static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); |
227 | | +static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, |
228 | | + void *parent, void *child); |
229 | | +static ngx_int_t ngx_http_proxy_merge_headers(ngx_conf_t *cf, |
230 | | + ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev); |
231 | | + |
232 | | +static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
233 | | + void *conf); |
234 | | +static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, |
235 | | + void *conf); |
236 | | +static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, |
237 | | + void *conf); |
238 | | +#if (NGX_HTTP_CACHE) |
239 | | +static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
240 | | + void *conf); |
241 | | +static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, |
242 | | + void *conf); |
243 | | +#endif |
244 | | + |
245 | | +static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); |
246 | | + |
247 | | +#if (NGX_HTTP_SSL) |
248 | | +static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, |
249 | | + ngx_http_proxy_loc_conf_t *plcf); |
250 | | +#endif |
251 | | +static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v); |
252 | | + |
253 | | + |
254 | | +static ngx_conf_post_t ngx_http_proxy_lowat_post = |
255 | | + { ngx_http_proxy_lowat_check }; |
256 | | + |
257 | | + |
258 | | +static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { |
259 | | + { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, |
260 | | + { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, |
261 | | + { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, |
262 | | + { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, |
263 | | + { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 }, |
264 | | + { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, |
265 | | + { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 }, |
266 | | + { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, |
267 | | + { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, |
268 | | + { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, |
269 | | + { ngx_null_string, 0 } |
270 | | +}; |
271 | | + |
272 | | + |
273 | | +ngx_module_t ngx_http_proxy_module; |
274 | | + |
275 | | + |
276 | | +static ngx_command_t ngx_http_proxy_commands[] = { |
277 | | + |
278 | | + { ngx_string("proxy_pass"), |
279 | | + NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, |
280 | | + ngx_http_proxy_pass, |
281 | | + NGX_HTTP_LOC_CONF_OFFSET, |
282 | | + 0, |
283 | | + NULL }, |
284 | | + |
285 | | + { ngx_string("proxy_redirect"), |
286 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, |
287 | | + ngx_http_proxy_redirect, |
288 | | + NGX_HTTP_LOC_CONF_OFFSET, |
289 | | + 0, |
290 | | + NULL }, |
291 | | + |
292 | | + { ngx_string("proxy_store"), |
293 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
294 | | + ngx_http_proxy_store, |
295 | | + NGX_HTTP_LOC_CONF_OFFSET, |
296 | | + 0, |
297 | | + NULL }, |
298 | | + |
299 | | + { ngx_string("proxy_store_access"), |
300 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, |
301 | | + ngx_conf_set_access_slot, |
302 | | + NGX_HTTP_LOC_CONF_OFFSET, |
303 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access), |
304 | | + NULL }, |
305 | | + |
306 | | + { ngx_string("proxy_buffering"), |
307 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
308 | | + ngx_conf_set_flag_slot, |
309 | | + NGX_HTTP_LOC_CONF_OFFSET, |
310 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering), |
311 | | + NULL }, |
312 | | + |
313 | | + { ngx_string("proxy_ignore_client_abort"), |
314 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
315 | | + ngx_conf_set_flag_slot, |
316 | | + NGX_HTTP_LOC_CONF_OFFSET, |
317 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort), |
318 | | + NULL }, |
319 | | + |
320 | | + { ngx_string("proxy_bind"), |
321 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
322 | | + ngx_http_upstream_bind_set_slot, |
323 | | + NGX_HTTP_LOC_CONF_OFFSET, |
324 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.local), |
325 | | + NULL }, |
326 | | + |
327 | | + { ngx_string("proxy_connect_timeout"), |
328 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
329 | | + ngx_conf_set_msec_slot, |
330 | | + NGX_HTTP_LOC_CONF_OFFSET, |
331 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout), |
332 | | + NULL }, |
333 | | + |
334 | | + { ngx_string("proxy_send_timeout"), |
335 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
336 | | + ngx_conf_set_msec_slot, |
337 | | + NGX_HTTP_LOC_CONF_OFFSET, |
338 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout), |
339 | | + NULL }, |
340 | | + |
341 | | + { ngx_string("proxy_send_lowat"), |
342 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
343 | | + ngx_conf_set_size_slot, |
344 | | + NGX_HTTP_LOC_CONF_OFFSET, |
345 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat), |
346 | | + &ngx_http_proxy_lowat_post }, |
347 | | + |
348 | | + { ngx_string("proxy_intercept_errors"), |
349 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
350 | | + ngx_conf_set_flag_slot, |
351 | | + NGX_HTTP_LOC_CONF_OFFSET, |
352 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors), |
353 | | + NULL }, |
354 | | + |
355 | | + { ngx_string("proxy_set_header"), |
356 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, |
357 | | + ngx_conf_set_keyval_slot, |
358 | | + NGX_HTTP_LOC_CONF_OFFSET, |
359 | | + offsetof(ngx_http_proxy_loc_conf_t, headers_source), |
360 | | + NULL }, |
361 | | + |
362 | | + { ngx_string("proxy_headers_hash_max_size"), |
363 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
364 | | + ngx_conf_set_num_slot, |
365 | | + NGX_HTTP_LOC_CONF_OFFSET, |
366 | | + offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size), |
367 | | + NULL }, |
368 | | + |
369 | | + { ngx_string("proxy_headers_hash_bucket_size"), |
370 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
371 | | + ngx_conf_set_num_slot, |
372 | | + NGX_HTTP_LOC_CONF_OFFSET, |
373 | | + offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size), |
374 | | + NULL }, |
375 | | + |
376 | | + { ngx_string("proxy_set_body"), |
377 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
378 | | + ngx_conf_set_str_slot, |
379 | | + NGX_HTTP_LOC_CONF_OFFSET, |
380 | | + offsetof(ngx_http_proxy_loc_conf_t, body_source), |
381 | | + NULL }, |
382 | | + |
383 | | + { ngx_string("proxy_method"), |
384 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
385 | | + ngx_conf_set_str_slot, |
386 | | + NGX_HTTP_LOC_CONF_OFFSET, |
387 | | + offsetof(ngx_http_proxy_loc_conf_t, method), |
388 | | + NULL }, |
389 | | + |
390 | | + { ngx_string("proxy_pass_request_headers"), |
391 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
392 | | + ngx_conf_set_flag_slot, |
393 | | + NGX_HTTP_LOC_CONF_OFFSET, |
394 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers), |
395 | | + NULL }, |
396 | | + |
397 | | + { ngx_string("proxy_pass_request_body"), |
398 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
399 | | + ngx_conf_set_flag_slot, |
400 | | + NGX_HTTP_LOC_CONF_OFFSET, |
401 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body), |
402 | | + NULL }, |
403 | | + |
404 | | + { ngx_string("proxy_buffer_size"), |
405 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
406 | | + ngx_conf_set_size_slot, |
407 | | + NGX_HTTP_LOC_CONF_OFFSET, |
408 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size), |
409 | | + NULL }, |
410 | | + |
411 | | + { ngx_string("proxy_read_timeout"), |
412 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
413 | | + ngx_conf_set_msec_slot, |
414 | | + NGX_HTTP_LOC_CONF_OFFSET, |
415 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout), |
416 | | + NULL }, |
417 | | + |
418 | | + { ngx_string("proxy_buffers"), |
419 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, |
420 | | + ngx_conf_set_bufs_slot, |
421 | | + NGX_HTTP_LOC_CONF_OFFSET, |
422 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs), |
423 | | + NULL }, |
424 | | + |
425 | | + { ngx_string("proxy_busy_buffers_size"), |
426 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
427 | | + ngx_conf_set_size_slot, |
428 | | + NGX_HTTP_LOC_CONF_OFFSET, |
429 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf), |
430 | | + NULL }, |
431 | | + |
432 | | +#if (NGX_HTTP_CACHE) |
433 | | + |
434 | | + { ngx_string("proxy_cache"), |
435 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
436 | | + ngx_http_proxy_cache, |
437 | | + NGX_HTTP_LOC_CONF_OFFSET, |
438 | | + 0, |
439 | | + NULL }, |
440 | | + |
441 | | + { ngx_string("proxy_cache_key"), |
442 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
443 | | + ngx_http_proxy_cache_key, |
444 | | + NGX_HTTP_LOC_CONF_OFFSET, |
445 | | + 0, |
446 | | + NULL }, |
447 | | + |
448 | | + { ngx_string("proxy_cache_path"), |
449 | | + NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, |
450 | | + ngx_http_file_cache_set_slot, |
451 | | + 0, |
452 | | + 0, |
453 | | + &ngx_http_proxy_module }, |
454 | | + |
455 | | + { ngx_string("proxy_cache_bypass"), |
456 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
457 | | + ngx_http_set_predicate_slot, |
458 | | + NGX_HTTP_LOC_CONF_OFFSET, |
459 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass), |
460 | | + NULL }, |
461 | | + |
462 | | + { ngx_string("proxy_no_cache"), |
463 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
464 | | + ngx_http_set_predicate_slot, |
465 | | + NGX_HTTP_LOC_CONF_OFFSET, |
466 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache), |
467 | | + NULL }, |
468 | | + |
469 | | + { ngx_string("proxy_cache_valid"), |
470 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
471 | | + ngx_http_file_cache_valid_set_slot, |
472 | | + NGX_HTTP_LOC_CONF_OFFSET, |
473 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid), |
474 | | + NULL }, |
475 | | + |
476 | | + { ngx_string("proxy_cache_min_uses"), |
477 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
478 | | + ngx_conf_set_num_slot, |
479 | | + NGX_HTTP_LOC_CONF_OFFSET, |
480 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses), |
481 | | + NULL }, |
482 | | + |
483 | | + { ngx_string("proxy_cache_use_stale"), |
484 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
485 | | + ngx_conf_set_bitmask_slot, |
486 | | + NGX_HTTP_LOC_CONF_OFFSET, |
487 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale), |
488 | | + &ngx_http_proxy_next_upstream_masks }, |
489 | | + |
490 | | + { ngx_string("proxy_cache_methods"), |
491 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
492 | | + ngx_conf_set_bitmask_slot, |
493 | | + NGX_HTTP_LOC_CONF_OFFSET, |
494 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods), |
495 | | + &ngx_http_upstream_cache_method_mask }, |
496 | | + |
497 | | +#endif |
498 | | + |
499 | | + { ngx_string("proxy_temp_path"), |
500 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, |
501 | | + ngx_conf_set_path_slot, |
502 | | + NGX_HTTP_LOC_CONF_OFFSET, |
503 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path), |
504 | | + NULL }, |
505 | | + |
506 | | + { ngx_string("proxy_max_temp_file_size"), |
507 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
508 | | + ngx_conf_set_size_slot, |
509 | | + NGX_HTTP_LOC_CONF_OFFSET, |
510 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf), |
511 | | + NULL }, |
512 | | + |
513 | | + { ngx_string("proxy_temp_file_write_size"), |
514 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
515 | | + ngx_conf_set_size_slot, |
516 | | + NGX_HTTP_LOC_CONF_OFFSET, |
517 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf), |
518 | | + NULL }, |
519 | | + |
520 | | + { ngx_string("proxy_next_upstream"), |
521 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
522 | | + ngx_conf_set_bitmask_slot, |
523 | | + NGX_HTTP_LOC_CONF_OFFSET, |
524 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream), |
525 | | + &ngx_http_proxy_next_upstream_masks }, |
526 | | + |
527 | | + { ngx_string("proxy_pass_header"), |
528 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
529 | | + ngx_conf_set_str_array_slot, |
530 | | + NGX_HTTP_LOC_CONF_OFFSET, |
531 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers), |
532 | | + NULL }, |
533 | | + |
534 | | + { ngx_string("proxy_hide_header"), |
535 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
536 | | + ngx_conf_set_str_array_slot, |
537 | | + NGX_HTTP_LOC_CONF_OFFSET, |
538 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers), |
539 | | + NULL }, |
540 | | + |
541 | | + { ngx_string("proxy_ignore_headers"), |
542 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
543 | | + ngx_conf_set_bitmask_slot, |
544 | | + NGX_HTTP_LOC_CONF_OFFSET, |
545 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers), |
546 | | + &ngx_http_upstream_ignore_headers_masks }, |
547 | | + |
548 | | +#if (NGX_HTTP_SSL) |
549 | | + |
550 | | + { ngx_string("proxy_ssl_session_reuse"), |
551 | | + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
552 | | + ngx_conf_set_flag_slot, |
553 | | + NGX_HTTP_LOC_CONF_OFFSET, |
554 | | + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse), |
555 | | + NULL }, |
556 | | + |
557 | | +#endif |
558 | | + |
559 | | + ngx_null_command |
560 | | +}; |
561 | | + |
562 | | + |
563 | | +static ngx_http_module_t ngx_http_proxy_module_ctx = { |
564 | | + ngx_http_proxy_add_variables, /* preconfiguration */ |
565 | | + NULL, /* postconfiguration */ |
566 | | + |
567 | | + NULL, /* create main configuration */ |
568 | | + NULL, /* init main configuration */ |
569 | | + |
570 | | + NULL, /* create server configuration */ |
571 | | + NULL, /* merge server configuration */ |
572 | | + |
573 | | + ngx_http_proxy_create_loc_conf, /* create location configration */ |
574 | | + ngx_http_proxy_merge_loc_conf /* merge location configration */ |
575 | | +}; |
576 | | + |
577 | | + |
578 | | +ngx_module_t ngx_http_proxy_module = { |
579 | | + NGX_MODULE_V1, |
580 | | + &ngx_http_proxy_module_ctx, /* module context */ |
581 | | + ngx_http_proxy_commands, /* module directives */ |
582 | | + NGX_HTTP_MODULE, /* module type */ |
583 | | + NULL, /* init master */ |
584 | | + NULL, /* init module */ |
585 | | + NULL, /* init process */ |
586 | | + NULL, /* init thread */ |
587 | | + NULL, /* exit thread */ |
588 | | + NULL, /* exit process */ |
589 | | + NULL, /* exit master */ |
590 | | + NGX_MODULE_V1_PADDING |
591 | | +}; |
592 | | + |
593 | | + |
594 | | +static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF; |
595 | | + |
596 | | + |
597 | | +static ngx_keyval_t ngx_http_proxy_headers[] = { |
598 | | + { ngx_string("Host"), ngx_string("$proxy_host") }, |
599 | | + { ngx_string("Connection"), ngx_string("close") }, |
600 | | + { ngx_string("Keep-Alive"), ngx_string("") }, |
601 | | + { ngx_string("Expect"), ngx_string("") }, |
602 | | + { ngx_null_string, ngx_null_string } |
603 | | +}; |
604 | | + |
605 | | + |
606 | | +static ngx_str_t ngx_http_proxy_hide_headers[] = { |
607 | | + ngx_string("Date"), |
608 | | + ngx_string("Server"), |
609 | | + ngx_string("X-Pad"), |
610 | | + ngx_string("X-Accel-Expires"), |
611 | | + ngx_string("X-Accel-Redirect"), |
612 | | + ngx_string("X-Accel-Limit-Rate"), |
613 | | + ngx_string("X-Accel-Buffering"), |
614 | | + ngx_string("X-Accel-Charset"), |
615 | | + ngx_null_string |
616 | | +}; |
617 | | + |
618 | | + |
619 | | +#if (NGX_HTTP_CACHE) |
620 | | + |
621 | | +static ngx_keyval_t ngx_http_proxy_cache_headers[] = { |
622 | | + { ngx_string("Host"), ngx_string("$proxy_host") }, |
623 | | + { ngx_string("Connection"), ngx_string("close") }, |
624 | | + { ngx_string("Keep-Alive"), ngx_string("") }, |
625 | | + { ngx_string("Expect"), ngx_string("") }, |
626 | | + { ngx_string("If-Modified-Since"), ngx_string("") }, |
627 | | + { ngx_string("If-Unmodified-Since"), ngx_string("") }, |
628 | | + { ngx_string("If-None-Match"), ngx_string("") }, |
629 | | + { ngx_string("If-Match"), ngx_string("") }, |
630 | | + { ngx_string("Range"), ngx_string("") }, |
631 | | + { ngx_string("If-Range"), ngx_string("") }, |
632 | | + { ngx_null_string, ngx_null_string } |
633 | | +}; |
634 | | + |
635 | | +#endif |
636 | | + |
637 | | + |
638 | | +static ngx_http_variable_t ngx_http_proxy_vars[] = { |
639 | | + |
640 | | + { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0, |
641 | | + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, |
642 | | + |
643 | | + { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0, |
644 | | + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, |
645 | | + |
646 | | + { ngx_string("proxy_add_x_forwarded_for"), NULL, |
647 | | + ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, |
648 | | + |
649 | | +#if 0 |
650 | | + { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 }, |
651 | | +#endif |
652 | | + |
653 | | + { ngx_string("proxy_internal_body_length"), NULL, |
654 | | + ngx_http_proxy_internal_body_length_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, |
655 | | + |
656 | | + { ngx_null_string, NULL, NULL, 0, 0, 0 } |
657 | | +}; |
658 | | + |
659 | | + |
660 | | +static ngx_path_init_t ngx_http_proxy_temp_path = { |
661 | | + ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 } |
662 | | +}; |
663 | | + |
664 | | + |
665 | | +static ngx_int_t |
666 | | +ngx_http_proxy_handler(ngx_http_request_t *r) |
667 | | +{ |
668 | | + ngx_int_t rc; |
669 | | + ngx_http_upstream_t *u; |
670 | | + ngx_http_proxy_ctx_t *ctx; |
671 | | + ngx_http_proxy_loc_conf_t *plcf; |
672 | | + |
673 | | + if (ngx_http_upstream_create(r) != NGX_OK) { |
674 | | + return NGX_HTTP_INTERNAL_SERVER_ERROR; |
675 | | + } |
676 | | + |
677 | | + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t)); |
678 | | + if (ctx == NULL) { |
679 | | + return NGX_ERROR; |
680 | | + } |
681 | | + |
682 | | + ngx_http_set_ctx(r, ctx, ngx_http_proxy_module); |
683 | | + |
684 | | + plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
685 | | + |
686 | | + u = r->upstream; |
687 | | + |
688 | | + if (plcf->proxy_lengths == NULL) { |
689 | | + ctx->vars = plcf->vars; |
690 | | + u->schema = plcf->vars.schema; |
691 | | +#if (NGX_HTTP_SSL) |
692 | | + u->ssl = (plcf->upstream.ssl != NULL); |
693 | | +#endif |
694 | | + |
695 | | + } else { |
696 | | + if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) { |
697 | | + return NGX_HTTP_INTERNAL_SERVER_ERROR; |
698 | | + } |
699 | | + } |
700 | | + |
701 | | + u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module; |
702 | | + |
703 | | + u->conf = &plcf->upstream; |
704 | | + |
705 | | +#if (NGX_HTTP_CACHE) |
706 | | + u->create_key = ngx_http_proxy_create_key; |
707 | | +#endif |
708 | | + u->create_request = ngx_http_proxy_create_request; |
709 | | + u->reinit_request = ngx_http_proxy_reinit_request; |
710 | | + u->process_header = ngx_http_proxy_process_status_line; |
711 | | + u->abort_request = ngx_http_proxy_abort_request; |
712 | | + u->finalize_request = ngx_http_proxy_finalize_request; |
713 | | + r->state = 0; |
714 | | + |
715 | | + if (plcf->redirects) { |
716 | | + u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; |
717 | | + } |
718 | | + |
719 | | + u->buffering = plcf->upstream.buffering; |
720 | | + |
721 | | + u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); |
722 | | + if (u->pipe == NULL) { |
723 | | + return NGX_HTTP_INTERNAL_SERVER_ERROR; |
724 | | + } |
725 | | + |
726 | | + u->pipe->input_filter = ngx_event_pipe_copy_input_filter; |
727 | | + |
728 | | + u->accel = 1; |
729 | | + |
730 | | + rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); |
731 | | + |
732 | | + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
733 | | + return rc; |
734 | | + } |
735 | | + |
736 | | + return NGX_DONE; |
737 | | +} |
738 | | + |
739 | | + |
740 | | +static ngx_int_t |
741 | | +ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx, |
742 | | + ngx_http_proxy_loc_conf_t *plcf) |
743 | | +{ |
744 | | + u_char *p; |
745 | | + size_t add; |
746 | | + u_short port; |
747 | | + ngx_str_t proxy; |
748 | | + ngx_url_t url; |
749 | | + ngx_http_upstream_t *u; |
750 | | + |
751 | | + if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0, |
752 | | + plcf->proxy_values->elts) |
753 | | + == NULL) |
754 | | + { |
755 | | + return NGX_ERROR; |
756 | | + } |
757 | | + |
758 | | + if (ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0) { |
759 | | + |
760 | | + add = 7; |
761 | | + port = 80; |
762 | | + |
763 | | +#if (NGX_HTTP_SSL) |
764 | | + |
765 | | + } else if (ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0) { |
766 | | + |
767 | | + add = 8; |
768 | | + port = 443; |
769 | | + r->upstream->ssl = 1; |
770 | | + |
771 | | +#endif |
772 | | + |
773 | | + } else { |
774 | | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
775 | | + "invalid URL prefix in \"%V\"", &proxy); |
776 | | + return NGX_ERROR; |
777 | | + } |
778 | | + |
779 | | + u = r->upstream; |
780 | | + |
781 | | + u->schema.len = add; |
782 | | + u->schema.data = proxy.data; |
783 | | + |
784 | | + ngx_memzero(&url, sizeof(ngx_url_t)); |
785 | | + |
786 | | + url.url.len = proxy.len - add; |
787 | | + url.url.data = proxy.data + add; |
788 | | + url.default_port = port; |
789 | | + url.uri_part = 1; |
790 | | + url.no_resolve = 1; |
791 | | + |
792 | | + if (ngx_parse_url(r->pool, &url) != NGX_OK) { |
793 | | + if (url.err) { |
794 | | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
795 | | + "%s in upstream \"%V\"", url.err, &url.url); |
796 | | + } |
797 | | + |
798 | | + return NGX_ERROR; |
799 | | + } |
800 | | + |
801 | | + if (url.uri.len) { |
802 | | + if (url.uri.data[0] == '?') { |
803 | | + p = ngx_pnalloc(r->pool, url.uri.len + 1); |
804 | | + if (p == NULL) { |
805 | | + return NGX_ERROR; |
806 | | + } |
807 | | + |
808 | | + *p++ = '/'; |
809 | | + ngx_memcpy(p, url.uri.data, url.uri.len); |
810 | | + |
811 | | + url.uri.len++; |
812 | | + url.uri.data = p - 1; |
813 | | + } |
814 | | + |
815 | | + } else { |
816 | | + url.uri = r->unparsed_uri; |
817 | | + } |
818 | | + |
819 | | + ctx->vars.key_start = u->schema; |
820 | | + |
821 | | + ngx_http_proxy_set_vars(&url, &ctx->vars); |
822 | | + |
823 | | + u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); |
824 | | + if (u->resolved == NULL) { |
825 | | + return NGX_ERROR; |
826 | | + } |
827 | | + |
828 | | + if (url.addrs && url.addrs[0].sockaddr) { |
829 | | + u->resolved->sockaddr = url.addrs[0].sockaddr; |
830 | | + u->resolved->socklen = url.addrs[0].socklen; |
831 | | + u->resolved->naddrs = 1; |
832 | | + u->resolved->host = url.addrs[0].name; |
833 | | + |
834 | | + } else { |
835 | | + u->resolved->host = url.host; |
836 | | + u->resolved->port = (in_port_t) (url.no_port ? port : url.port); |
837 | | + u->resolved->no_port = url.no_port; |
838 | | + } |
839 | | + |
840 | | + return NGX_OK; |
841 | | +} |
842 | | + |
843 | | + |
844 | | +#if (NGX_HTTP_CACHE) |
845 | | + |
846 | | +static ngx_int_t |
847 | | +ngx_http_proxy_create_key(ngx_http_request_t *r) |
848 | | +{ |
849 | | + size_t len, loc_len; |
850 | | + u_char *p; |
851 | | + uintptr_t escape; |
852 | | + ngx_str_t *key; |
853 | | + ngx_http_upstream_t *u; |
854 | | + ngx_http_proxy_ctx_t *ctx; |
855 | | + ngx_http_proxy_loc_conf_t *plcf; |
856 | | + |
857 | | + u = r->upstream; |
858 | | + |
859 | | + plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
860 | | + |
861 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
862 | | + |
863 | | + key = ngx_array_push(&r->cache->keys); |
864 | | + if (key == NULL) { |
865 | | + return NGX_ERROR; |
866 | | + } |
867 | | + |
868 | | + if (plcf->cache_key.value.len) { |
869 | | + |
870 | | + if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) { |
871 | | + return NGX_ERROR; |
872 | | + } |
873 | | + |
874 | | + return NGX_OK; |
875 | | + } |
876 | | + |
877 | | + *key = ctx->vars.key_start; |
878 | | + |
879 | | + key = ngx_array_push(&r->cache->keys); |
880 | | + if (key == NULL) { |
881 | | + return NGX_ERROR; |
882 | | + } |
883 | | + |
884 | | + if (plcf->proxy_lengths) { |
885 | | + |
886 | | + *key = ctx->vars.uri; |
887 | | + u->uri = ctx->vars.uri; |
888 | | + |
889 | | + return NGX_OK; |
890 | | + |
891 | | + } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main) |
892 | | + { |
893 | | + *key = r->unparsed_uri; |
894 | | + u->uri = r->unparsed_uri; |
895 | | + |
896 | | + return NGX_OK; |
897 | | + } |
898 | | + |
899 | | + loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0; |
900 | | + |
901 | | + if (r->quoted_uri || r->internal) { |
902 | | + escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, |
903 | | + r->uri.len - loc_len, NGX_ESCAPE_URI); |
904 | | + } else { |
905 | | + escape = 0; |
906 | | + } |
907 | | + |
908 | | + len = ctx->vars.uri.len + r->uri.len - loc_len + escape |
909 | | + + sizeof("?") - 1 + r->args.len; |
910 | | + |
911 | | + p = ngx_pnalloc(r->pool, len); |
912 | | + if (p == NULL) { |
913 | | + return NGX_ERROR; |
914 | | + } |
915 | | + |
916 | | + key->data = p; |
917 | | + |
918 | | + if (r->valid_location) { |
919 | | + p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len); |
920 | | + } |
921 | | + |
922 | | + if (escape) { |
923 | | + ngx_escape_uri(p, r->uri.data + loc_len, |
924 | | + r->uri.len - loc_len, NGX_ESCAPE_URI); |
925 | | + p += r->uri.len - loc_len + escape; |
926 | | + |
927 | | + } else { |
928 | | + p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len); |
929 | | + } |
930 | | + |
931 | | + if (r->args.len > 0) { |
932 | | + *p++ = '?'; |
933 | | + p = ngx_copy(p, r->args.data, r->args.len); |
934 | | + } |
935 | | + |
936 | | + key->len = p - key->data; |
937 | | + u->uri = *key; |
938 | | + |
939 | | + return NGX_OK; |
940 | | +} |
941 | | + |
942 | | +#endif |
943 | | + |
944 | | + |
945 | | +static ngx_int_t |
946 | | +ngx_http_proxy_create_request(ngx_http_request_t *r) |
947 | | +{ |
948 | | + size_t len, uri_len, loc_len, body_len; |
949 | | + uintptr_t escape; |
950 | | + ngx_buf_t *b; |
951 | | + ngx_str_t method; |
952 | | + ngx_uint_t i, unparsed_uri; |
953 | | + ngx_chain_t *cl, *body; |
954 | | + ngx_list_part_t *part; |
955 | | + ngx_table_elt_t *header; |
956 | | + ngx_http_upstream_t *u; |
957 | | + ngx_http_proxy_ctx_t *ctx; |
958 | | + ngx_http_script_code_pt code; |
959 | | + ngx_http_script_engine_t e, le; |
960 | | + ngx_http_proxy_loc_conf_t *plcf; |
961 | | + ngx_http_script_len_code_pt lcode; |
962 | | + |
963 | | + u = r->upstream; |
964 | | + |
965 | | + plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
966 | | + |
967 | | + if (u->method.len) { |
968 | | + /* HEAD was changed to GET to cache response */ |
969 | | + method = u->method; |
970 | | + method.len++; |
971 | | + |
972 | | + } else if (plcf->method.len) { |
973 | | + method = plcf->method; |
974 | | + |
975 | | + } else { |
976 | | + method = r->method_name; |
977 | | + method.len++; |
978 | | + } |
979 | | + |
980 | | + len = method.len + sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; |
981 | | + |
982 | | + escape = 0; |
983 | | + loc_len = 0; |
984 | | + unparsed_uri = 0; |
985 | | + |
986 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
987 | | + |
988 | | + if (plcf->proxy_lengths) { |
989 | | + uri_len = ctx->vars.uri.len; |
990 | | + |
991 | | + } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main) |
992 | | + { |
993 | | + unparsed_uri = 1; |
994 | | + uri_len = r->unparsed_uri.len; |
995 | | + |
996 | | + } else { |
997 | | + loc_len = (r->valid_location && ctx->vars.uri.len) ? |
998 | | + plcf->location.len : 0; |
999 | | + |
1000 | | + if (r->quoted_uri || r->space_in_uri || r->internal) { |
1001 | | + escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, |
1002 | | + r->uri.len - loc_len, NGX_ESCAPE_URI); |
1003 | | + } |
1004 | | + |
1005 | | + uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape |
1006 | | + + sizeof("?") - 1 + r->args.len; |
1007 | | + } |
1008 | | + |
1009 | | + if (uri_len == 0) { |
1010 | | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1011 | | + "zero length URI to proxy"); |
1012 | | + return NGX_ERROR; |
1013 | | + } |
1014 | | + |
1015 | | + len += uri_len; |
1016 | | + |
1017 | | + ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes); |
1018 | | + |
1019 | | + if (plcf->body_set_len) { |
1020 | | + le.ip = plcf->body_set_len->elts; |
1021 | | + le.request = r; |
1022 | | + le.flushed = 1; |
1023 | | + body_len = 0; |
1024 | | + |
1025 | | + while (*(uintptr_t *) le.ip) { |
1026 | | + lcode = *(ngx_http_script_len_code_pt *) le.ip; |
1027 | | + body_len += lcode(&le); |
1028 | | + } |
1029 | | + |
1030 | | + ctx->internal_body_length = body_len; |
1031 | | + len += body_len; |
1032 | | + } |
1033 | | + |
1034 | | + le.ip = plcf->headers_set_len->elts; |
1035 | | + le.request = r; |
1036 | | + le.flushed = 1; |
1037 | | + |
1038 | | + while (*(uintptr_t *) le.ip) { |
1039 | | + while (*(uintptr_t *) le.ip) { |
1040 | | + lcode = *(ngx_http_script_len_code_pt *) le.ip; |
1041 | | + len += lcode(&le); |
1042 | | + } |
1043 | | + le.ip += sizeof(uintptr_t); |
1044 | | + } |
1045 | | + |
1046 | | + |
1047 | | + if (plcf->upstream.pass_request_headers) { |
1048 | | + part = &r->headers_in.headers.part; |
1049 | | + header = part->elts; |
1050 | | + |
1051 | | + for (i = 0; /* void */; i++) { |
1052 | | + |
1053 | | + if (i >= part->nelts) { |
1054 | | + if (part->next == NULL) { |
1055 | | + break; |
1056 | | + } |
1057 | | + |
1058 | | + part = part->next; |
1059 | | + header = part->elts; |
1060 | | + i = 0; |
1061 | | + } |
1062 | | + |
1063 | | + if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash, |
1064 | | + header[i].lowcase_key, header[i].key.len)) |
1065 | | + { |
1066 | | + continue; |
1067 | | + } |
1068 | | + |
1069 | | + len += header[i].key.len + sizeof(": ") - 1 |
1070 | | + + header[i].value.len + sizeof(CRLF) - 1; |
1071 | | + } |
1072 | | + } |
1073 | | + |
1074 | | + |
1075 | | + b = ngx_create_temp_buf(r->pool, len); |
1076 | | + if (b == NULL) { |
1077 | | + return NGX_ERROR; |
1078 | | + } |
1079 | | + |
1080 | | + cl = ngx_alloc_chain_link(r->pool); |
1081 | | + if (cl == NULL) { |
1082 | | + return NGX_ERROR; |
1083 | | + } |
1084 | | + |
1085 | | + cl->buf = b; |
1086 | | + |
1087 | | + |
1088 | | + /* the request line */ |
1089 | | + |
1090 | | + b->last = ngx_copy(b->last, method.data, method.len); |
1091 | | + |
1092 | | + u->uri.data = b->last; |
1093 | | + |
1094 | | + if (plcf->proxy_lengths) { |
1095 | | + b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len); |
1096 | | + |
1097 | | + } else if (unparsed_uri) { |
1098 | | + b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len); |
1099 | | + |
1100 | | + } else { |
1101 | | + if (r->valid_location) { |
1102 | | + b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len); |
1103 | | + } |
1104 | | + |
1105 | | + if (escape) { |
1106 | | + ngx_escape_uri(b->last, r->uri.data + loc_len, |
1107 | | + r->uri.len - loc_len, NGX_ESCAPE_URI); |
1108 | | + b->last += r->uri.len - loc_len + escape; |
1109 | | + |
1110 | | + } else { |
1111 | | + b->last = ngx_copy(b->last, r->uri.data + loc_len, |
1112 | | + r->uri.len - loc_len); |
1113 | | + } |
1114 | | + |
1115 | | + if (r->args.len > 0) { |
1116 | | + *b->last++ = '?'; |
1117 | | + b->last = ngx_copy(b->last, r->args.data, r->args.len); |
1118 | | + } |
1119 | | + } |
1120 | | + |
1121 | | + u->uri.len = b->last - u->uri.data; |
1122 | | + |
1123 | | + b->last = ngx_cpymem(b->last, ngx_http_proxy_version, |
1124 | | + sizeof(ngx_http_proxy_version) - 1); |
1125 | | + |
1126 | | + ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); |
1127 | | + |
1128 | | + e.ip = plcf->headers_set->elts; |
1129 | | + e.pos = b->last; |
1130 | | + e.request = r; |
1131 | | + e.flushed = 1; |
1132 | | + |
1133 | | + le.ip = plcf->headers_set_len->elts; |
1134 | | + |
1135 | | + while (*(uintptr_t *) le.ip) { |
1136 | | + lcode = *(ngx_http_script_len_code_pt *) le.ip; |
1137 | | + |
1138 | | + /* skip the header line name length */ |
1139 | | + (void) lcode(&le); |
1140 | | + |
1141 | | + if (*(ngx_http_script_len_code_pt *) le.ip) { |
1142 | | + |
1143 | | + for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { |
1144 | | + lcode = *(ngx_http_script_len_code_pt *) le.ip; |
1145 | | + } |
1146 | | + |
1147 | | + e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0; |
1148 | | + |
1149 | | + } else { |
1150 | | + e.skip = 0; |
1151 | | + } |
1152 | | + |
1153 | | + le.ip += sizeof(uintptr_t); |
1154 | | + |
1155 | | + while (*(uintptr_t *) e.ip) { |
1156 | | + code = *(ngx_http_script_code_pt *) e.ip; |
1157 | | + code((ngx_http_script_engine_t *) &e); |
1158 | | + } |
1159 | | + e.ip += sizeof(uintptr_t); |
1160 | | + } |
1161 | | + |
1162 | | + b->last = e.pos; |
1163 | | + |
1164 | | + |
1165 | | + if (plcf->upstream.pass_request_headers) { |
1166 | | + part = &r->headers_in.headers.part; |
1167 | | + header = part->elts; |
1168 | | + |
1169 | | + for (i = 0; /* void */; i++) { |
1170 | | + |
1171 | | + if (i >= part->nelts) { |
1172 | | + if (part->next == NULL) { |
1173 | | + break; |
1174 | | + } |
1175 | | + |
1176 | | + part = part->next; |
1177 | | + header = part->elts; |
1178 | | + i = 0; |
1179 | | + } |
1180 | | + |
1181 | | + if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash, |
1182 | | + header[i].lowcase_key, header[i].key.len)) |
1183 | | + { |
1184 | | + continue; |
1185 | | + } |
1186 | | + |
1187 | | + b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); |
1188 | | + |
1189 | | + *b->last++ = ':'; *b->last++ = ' '; |
1190 | | + |
1191 | | + b->last = ngx_copy(b->last, header[i].value.data, |
1192 | | + header[i].value.len); |
1193 | | + |
1194 | | + *b->last++ = CR; *b->last++ = LF; |
1195 | | + |
1196 | | + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1197 | | + "http proxy header: \"%V: %V\"", |
1198 | | + &header[i].key, &header[i].value); |
1199 | | + } |
1200 | | + } |
1201 | | + |
1202 | | + |
1203 | | + /* add "\r\n" at the header end */ |
1204 | | + *b->last++ = CR; *b->last++ = LF; |
1205 | | + |
1206 | | + if (plcf->body_set) { |
1207 | | + e.ip = plcf->body_set->elts; |
1208 | | + e.pos = b->last; |
1209 | | + |
1210 | | + while (*(uintptr_t *) e.ip) { |
1211 | | + code = *(ngx_http_script_code_pt *) e.ip; |
1212 | | + code((ngx_http_script_engine_t *) &e); |
1213 | | + } |
1214 | | + |
1215 | | + b->last = e.pos; |
1216 | | + } |
1217 | | + |
1218 | | + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1219 | | + "http proxy header:\n\"%*s\"", |
1220 | | + (size_t) (b->last - b->pos), b->pos); |
1221 | | + |
1222 | | + if (plcf->body_set == NULL && plcf->upstream.pass_request_body) { |
1223 | | + |
1224 | | + body = u->request_bufs; |
1225 | | + u->request_bufs = cl; |
1226 | | + |
1227 | | + while (body) { |
1228 | | + b = ngx_alloc_buf(r->pool); |
1229 | | + if (b == NULL) { |
1230 | | + return NGX_ERROR; |
1231 | | + } |
1232 | | + |
1233 | | + ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); |
1234 | | + |
1235 | | + cl->next = ngx_alloc_chain_link(r->pool); |
1236 | | + if (cl->next == NULL) { |
1237 | | + return NGX_ERROR; |
1238 | | + } |
1239 | | + |
1240 | | + cl = cl->next; |
1241 | | + cl->buf = b; |
1242 | | + |
1243 | | + body = body->next; |
1244 | | + } |
1245 | | + |
1246 | | + b->flush = 1; |
1247 | | + |
1248 | | + } else { |
1249 | | + u->request_bufs = cl; |
1250 | | + } |
1251 | | + |
1252 | | + cl->next = NULL; |
1253 | | + |
1254 | | + return NGX_OK; |
1255 | | +} |
1256 | | + |
1257 | | + |
1258 | | +static ngx_int_t |
1259 | | +ngx_http_proxy_reinit_request(ngx_http_request_t *r) |
1260 | | +{ |
1261 | | + ngx_http_proxy_ctx_t *ctx; |
1262 | | + |
1263 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1264 | | + |
1265 | | + if (ctx == NULL) { |
1266 | | + return NGX_OK; |
1267 | | + } |
1268 | | + |
1269 | | + ctx->status.code = 0; |
1270 | | + ctx->status.count = 0; |
1271 | | + ctx->status.start = NULL; |
1272 | | + ctx->status.end = NULL; |
1273 | | + |
1274 | | + r->upstream->process_header = ngx_http_proxy_process_status_line; |
1275 | | + r->state = 0; |
1276 | | + |
1277 | | + return NGX_OK; |
1278 | | +} |
1279 | | + |
1280 | | + |
1281 | | +static ngx_int_t |
1282 | | +ngx_http_proxy_process_status_line(ngx_http_request_t *r) |
1283 | | +{ |
1284 | | + size_t len; |
1285 | | + ngx_int_t rc; |
1286 | | + ngx_http_upstream_t *u; |
1287 | | + ngx_http_proxy_ctx_t *ctx; |
1288 | | + |
1289 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1290 | | + |
1291 | | + if (ctx == NULL) { |
1292 | | + return NGX_ERROR; |
1293 | | + } |
1294 | | + |
1295 | | + u = r->upstream; |
1296 | | + |
1297 | | + rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); |
1298 | | + |
1299 | | + if (rc == NGX_AGAIN) { |
1300 | | + return rc; |
1301 | | + } |
1302 | | + |
1303 | | + if (rc == NGX_ERROR) { |
1304 | | + |
1305 | | +#if (NGX_HTTP_CACHE) |
1306 | | + |
1307 | | + if (r->cache) { |
1308 | | + r->http_version = NGX_HTTP_VERSION_9; |
1309 | | + return NGX_OK; |
1310 | | + } |
1311 | | + |
1312 | | +#endif |
1313 | | + |
1314 | | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1315 | | + "upstream sent no valid HTTP/1.0 header"); |
1316 | | + |
1317 | | +#if 0 |
1318 | | + if (u->accel) { |
1319 | | + return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1320 | | + } |
1321 | | +#endif |
1322 | | + |
1323 | | + r->http_version = NGX_HTTP_VERSION_9; |
1324 | | + u->state->status = NGX_HTTP_OK; |
1325 | | + |
1326 | | + return NGX_OK; |
1327 | | + } |
1328 | | + |
1329 | | + if (u->state) { |
1330 | | + u->state->status = ctx->status.code; |
1331 | | + } |
1332 | | + |
1333 | | + u->headers_in.status_n = ctx->status.code; |
1334 | | + |
1335 | | + len = ctx->status.end - ctx->status.start; |
1336 | | + u->headers_in.status_line.len = len; |
1337 | | + |
1338 | | + u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); |
1339 | | + if (u->headers_in.status_line.data == NULL) { |
1340 | | + return NGX_ERROR; |
1341 | | + } |
1342 | | + |
1343 | | + ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); |
1344 | | + |
1345 | | + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1346 | | + "http proxy status %ui \"%V\"", |
1347 | | + u->headers_in.status_n, &u->headers_in.status_line); |
1348 | | + |
1349 | | + u->process_header = ngx_http_proxy_process_header; |
1350 | | + |
1351 | | + return ngx_http_proxy_process_header(r); |
1352 | | +} |
1353 | | + |
1354 | | + |
1355 | | +static ngx_int_t |
1356 | | +ngx_http_proxy_process_header(ngx_http_request_t *r) |
1357 | | +{ |
1358 | | + ngx_int_t rc; |
1359 | | + ngx_table_elt_t *h; |
1360 | | + ngx_http_upstream_header_t *hh; |
1361 | | + ngx_http_upstream_main_conf_t *umcf; |
1362 | | + |
1363 | | + umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
1364 | | + |
1365 | | + for ( ;; ) { |
1366 | | + |
1367 | | + rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); |
1368 | | + |
1369 | | + if (rc == NGX_OK) { |
1370 | | + |
1371 | | + /* a header line has been parsed successfully */ |
1372 | | + |
1373 | | + h = ngx_list_push(&r->upstream->headers_in.headers); |
1374 | | + if (h == NULL) { |
1375 | | + return NGX_ERROR; |
1376 | | + } |
1377 | | + |
1378 | | + h->hash = r->header_hash; |
1379 | | + |
1380 | | + h->key.len = r->header_name_end - r->header_name_start; |
1381 | | + h->value.len = r->header_end - r->header_start; |
1382 | | + |
1383 | | + h->key.data = ngx_pnalloc(r->pool, |
1384 | | + h->key.len + 1 + h->value.len + 1 + h->key.len); |
1385 | | + if (h->key.data == NULL) { |
1386 | | + return NGX_ERROR; |
1387 | | + } |
1388 | | + |
1389 | | + h->value.data = h->key.data + h->key.len + 1; |
1390 | | + h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; |
1391 | | + |
1392 | | + ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); |
1393 | | + ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); |
1394 | | + |
1395 | | + if (h->key.len == r->lowcase_index) { |
1396 | | + ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); |
1397 | | + |
1398 | | + } else { |
1399 | | + ngx_strlow(h->lowcase_key, h->key.data, h->key.len); |
1400 | | + } |
1401 | | + |
1402 | | + hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, |
1403 | | + h->lowcase_key, h->key.len); |
1404 | | + |
1405 | | + if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { |
1406 | | + return NGX_ERROR; |
1407 | | + } |
1408 | | + |
1409 | | + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1410 | | + "http proxy header: \"%V: %V\"", |
1411 | | + &h->key, &h->value); |
1412 | | + |
1413 | | + continue; |
1414 | | + } |
1415 | | + |
1416 | | + if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
1417 | | + |
1418 | | + /* a whole header has been parsed successfully */ |
1419 | | + |
1420 | | + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1421 | | + "http proxy header done"); |
1422 | | + |
1423 | | + /* |
1424 | | + * if no "Server" and "Date" in header line, |
1425 | | + * then add the special empty headers |
1426 | | + */ |
1427 | | + |
1428 | | + if (r->upstream->headers_in.server == NULL) { |
1429 | | + h = ngx_list_push(&r->upstream->headers_in.headers); |
1430 | | + if (h == NULL) { |
1431 | | + return NGX_ERROR; |
1432 | | + } |
1433 | | + |
1434 | | + h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( |
1435 | | + ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); |
1436 | | + |
1437 | | + ngx_str_set(&h->key, "Server"); |
1438 | | + ngx_str_null(&h->value); |
1439 | | + h->lowcase_key = (u_char *) "server"; |
1440 | | + } |
1441 | | + |
1442 | | + if (r->upstream->headers_in.date == NULL) { |
1443 | | + h = ngx_list_push(&r->upstream->headers_in.headers); |
1444 | | + if (h == NULL) { |
1445 | | + return NGX_ERROR; |
1446 | | + } |
1447 | | + |
1448 | | + h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); |
1449 | | + |
1450 | | + ngx_str_set(&h->key, "Date"); |
1451 | | + ngx_str_null(&h->value); |
1452 | | + h->lowcase_key = (u_char *) "date"; |
1453 | | + } |
1454 | | + |
1455 | | + return NGX_OK; |
1456 | | + } |
1457 | | + |
1458 | | + if (rc == NGX_AGAIN) { |
1459 | | + return NGX_AGAIN; |
1460 | | + } |
1461 | | + |
1462 | | + /* there was error while a header line parsing */ |
1463 | | + |
1464 | | + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1465 | | + "upstream sent invalid header"); |
1466 | | + |
1467 | | + return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1468 | | + } |
1469 | | +} |
1470 | | + |
1471 | | + |
1472 | | +static void |
1473 | | +ngx_http_proxy_abort_request(ngx_http_request_t *r) |
1474 | | +{ |
1475 | | + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1476 | | + "abort http proxy request"); |
1477 | | + |
1478 | | + return; |
1479 | | +} |
1480 | | + |
1481 | | + |
1482 | | +static void |
1483 | | +ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) |
1484 | | +{ |
1485 | | + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1486 | | + "finalize http proxy request"); |
1487 | | + |
1488 | | + return; |
1489 | | +} |
1490 | | + |
1491 | | + |
1492 | | +static ngx_int_t |
1493 | | +ngx_http_proxy_host_variable(ngx_http_request_t *r, |
1494 | | + ngx_http_variable_value_t *v, uintptr_t data) |
1495 | | +{ |
1496 | | + ngx_http_proxy_ctx_t *ctx; |
1497 | | + |
1498 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1499 | | + |
1500 | | + if (ctx == NULL) { |
1501 | | + v->not_found = 1; |
1502 | | + return NGX_OK; |
1503 | | + } |
1504 | | + |
1505 | | + v->len = ctx->vars.host_header.len; |
1506 | | + v->valid = 1; |
1507 | | + v->no_cacheable = 0; |
1508 | | + v->not_found = 0; |
1509 | | + v->data = ctx->vars.host_header.data; |
1510 | | + |
1511 | | + return NGX_OK; |
1512 | | +} |
1513 | | + |
1514 | | + |
1515 | | +static ngx_int_t |
1516 | | +ngx_http_proxy_port_variable(ngx_http_request_t *r, |
1517 | | + ngx_http_variable_value_t *v, uintptr_t data) |
1518 | | +{ |
1519 | | + ngx_http_proxy_ctx_t *ctx; |
1520 | | + |
1521 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1522 | | + |
1523 | | + if (ctx == NULL) { |
1524 | | + v->not_found = 1; |
1525 | | + return NGX_OK; |
1526 | | + } |
1527 | | + |
1528 | | + v->len = ctx->vars.port.len; |
1529 | | + v->valid = 1; |
1530 | | + v->no_cacheable = 0; |
1531 | | + v->not_found = 0; |
1532 | | + v->data = ctx->vars.port.data; |
1533 | | + |
1534 | | + return NGX_OK; |
1535 | | +} |
1536 | | + |
1537 | | + |
1538 | | +static ngx_int_t |
1539 | | +ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, |
1540 | | + ngx_http_variable_value_t *v, uintptr_t data) |
1541 | | +{ |
1542 | | + u_char *p; |
1543 | | + |
1544 | | + v->valid = 1; |
1545 | | + v->no_cacheable = 0; |
1546 | | + v->not_found = 0; |
1547 | | + |
1548 | | + if (r->headers_in.x_forwarded_for == NULL) { |
1549 | | + v->len = r->connection->addr_text.len; |
1550 | | + v->data = r->connection->addr_text.data; |
1551 | | + return NGX_OK; |
1552 | | + } |
1553 | | + |
1554 | | + v->len = r->headers_in.x_forwarded_for->value.len |
1555 | | + + sizeof(", ") - 1 + r->connection->addr_text.len; |
1556 | | + |
1557 | | + p = ngx_pnalloc(r->pool, v->len); |
1558 | | + if (p == NULL) { |
1559 | | + return NGX_ERROR; |
1560 | | + } |
1561 | | + |
1562 | | + v->data = p; |
1563 | | + |
1564 | | + p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data, |
1565 | | + r->headers_in.x_forwarded_for->value.len); |
1566 | | + |
1567 | | + *p++ = ','; *p++ = ' '; |
1568 | | + |
1569 | | + ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); |
1570 | | + |
1571 | | + return NGX_OK; |
1572 | | +} |
1573 | | + |
1574 | | + |
1575 | | +static ngx_int_t |
1576 | | +ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, |
1577 | | + ngx_http_variable_value_t *v, uintptr_t data) |
1578 | | +{ |
1579 | | + ngx_http_proxy_ctx_t *ctx; |
1580 | | + |
1581 | | + ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
1582 | | + |
1583 | | + if (ctx == NULL) { |
1584 | | + v->not_found = 1; |
1585 | | + return NGX_OK; |
1586 | | + } |
1587 | | + |
1588 | | + v->valid = 1; |
1589 | | + v->no_cacheable = 0; |
1590 | | + v->not_found = 0; |
1591 | | + |
1592 | | + v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN); |
1593 | | + |
1594 | | + if (v->data == NULL) { |
1595 | | + return NGX_ERROR; |
1596 | | + } |
1597 | | + |
1598 | | + v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data; |
1599 | | + |
1600 | | + return NGX_OK; |
1601 | | +} |
1602 | | + |
1603 | | + |
1604 | | +static ngx_int_t |
1605 | | +ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, |
1606 | | + size_t prefix) |
1607 | | +{ |
1608 | | + ngx_int_t rc; |
1609 | | + ngx_uint_t i; |
1610 | | + ngx_http_proxy_loc_conf_t *plcf; |
1611 | | + ngx_http_proxy_redirect_t *pr; |
1612 | | + |
1613 | | + plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
1614 | | + |
1615 | | + pr = plcf->redirects->elts; |
1616 | | + |
1617 | | + if (pr == NULL) { |
1618 | | + return NGX_DECLINED; |
1619 | | + } |
1620 | | + |
1621 | | + for (i = 0; i < plcf->redirects->nelts; i++) { |
1622 | | + rc = pr[i].handler(r, h, prefix, &pr[i]); |
1623 | | + |
1624 | | + if (rc != NGX_DECLINED) { |
1625 | | + return rc; |
1626 | | + } |
1627 | | + } |
1628 | | + |
1629 | | + return NGX_DECLINED; |
1630 | | +} |
1631 | | + |
1632 | | + |
1633 | | +static ngx_int_t |
1634 | | +ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h, |
1635 | | + size_t prefix, ngx_http_proxy_redirect_t *pr) |
1636 | | +{ |
1637 | | + size_t len; |
1638 | | + u_char *data, *p; |
1639 | | + |
1640 | | + if (pr->redirect.len > h->value.len - prefix |
1641 | | + || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data, |
1642 | | + pr->redirect.len) != 0) |
1643 | | + { |
1644 | | + return NGX_DECLINED; |
1645 | | + } |
1646 | | + |
1647 | | + len = pr->replacement.text.len + h->value.len - pr->redirect.len; |
1648 | | + |
1649 | | + data = ngx_pnalloc(r->pool, len); |
1650 | | + if (data == NULL) { |
1651 | | + return NGX_ERROR; |
1652 | | + } |
1653 | | + |
1654 | | + p = ngx_copy(data, h->value.data, prefix); |
1655 | | + |
1656 | | + if (pr->replacement.text.len) { |
1657 | | + p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len); |
1658 | | + } |
1659 | | + |
1660 | | + ngx_memcpy(p, h->value.data + prefix + pr->redirect.len, |
1661 | | + h->value.len - pr->redirect.len - prefix); |
1662 | | + |
1663 | | + h->value.len = len; |
1664 | | + h->value.data = data; |
1665 | | + |
1666 | | + return NGX_OK; |
1667 | | +} |
1668 | | + |
1669 | | + |
1670 | | +static ngx_int_t |
1671 | | +ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h, |
1672 | | + size_t prefix, ngx_http_proxy_redirect_t *pr) |
1673 | | +{ |
1674 | | + size_t len; |
1675 | | + u_char *data, *p; |
1676 | | + ngx_http_script_code_pt code; |
1677 | | + ngx_http_script_engine_t e; |
1678 | | + ngx_http_script_len_code_pt lcode; |
1679 | | + |
1680 | | + if (pr->redirect.len > h->value.len - prefix |
1681 | | + || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data, |
1682 | | + pr->redirect.len) != 0) |
1683 | | + { |
1684 | | + return NGX_DECLINED; |
1685 | | + } |
1686 | | + |
1687 | | + ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); |
1688 | | + |
1689 | | + e.ip = pr->replacement.vars.lengths; |
1690 | | + e.request = r; |
1691 | | + |
1692 | | + len = h->value.len - pr->redirect.len; |
1693 | | + |
1694 | | + while (*(uintptr_t *) e.ip) { |
1695 | | + lcode = *(ngx_http_script_len_code_pt *) e.ip; |
1696 | | + len += lcode(&e); |
1697 | | + } |
1698 | | + |
1699 | | + data = ngx_pnalloc(r->pool, len); |
1700 | | + if (data == NULL) { |
1701 | | + return NGX_ERROR; |
1702 | | + } |
1703 | | + |
1704 | | + p = ngx_copy(data, h->value.data, prefix); |
1705 | | + |
1706 | | + e.ip = pr->replacement.vars.values; |
1707 | | + e.pos = p; |
1708 | | + |
1709 | | + while (*(uintptr_t *) e.ip) { |
1710 | | + code = *(ngx_http_script_code_pt *) e.ip; |
1711 | | + code(&e); |
1712 | | + } |
1713 | | + |
1714 | | + ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len, |
1715 | | + h->value.len - pr->redirect.len - prefix); |
1716 | | + |
1717 | | + h->value.len = len; |
1718 | | + h->value.data = data; |
1719 | | + |
1720 | | + return NGX_OK; |
1721 | | +} |
1722 | | + |
1723 | | + |
1724 | | +static ngx_int_t |
1725 | | +ngx_http_proxy_add_variables(ngx_conf_t *cf) |
1726 | | +{ |
1727 | | + ngx_http_variable_t *var, *v; |
1728 | | + |
1729 | | + for (v = ngx_http_proxy_vars; v->name.len; v++) { |
1730 | | + var = ngx_http_add_variable(cf, &v->name, v->flags); |
1731 | | + if (var == NULL) { |
1732 | | + return NGX_ERROR; |
1733 | | + } |
1734 | | + |
1735 | | + var->get_handler = v->get_handler; |
1736 | | + var->data = v->data; |
1737 | | + } |
1738 | | + |
1739 | | + return NGX_OK; |
1740 | | +} |
1741 | | + |
1742 | | + |
1743 | | +static void * |
1744 | | +ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) |
1745 | | +{ |
1746 | | + ngx_http_proxy_loc_conf_t *conf; |
1747 | | + |
1748 | | + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)); |
1749 | | + if (conf == NULL) { |
1750 | | + return NULL; |
1751 | | + } |
1752 | | + |
1753 | | + /* |
1754 | | + * set by ngx_pcalloc(): |
1755 | | + * |
1756 | | + * conf->upstream.bufs.num = 0; |
1757 | | + * conf->upstream.ignore_headers = 0; |
1758 | | + * conf->upstream.next_upstream = 0; |
1759 | | + * conf->upstream.cache_use_stale = 0; |
1760 | | + * conf->upstream.cache_methods = 0; |
1761 | | + * conf->upstream.temp_path = NULL; |
1762 | | + * conf->upstream.hide_headers_hash = { NULL, 0 }; |
1763 | | + * conf->upstream.uri = { 0, NULL }; |
1764 | | + * conf->upstream.location = NULL; |
1765 | | + * conf->upstream.store_lengths = NULL; |
1766 | | + * conf->upstream.store_values = NULL; |
1767 | | + * |
1768 | | + * conf->method = NULL; |
1769 | | + * conf->headers_source = NULL; |
1770 | | + * conf->headers_set_len = NULL; |
1771 | | + * conf->headers_set = NULL; |
1772 | | + * conf->headers_set_hash = NULL; |
1773 | | + * conf->body_set_len = NULL; |
1774 | | + * conf->body_set = NULL; |
1775 | | + * conf->body_source = { 0, NULL }; |
1776 | | + * conf->redirects = NULL; |
1777 | | + */ |
1778 | | + |
1779 | | + conf->upstream.store = NGX_CONF_UNSET; |
1780 | | + conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
1781 | | + conf->upstream.buffering = NGX_CONF_UNSET; |
1782 | | + conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
1783 | | + |
1784 | | + conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
1785 | | + conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
1786 | | + conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
1787 | | + |
1788 | | + conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
1789 | | + conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; |
1790 | | + |
1791 | | + conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; |
1792 | | + conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; |
1793 | | + conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; |
1794 | | + |
1795 | | + conf->upstream.pass_request_headers = NGX_CONF_UNSET; |
1796 | | + conf->upstream.pass_request_body = NGX_CONF_UNSET; |
1797 | | + |
1798 | | +#if (NGX_HTTP_CACHE) |
1799 | | + conf->upstream.cache = NGX_CONF_UNSET_PTR; |
1800 | | + conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; |
1801 | | + conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; |
1802 | | + conf->upstream.no_cache = NGX_CONF_UNSET_PTR; |
1803 | | + conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; |
1804 | | +#endif |
1805 | | + |
1806 | | + conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; |
1807 | | + conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; |
1808 | | + |
1809 | | + conf->upstream.intercept_errors = NGX_CONF_UNSET; |
1810 | | +#if (NGX_HTTP_SSL) |
1811 | | + conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; |
1812 | | +#endif |
1813 | | + |
1814 | | + /* "proxy_cyclic_temp_file" is disabled */ |
1815 | | + conf->upstream.cyclic_temp_file = 0; |
1816 | | + |
1817 | | + conf->redirect = NGX_CONF_UNSET; |
1818 | | + conf->upstream.change_buffering = 1; |
1819 | | + |
1820 | | + conf->headers_hash_max_size = NGX_CONF_UNSET_UINT; |
1821 | | + conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT; |
1822 | | + |
1823 | | + return conf; |
1824 | | +} |
1825 | | + |
1826 | | + |
1827 | | +static char * |
1828 | | +ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |
1829 | | +{ |
1830 | | + ngx_http_proxy_loc_conf_t *prev = parent; |
1831 | | + ngx_http_proxy_loc_conf_t *conf = child; |
1832 | | + |
1833 | | + size_t size; |
1834 | | + ngx_keyval_t *s; |
1835 | | + ngx_hash_init_t hash; |
1836 | | + ngx_http_core_loc_conf_t *clcf; |
1837 | | + ngx_http_proxy_redirect_t *pr; |
1838 | | + ngx_http_script_compile_t sc; |
1839 | | + |
1840 | | + if (conf->upstream.store != 0) { |
1841 | | + ngx_conf_merge_value(conf->upstream.store, |
1842 | | + prev->upstream.store, 0); |
1843 | | + |
1844 | | + if (conf->upstream.store_lengths == NULL) { |
1845 | | + conf->upstream.store_lengths = prev->upstream.store_lengths; |
1846 | | + conf->upstream.store_values = prev->upstream.store_values; |
1847 | | + } |
1848 | | + } |
1849 | | + |
1850 | | + ngx_conf_merge_uint_value(conf->upstream.store_access, |
1851 | | + prev->upstream.store_access, 0600); |
1852 | | + |
1853 | | + ngx_conf_merge_value(conf->upstream.buffering, |
1854 | | + prev->upstream.buffering, 1); |
1855 | | + |
1856 | | + ngx_conf_merge_value(conf->upstream.ignore_client_abort, |
1857 | | + prev->upstream.ignore_client_abort, 0); |
1858 | | + |
1859 | | + ngx_conf_merge_msec_value(conf->upstream.connect_timeout, |
1860 | | + prev->upstream.connect_timeout, 60000); |
1861 | | + |
1862 | | + ngx_conf_merge_msec_value(conf->upstream.send_timeout, |
1863 | | + prev->upstream.send_timeout, 60000); |
1864 | | + |
1865 | | + ngx_conf_merge_msec_value(conf->upstream.read_timeout, |
1866 | | + prev->upstream.read_timeout, 60000); |
1867 | | + |
1868 | | + ngx_conf_merge_size_value(conf->upstream.send_lowat, |
1869 | | + prev->upstream.send_lowat, 0); |
1870 | | + |
1871 | | + ngx_conf_merge_size_value(conf->upstream.buffer_size, |
1872 | | + prev->upstream.buffer_size, |
1873 | | + (size_t) ngx_pagesize); |
1874 | | + |
1875 | | + ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, |
1876 | | + 8, ngx_pagesize); |
1877 | | + |
1878 | | + if (conf->upstream.bufs.num < 2) { |
1879 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1880 | | + "there must be at least 2 \"proxy_buffers\""); |
1881 | | + return NGX_CONF_ERROR; |
1882 | | + } |
1883 | | + |
1884 | | + |
1885 | | + size = conf->upstream.buffer_size; |
1886 | | + if (size < conf->upstream.bufs.size) { |
1887 | | + size = conf->upstream.bufs.size; |
1888 | | + } |
1889 | | + |
1890 | | + |
1891 | | + ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, |
1892 | | + prev->upstream.busy_buffers_size_conf, |
1893 | | + NGX_CONF_UNSET_SIZE); |
1894 | | + |
1895 | | + if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { |
1896 | | + conf->upstream.busy_buffers_size = 2 * size; |
1897 | | + } else { |
1898 | | + conf->upstream.busy_buffers_size = |
1899 | | + conf->upstream.busy_buffers_size_conf; |
1900 | | + } |
1901 | | + |
1902 | | + if (conf->upstream.busy_buffers_size < size) { |
1903 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1904 | | + "\"proxy_busy_buffers_size\" must be equal or bigger than " |
1905 | | + "maximum of the value of \"proxy_buffer_size\" and " |
1906 | | + "one of the \"proxy_buffers\""); |
1907 | | + |
1908 | | + return NGX_CONF_ERROR; |
1909 | | + } |
1910 | | + |
1911 | | + if (conf->upstream.busy_buffers_size |
1912 | | + > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) |
1913 | | + { |
1914 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1915 | | + "\"proxy_busy_buffers_size\" must be less than " |
1916 | | + "the size of all \"proxy_buffers\" minus one buffer"); |
1917 | | + |
1918 | | + return NGX_CONF_ERROR; |
1919 | | + } |
1920 | | + |
1921 | | + |
1922 | | + ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf, |
1923 | | + prev->upstream.temp_file_write_size_conf, |
1924 | | + NGX_CONF_UNSET_SIZE); |
1925 | | + |
1926 | | + if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { |
1927 | | + conf->upstream.temp_file_write_size = 2 * size; |
1928 | | + } else { |
1929 | | + conf->upstream.temp_file_write_size = |
1930 | | + conf->upstream.temp_file_write_size_conf; |
1931 | | + } |
1932 | | + |
1933 | | + if (conf->upstream.temp_file_write_size < size) { |
1934 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1935 | | + "\"proxy_temp_file_write_size\" must be equal or bigger than " |
1936 | | + "maximum of the value of \"proxy_buffer_size\" and " |
1937 | | + "one of the \"proxy_buffers\""); |
1938 | | + |
1939 | | + return NGX_CONF_ERROR; |
1940 | | + } |
1941 | | + |
1942 | | + ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf, |
1943 | | + prev->upstream.max_temp_file_size_conf, |
1944 | | + NGX_CONF_UNSET_SIZE); |
1945 | | + |
1946 | | + if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { |
1947 | | + conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; |
1948 | | + } else { |
1949 | | + conf->upstream.max_temp_file_size = |
1950 | | + conf->upstream.max_temp_file_size_conf; |
1951 | | + } |
1952 | | + |
1953 | | + if (conf->upstream.max_temp_file_size != 0 |
1954 | | + && conf->upstream.max_temp_file_size < size) |
1955 | | + { |
1956 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1957 | | + "\"proxy_max_temp_file_size\" must be equal to zero to disable " |
1958 | | + "the temporary files usage or must be equal or bigger than " |
1959 | | + "maximum of the value of \"proxy_buffer_size\" and " |
1960 | | + "one of the \"proxy_buffers\""); |
1961 | | + |
1962 | | + return NGX_CONF_ERROR; |
1963 | | + } |
1964 | | + |
1965 | | + |
1966 | | + ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers, |
1967 | | + prev->upstream.ignore_headers, |
1968 | | + NGX_CONF_BITMASK_SET); |
1969 | | + |
1970 | | + |
1971 | | + ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, |
1972 | | + prev->upstream.next_upstream, |
1973 | | + (NGX_CONF_BITMASK_SET |
1974 | | + |NGX_HTTP_UPSTREAM_FT_ERROR |
1975 | | + |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); |
1976 | | + |
1977 | | + if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { |
1978 | | + conf->upstream.next_upstream = NGX_CONF_BITMASK_SET |
1979 | | + |NGX_HTTP_UPSTREAM_FT_OFF; |
1980 | | + } |
1981 | | + |
1982 | | + if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path, |
1983 | | + prev->upstream.temp_path, |
1984 | | + &ngx_http_proxy_temp_path) |
1985 | | + != NGX_OK) |
1986 | | + { |
1987 | | + return NGX_CONF_ERROR; |
1988 | | + } |
1989 | | + |
1990 | | + |
1991 | | +#if (NGX_HTTP_CACHE) |
1992 | | + |
1993 | | + ngx_conf_merge_ptr_value(conf->upstream.cache, |
1994 | | + prev->upstream.cache, NULL); |
1995 | | + |
1996 | | + if (conf->upstream.cache && conf->upstream.cache->data == NULL) { |
1997 | | + ngx_shm_zone_t *shm_zone; |
1998 | | + |
1999 | | + shm_zone = conf->upstream.cache; |
2000 | | + |
2001 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2002 | | + "\"proxy_cache\" zone \"%V\" is unknown", |
2003 | | + &shm_zone->shm.name); |
2004 | | + |
2005 | | + return NGX_CONF_ERROR; |
2006 | | + } |
2007 | | + |
2008 | | + ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, |
2009 | | + prev->upstream.cache_min_uses, 1); |
2010 | | + |
2011 | | + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, |
2012 | | + prev->upstream.cache_use_stale, |
2013 | | + (NGX_CONF_BITMASK_SET |
2014 | | + |NGX_HTTP_UPSTREAM_FT_OFF)); |
2015 | | + |
2016 | | + if (conf->upstream.cache_methods == 0) { |
2017 | | + conf->upstream.cache_methods = prev->upstream.cache_methods; |
2018 | | + } |
2019 | | + |
2020 | | + conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; |
2021 | | + |
2022 | | + if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) { |
2023 | | + conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET |
2024 | | + |NGX_HTTP_UPSTREAM_FT_OFF; |
2025 | | + } |
2026 | | + |
2027 | | + ngx_conf_merge_ptr_value(conf->upstream.cache_bypass, |
2028 | | + prev->upstream.cache_bypass, NULL); |
2029 | | + |
2030 | | + ngx_conf_merge_ptr_value(conf->upstream.no_cache, |
2031 | | + prev->upstream.no_cache, NULL); |
2032 | | + |
2033 | | + if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) { |
2034 | | + ngx_log_error(NGX_LOG_WARN, cf->log, 0, |
2035 | | + "\"proxy_no_cache\" functionality has been changed in 0.8.46, " |
2036 | | + "now it should be used together with \"proxy_cache_bypass\""); |
2037 | | + } |
2038 | | + |
2039 | | + ngx_conf_merge_ptr_value(conf->upstream.cache_valid, |
2040 | | + prev->upstream.cache_valid, NULL); |
2041 | | + |
2042 | | + if (conf->cache_key.value.data == NULL) { |
2043 | | + conf->cache_key = prev->cache_key; |
2044 | | + } |
2045 | | + |
2046 | | +#endif |
2047 | | + |
2048 | | + if (conf->method.len == 0) { |
2049 | | + conf->method = prev->method; |
2050 | | + |
2051 | | + } else { |
2052 | | + conf->method.data[conf->method.len] = ' '; |
2053 | | + conf->method.len++; |
2054 | | + } |
2055 | | + |
2056 | | + ngx_conf_merge_value(conf->upstream.pass_request_headers, |
2057 | | + prev->upstream.pass_request_headers, 1); |
2058 | | + ngx_conf_merge_value(conf->upstream.pass_request_body, |
2059 | | + prev->upstream.pass_request_body, 1); |
2060 | | + |
2061 | | + ngx_conf_merge_value(conf->upstream.intercept_errors, |
2062 | | + prev->upstream.intercept_errors, 0); |
2063 | | + |
2064 | | +#if (NGX_HTTP_SSL) |
2065 | | + ngx_conf_merge_value(conf->upstream.ssl_session_reuse, |
2066 | | + prev->upstream.ssl_session_reuse, 1); |
2067 | | +#endif |
2068 | | + |
2069 | | + ngx_conf_merge_value(conf->redirect, prev->redirect, 1); |
2070 | | + |
2071 | | + if (conf->redirect) { |
2072 | | + |
2073 | | + if (conf->redirects == NULL) { |
2074 | | + conf->redirects = prev->redirects; |
2075 | | + } |
2076 | | + |
2077 | | + if (conf->redirects == NULL && conf->url.data) { |
2078 | | + |
2079 | | + conf->redirects = ngx_array_create(cf->pool, 1, |
2080 | | + sizeof(ngx_http_proxy_redirect_t)); |
2081 | | + if (conf->redirects == NULL) { |
2082 | | + return NGX_CONF_ERROR; |
2083 | | + } |
2084 | | + |
2085 | | + pr = ngx_array_push(conf->redirects); |
2086 | | + if (pr == NULL) { |
2087 | | + return NGX_CONF_ERROR; |
2088 | | + } |
2089 | | + |
2090 | | + pr->handler = ngx_http_proxy_rewrite_redirect_text; |
2091 | | + pr->redirect = conf->url; |
2092 | | + |
2093 | | + if (conf->vars.uri.len) { |
2094 | | + pr->replacement.text = conf->location; |
2095 | | + |
2096 | | + } else { |
2097 | | + ngx_str_null(&pr->replacement.text); |
2098 | | + } |
2099 | | + } |
2100 | | + } |
2101 | | + |
2102 | | +#if (NGX_HTTP_SSL) |
2103 | | + if (conf->upstream.ssl == NULL) { |
2104 | | + conf->upstream.ssl = prev->upstream.ssl; |
2105 | | + } |
2106 | | +#endif |
2107 | | + |
2108 | | + ngx_conf_merge_uint_value(conf->headers_hash_max_size, |
2109 | | + prev->headers_hash_max_size, 512); |
2110 | | + |
2111 | | + ngx_conf_merge_uint_value(conf->headers_hash_bucket_size, |
2112 | | + prev->headers_hash_bucket_size, 64); |
2113 | | + |
2114 | | + conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size, |
2115 | | + ngx_cacheline_size); |
2116 | | + |
2117 | | + hash.max_size = conf->headers_hash_max_size; |
2118 | | + hash.bucket_size = conf->headers_hash_bucket_size; |
2119 | | + hash.name = "proxy_headers_hash"; |
2120 | | + |
2121 | | + if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, |
2122 | | + &prev->upstream, ngx_http_proxy_hide_headers, &hash) |
2123 | | + != NGX_OK) |
2124 | | + { |
2125 | | + return NGX_CONF_ERROR; |
2126 | | + } |
2127 | | + |
2128 | | + if (conf->upstream.upstream == NULL) { |
2129 | | + conf->upstream.upstream = prev->upstream.upstream; |
2130 | | + conf->vars = prev->vars; |
2131 | | + } |
2132 | | + |
2133 | | + if (conf->proxy_lengths == NULL) { |
2134 | | + conf->proxy_lengths = prev->proxy_lengths; |
2135 | | + conf->proxy_values = prev->proxy_values; |
2136 | | + } |
2137 | | + |
2138 | | + if (conf->upstream.upstream || conf->proxy_lengths) { |
2139 | | + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); |
2140 | | + if (clcf->handler == NULL && clcf->lmt_excpt) { |
2141 | | + clcf->handler = ngx_http_proxy_handler; |
2142 | | + conf->location = prev->location; |
2143 | | + } |
2144 | | + } |
2145 | | + |
2146 | | + if (conf->body_source.data == NULL) { |
2147 | | + conf->body_source = prev->body_source; |
2148 | | + conf->body_set_len = prev->body_set_len; |
2149 | | + conf->body_set = prev->body_set; |
2150 | | + } |
2151 | | + |
2152 | | + if (conf->body_source.data && conf->body_set_len == NULL) { |
2153 | | + |
2154 | | + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
2155 | | + |
2156 | | + sc.cf = cf; |
2157 | | + sc.source = &conf->body_source; |
2158 | | + sc.flushes = &conf->flushes; |
2159 | | + sc.lengths = &conf->body_set_len; |
2160 | | + sc.values = &conf->body_set; |
2161 | | + sc.complete_lengths = 1; |
2162 | | + sc.complete_values = 1; |
2163 | | + |
2164 | | + if (ngx_http_script_compile(&sc) != NGX_OK) { |
2165 | | + return NGX_CONF_ERROR; |
2166 | | + } |
2167 | | + |
2168 | | + if (conf->headers_source == NULL) { |
2169 | | + conf->headers_source = ngx_array_create(cf->pool, 4, |
2170 | | + sizeof(ngx_keyval_t)); |
2171 | | + if (conf->headers_source == NULL) { |
2172 | | + return NGX_CONF_ERROR; |
2173 | | + } |
2174 | | + } |
2175 | | + |
2176 | | + s = ngx_array_push(conf->headers_source); |
2177 | | + if (s == NULL) { |
2178 | | + return NGX_CONF_ERROR; |
2179 | | + } |
2180 | | + |
2181 | | + ngx_str_set(&s->key, "Content-Length"); |
2182 | | + ngx_str_set(&s->value, "$proxy_internal_body_length"); |
2183 | | + } |
2184 | | + |
2185 | | + if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) { |
2186 | | + return NGX_CONF_ERROR; |
2187 | | + } |
2188 | | + |
2189 | | + return NGX_CONF_OK; |
2190 | | +} |
2191 | | + |
2192 | | + |
2193 | | +static ngx_int_t |
2194 | | +ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf, |
2195 | | + ngx_http_proxy_loc_conf_t *prev) |
2196 | | +{ |
2197 | | + u_char *p; |
2198 | | + size_t size; |
2199 | | + uintptr_t *code; |
2200 | | + ngx_uint_t i; |
2201 | | + ngx_array_t headers_names; |
2202 | | + ngx_keyval_t *src, *s, *h; |
2203 | | + ngx_hash_key_t *hk; |
2204 | | + ngx_hash_init_t hash; |
2205 | | + ngx_http_script_compile_t sc; |
2206 | | + ngx_http_script_copy_code_t *copy; |
2207 | | + |
2208 | | + if (conf->headers_source == NULL) { |
2209 | | + conf->flushes = prev->flushes; |
2210 | | + conf->headers_set_len = prev->headers_set_len; |
2211 | | + conf->headers_set = prev->headers_set; |
2212 | | + conf->headers_set_hash = prev->headers_set_hash; |
2213 | | + conf->headers_source = prev->headers_source; |
2214 | | + } |
2215 | | + |
2216 | | + if (conf->headers_set_hash.buckets |
2217 | | +#if (NGX_HTTP_CACHE) |
2218 | | + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) |
2219 | | +#endif |
2220 | | + ) |
2221 | | + { |
2222 | | + return NGX_OK; |
2223 | | + } |
2224 | | + |
2225 | | + |
2226 | | + if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) |
2227 | | + != NGX_OK) |
2228 | | + { |
2229 | | + return NGX_ERROR; |
2230 | | + } |
2231 | | + |
2232 | | + if (conf->headers_source == NULL) { |
2233 | | + conf->headers_source = ngx_array_create(cf->pool, 4, |
2234 | | + sizeof(ngx_keyval_t)); |
2235 | | + if (conf->headers_source == NULL) { |
2236 | | + return NGX_ERROR; |
2237 | | + } |
2238 | | + } |
2239 | | + |
2240 | | + conf->headers_set_len = ngx_array_create(cf->pool, 64, 1); |
2241 | | + if (conf->headers_set_len == NULL) { |
2242 | | + return NGX_ERROR; |
2243 | | + } |
2244 | | + |
2245 | | + conf->headers_set = ngx_array_create(cf->pool, 512, 1); |
2246 | | + if (conf->headers_set == NULL) { |
2247 | | + return NGX_ERROR; |
2248 | | + } |
2249 | | + |
2250 | | + |
2251 | | + src = conf->headers_source->elts; |
2252 | | + |
2253 | | +#if (NGX_HTTP_CACHE) |
2254 | | + |
2255 | | + h = conf->upstream.cache ? ngx_http_proxy_cache_headers: |
2256 | | + ngx_http_proxy_headers; |
2257 | | +#else |
2258 | | + |
2259 | | + h = ngx_http_proxy_headers; |
2260 | | + |
2261 | | +#endif |
2262 | | + |
2263 | | + while (h->key.len) { |
2264 | | + |
2265 | | + for (i = 0; i < conf->headers_source->nelts; i++) { |
2266 | | + if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { |
2267 | | + goto next; |
2268 | | + } |
2269 | | + } |
2270 | | + |
2271 | | + s = ngx_array_push(conf->headers_source); |
2272 | | + if (s == NULL) { |
2273 | | + return NGX_ERROR; |
2274 | | + } |
2275 | | + |
2276 | | + *s = *h; |
2277 | | + |
2278 | | + src = conf->headers_source->elts; |
2279 | | + |
2280 | | + next: |
2281 | | + |
2282 | | + h++; |
2283 | | + } |
2284 | | + |
2285 | | + |
2286 | | + src = conf->headers_source->elts; |
2287 | | + for (i = 0; i < conf->headers_source->nelts; i++) { |
2288 | | + |
2289 | | + hk = ngx_array_push(&headers_names); |
2290 | | + if (hk == NULL) { |
2291 | | + return NGX_ERROR; |
2292 | | + } |
2293 | | + |
2294 | | + hk->key = src[i].key; |
2295 | | + hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len); |
2296 | | + hk->value = (void *) 1; |
2297 | | + |
2298 | | + if (src[i].value.len == 0) { |
2299 | | + continue; |
2300 | | + } |
2301 | | + |
2302 | | + if (ngx_http_script_variables_count(&src[i].value) == 0) { |
2303 | | + copy = ngx_array_push_n(conf->headers_set_len, |
2304 | | + sizeof(ngx_http_script_copy_code_t)); |
2305 | | + if (copy == NULL) { |
2306 | | + return NGX_ERROR; |
2307 | | + } |
2308 | | + |
2309 | | + copy->code = (ngx_http_script_code_pt) |
2310 | | + ngx_http_script_copy_len_code; |
2311 | | + copy->len = src[i].key.len + sizeof(": ") - 1 |
2312 | | + + src[i].value.len + sizeof(CRLF) - 1; |
2313 | | + |
2314 | | + |
2315 | | + size = (sizeof(ngx_http_script_copy_code_t) |
2316 | | + + src[i].key.len + sizeof(": ") - 1 |
2317 | | + + src[i].value.len + sizeof(CRLF) - 1 |
2318 | | + + sizeof(uintptr_t) - 1) |
2319 | | + & ~(sizeof(uintptr_t) - 1); |
2320 | | + |
2321 | | + copy = ngx_array_push_n(conf->headers_set, size); |
2322 | | + if (copy == NULL) { |
2323 | | + return NGX_ERROR; |
2324 | | + } |
2325 | | + |
2326 | | + copy->code = ngx_http_script_copy_code; |
2327 | | + copy->len = src[i].key.len + sizeof(": ") - 1 |
2328 | | + + src[i].value.len + sizeof(CRLF) - 1; |
2329 | | + |
2330 | | + p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); |
2331 | | + |
2332 | | + p = ngx_cpymem(p, src[i].key.data, src[i].key.len); |
2333 | | + *p++ = ':'; *p++ = ' '; |
2334 | | + p = ngx_cpymem(p, src[i].value.data, src[i].value.len); |
2335 | | + *p++ = CR; *p = LF; |
2336 | | + |
2337 | | + } else { |
2338 | | + copy = ngx_array_push_n(conf->headers_set_len, |
2339 | | + sizeof(ngx_http_script_copy_code_t)); |
2340 | | + if (copy == NULL) { |
2341 | | + return NGX_ERROR; |
2342 | | + } |
2343 | | + |
2344 | | + copy->code = (ngx_http_script_code_pt) |
2345 | | + ngx_http_script_copy_len_code; |
2346 | | + copy->len = src[i].key.len + sizeof(": ") - 1; |
2347 | | + |
2348 | | + |
2349 | | + size = (sizeof(ngx_http_script_copy_code_t) |
2350 | | + + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1) |
2351 | | + & ~(sizeof(uintptr_t) - 1); |
2352 | | + |
2353 | | + copy = ngx_array_push_n(conf->headers_set, size); |
2354 | | + if (copy == NULL) { |
2355 | | + return NGX_ERROR; |
2356 | | + } |
2357 | | + |
2358 | | + copy->code = ngx_http_script_copy_code; |
2359 | | + copy->len = src[i].key.len + sizeof(": ") - 1; |
2360 | | + |
2361 | | + p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); |
2362 | | + p = ngx_cpymem(p, src[i].key.data, src[i].key.len); |
2363 | | + *p++ = ':'; *p = ' '; |
2364 | | + |
2365 | | + |
2366 | | + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
2367 | | + |
2368 | | + sc.cf = cf; |
2369 | | + sc.source = &src[i].value; |
2370 | | + sc.flushes = &conf->flushes; |
2371 | | + sc.lengths = &conf->headers_set_len; |
2372 | | + sc.values = &conf->headers_set; |
2373 | | + |
2374 | | + if (ngx_http_script_compile(&sc) != NGX_OK) { |
2375 | | + return NGX_ERROR; |
2376 | | + } |
2377 | | + |
2378 | | + |
2379 | | + copy = ngx_array_push_n(conf->headers_set_len, |
2380 | | + sizeof(ngx_http_script_copy_code_t)); |
2381 | | + if (copy == NULL) { |
2382 | | + return NGX_ERROR; |
2383 | | + } |
2384 | | + |
2385 | | + copy->code = (ngx_http_script_code_pt) |
2386 | | + ngx_http_script_copy_len_code; |
2387 | | + copy->len = sizeof(CRLF) - 1; |
2388 | | + |
2389 | | + |
2390 | | + size = (sizeof(ngx_http_script_copy_code_t) |
2391 | | + + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) |
2392 | | + & ~(sizeof(uintptr_t) - 1); |
2393 | | + |
2394 | | + copy = ngx_array_push_n(conf->headers_set, size); |
2395 | | + if (copy == NULL) { |
2396 | | + return NGX_ERROR; |
2397 | | + } |
2398 | | + |
2399 | | + copy->code = ngx_http_script_copy_code; |
2400 | | + copy->len = sizeof(CRLF) - 1; |
2401 | | + |
2402 | | + p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); |
2403 | | + *p++ = CR; *p = LF; |
2404 | | + } |
2405 | | + |
2406 | | + code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); |
2407 | | + if (code == NULL) { |
2408 | | + return NGX_ERROR; |
2409 | | + } |
2410 | | + |
2411 | | + *code = (uintptr_t) NULL; |
2412 | | + |
2413 | | + code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t)); |
2414 | | + if (code == NULL) { |
2415 | | + return NGX_ERROR; |
2416 | | + } |
2417 | | + |
2418 | | + *code = (uintptr_t) NULL; |
2419 | | + } |
2420 | | + |
2421 | | + code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t)); |
2422 | | + if (code == NULL) { |
2423 | | + return NGX_ERROR; |
2424 | | + } |
2425 | | + |
2426 | | + *code = (uintptr_t) NULL; |
2427 | | + |
2428 | | + |
2429 | | + hash.hash = &conf->headers_set_hash; |
2430 | | + hash.key = ngx_hash_key_lc; |
2431 | | + hash.max_size = conf->headers_hash_max_size; |
2432 | | + hash.bucket_size = conf->headers_hash_bucket_size; |
2433 | | + hash.name = "proxy_headers_hash"; |
2434 | | + hash.pool = cf->pool; |
2435 | | + hash.temp_pool = NULL; |
2436 | | + |
2437 | | + return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts); |
2438 | | +} |
2439 | | + |
2440 | | + |
2441 | | +static char * |
2442 | | +ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2443 | | +{ |
2444 | | + ngx_http_proxy_loc_conf_t *plcf = conf; |
2445 | | + |
2446 | | + size_t add; |
2447 | | + u_short port; |
2448 | | + ngx_str_t *value, *url; |
2449 | | + ngx_url_t u; |
2450 | | + ngx_uint_t n; |
2451 | | + ngx_http_core_loc_conf_t *clcf; |
2452 | | + ngx_http_script_compile_t sc; |
2453 | | + |
2454 | | + if (plcf->upstream.upstream || plcf->proxy_lengths) { |
2455 | | + return "is duplicate"; |
2456 | | + } |
2457 | | + |
2458 | | + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); |
2459 | | + |
2460 | | + clcf->handler = ngx_http_proxy_handler; |
2461 | | + |
2462 | | + if (clcf->name.data[clcf->name.len - 1] == '/') { |
2463 | | + clcf->auto_redirect = 1; |
2464 | | + } |
2465 | | + |
2466 | | + value = cf->args->elts; |
2467 | | + |
2468 | | + url = &value[1]; |
2469 | | + |
2470 | | + n = ngx_http_script_variables_count(url); |
2471 | | + |
2472 | | + if (n) { |
2473 | | + |
2474 | | + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
2475 | | + |
2476 | | + sc.cf = cf; |
2477 | | + sc.source = url; |
2478 | | + sc.lengths = &plcf->proxy_lengths; |
2479 | | + sc.values = &plcf->proxy_values; |
2480 | | + sc.variables = n; |
2481 | | + sc.complete_lengths = 1; |
2482 | | + sc.complete_values = 1; |
2483 | | + |
2484 | | + if (ngx_http_script_compile(&sc) != NGX_OK) { |
2485 | | + return NGX_CONF_ERROR; |
2486 | | + } |
2487 | | + |
2488 | | +#if (NGX_HTTP_SSL) |
2489 | | + if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) { |
2490 | | + return NGX_CONF_ERROR; |
2491 | | + } |
2492 | | +#endif |
2493 | | + |
2494 | | + return NGX_CONF_OK; |
2495 | | + } |
2496 | | + |
2497 | | + if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) { |
2498 | | + add = 7; |
2499 | | + port = 80; |
2500 | | + |
2501 | | + } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) { |
2502 | | + |
2503 | | +#if (NGX_HTTP_SSL) |
2504 | | + if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) { |
2505 | | + return NGX_CONF_ERROR; |
2506 | | + } |
2507 | | + |
2508 | | + add = 8; |
2509 | | + port = 443; |
2510 | | +#else |
2511 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2512 | | + "https protocol requires SSL support"); |
2513 | | + return NGX_CONF_ERROR; |
2514 | | +#endif |
2515 | | + |
2516 | | + } else { |
2517 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix"); |
2518 | | + return NGX_CONF_ERROR; |
2519 | | + } |
2520 | | + |
2521 | | + ngx_memzero(&u, sizeof(ngx_url_t)); |
2522 | | + |
2523 | | + u.url.len = url->len - add; |
2524 | | + u.url.data = url->data + add; |
2525 | | + u.default_port = port; |
2526 | | + u.uri_part = 1; |
2527 | | + u.no_resolve = 1; |
2528 | | + |
2529 | | + plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); |
2530 | | + if (plcf->upstream.upstream == NULL) { |
2531 | | + return NGX_CONF_ERROR; |
2532 | | + } |
2533 | | + |
2534 | | + plcf->vars.schema.len = add; |
2535 | | + plcf->vars.schema.data = url->data; |
2536 | | + plcf->vars.key_start = plcf->vars.schema; |
2537 | | + |
2538 | | + ngx_http_proxy_set_vars(&u, &plcf->vars); |
2539 | | + |
2540 | | + plcf->location = clcf->name; |
2541 | | + |
2542 | | + if (clcf->named |
2543 | | +#if (NGX_PCRE) |
2544 | | + || clcf->regex |
2545 | | +#endif |
2546 | | + || clcf->noname) |
2547 | | + { |
2548 | | + if (plcf->vars.uri.len) { |
2549 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2550 | | + "\"proxy_pass\" may not have URI part in " |
2551 | | + "location given by regular expression, " |
2552 | | + "or inside named location, " |
2553 | | + "or inside the \"if\" statement, " |
2554 | | + "or inside the \"limit_except\" block"); |
2555 | | + return NGX_CONF_ERROR; |
2556 | | + } |
2557 | | + |
2558 | | + plcf->location.len = 0; |
2559 | | + } |
2560 | | + |
2561 | | + plcf->url = *url; |
2562 | | + |
2563 | | + return NGX_CONF_OK; |
2564 | | +} |
2565 | | + |
2566 | | + |
2567 | | +static char * |
2568 | | +ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2569 | | +{ |
2570 | | + ngx_http_proxy_loc_conf_t *plcf = conf; |
2571 | | + |
2572 | | + ngx_str_t *value; |
2573 | | + ngx_array_t *vars_lengths, *vars_values; |
2574 | | + ngx_http_script_compile_t sc; |
2575 | | + ngx_http_proxy_redirect_t *pr; |
2576 | | + |
2577 | | + if (plcf->redirect == 0) { |
2578 | | + return NGX_CONF_OK; |
2579 | | + } |
2580 | | + |
2581 | | + value = cf->args->elts; |
2582 | | + |
2583 | | + if (cf->args->nelts == 2) { |
2584 | | + if (ngx_strcmp(value[1].data, "off") == 0) { |
2585 | | + plcf->redirect = 0; |
2586 | | + plcf->redirects = NULL; |
2587 | | + return NGX_CONF_OK; |
2588 | | + } |
2589 | | + |
2590 | | + if (ngx_strcmp(value[1].data, "false") == 0) { |
2591 | | + ngx_conf_log_error(NGX_LOG_ERR, cf, 0, |
2592 | | + "invalid parameter \"false\", use \"off\" instead"); |
2593 | | + plcf->redirect = 0; |
2594 | | + plcf->redirects = NULL; |
2595 | | + return NGX_CONF_OK; |
2596 | | + } |
2597 | | + |
2598 | | + if (ngx_strcmp(value[1].data, "default") != 0) { |
2599 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2600 | | + "invalid parameter \"%V\"", &value[1]); |
2601 | | + return NGX_CONF_ERROR; |
2602 | | + } |
2603 | | + } |
2604 | | + |
2605 | | + if (plcf->redirects == NULL) { |
2606 | | + plcf->redirects = ngx_array_create(cf->pool, 1, |
2607 | | + sizeof(ngx_http_proxy_redirect_t)); |
2608 | | + if (plcf->redirects == NULL) { |
2609 | | + return NGX_CONF_ERROR; |
2610 | | + } |
2611 | | + } |
2612 | | + |
2613 | | + pr = ngx_array_push(plcf->redirects); |
2614 | | + if (pr == NULL) { |
2615 | | + return NGX_CONF_ERROR; |
2616 | | + } |
2617 | | + |
2618 | | + if (ngx_strcmp(value[1].data, "default") == 0) { |
2619 | | + if (plcf->proxy_lengths) { |
2620 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2621 | | + "\"proxy_redirect default\" may not be used " |
2622 | | + "with \"proxy_pass\" directive with variables"); |
2623 | | + return NGX_CONF_ERROR; |
2624 | | + } |
2625 | | + |
2626 | | + if (plcf->url.data == NULL) { |
2627 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2628 | | + "\"proxy_redirect default\" must go " |
2629 | | + "after the \"proxy_pass\" directive"); |
2630 | | + return NGX_CONF_ERROR; |
2631 | | + } |
2632 | | + |
2633 | | + pr->handler = ngx_http_proxy_rewrite_redirect_text; |
2634 | | + pr->redirect = plcf->url; |
2635 | | + |
2636 | | + if (plcf->vars.uri.len) { |
2637 | | + pr->replacement.text = plcf->location; |
2638 | | + |
2639 | | + } else { |
2640 | | + ngx_str_null(&pr->replacement.text); |
2641 | | + } |
2642 | | + |
2643 | | + return NGX_CONF_OK; |
2644 | | + } |
2645 | | + |
2646 | | + if (ngx_http_script_variables_count(&value[2]) == 0) { |
2647 | | + pr->handler = ngx_http_proxy_rewrite_redirect_text; |
2648 | | + pr->redirect = value[1]; |
2649 | | + pr->replacement.text = value[2]; |
2650 | | + |
2651 | | + return NGX_CONF_OK; |
2652 | | + } |
2653 | | + |
2654 | | + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
2655 | | + |
2656 | | + vars_lengths = NULL; |
2657 | | + vars_values = NULL; |
2658 | | + |
2659 | | + sc.cf = cf; |
2660 | | + sc.source = &value[2]; |
2661 | | + sc.lengths = &vars_lengths; |
2662 | | + sc.values = &vars_values; |
2663 | | + sc.complete_lengths = 1; |
2664 | | + sc.complete_values = 1; |
2665 | | + |
2666 | | + if (ngx_http_script_compile(&sc) != NGX_OK) { |
2667 | | + return NGX_CONF_ERROR; |
2668 | | + } |
2669 | | + |
2670 | | + pr->handler = ngx_http_proxy_rewrite_redirect_vars; |
2671 | | + pr->redirect = value[1]; |
2672 | | + pr->replacement.vars.lengths = vars_lengths->elts; |
2673 | | + pr->replacement.vars.values = vars_values->elts; |
2674 | | + |
2675 | | + return NGX_CONF_OK; |
2676 | | +} |
2677 | | + |
2678 | | + |
2679 | | +static char * |
2680 | | +ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2681 | | +{ |
2682 | | + ngx_http_proxy_loc_conf_t *plcf = conf; |
2683 | | + |
2684 | | + ngx_str_t *value; |
2685 | | + ngx_http_script_compile_t sc; |
2686 | | + |
2687 | | + if (plcf->upstream.store != NGX_CONF_UNSET |
2688 | | + || plcf->upstream.store_lengths) |
2689 | | + { |
2690 | | + return "is duplicate"; |
2691 | | + } |
2692 | | + |
2693 | | + value = cf->args->elts; |
2694 | | + |
2695 | | + if (ngx_strcmp(value[1].data, "off") == 0) { |
2696 | | + plcf->upstream.store = 0; |
2697 | | + return NGX_CONF_OK; |
2698 | | + } |
2699 | | + |
2700 | | +#if (NGX_HTTP_CACHE) |
2701 | | + |
2702 | | + if (plcf->upstream.cache != NGX_CONF_UNSET_PTR |
2703 | | + && plcf->upstream.cache != NULL) |
2704 | | + { |
2705 | | + return "is incompatible with \"proxy_cache\""; |
2706 | | + } |
2707 | | + |
2708 | | +#endif |
2709 | | + |
2710 | | + if (ngx_strcmp(value[1].data, "on") == 0) { |
2711 | | + plcf->upstream.store = 1; |
2712 | | + return NGX_CONF_OK; |
2713 | | + } |
2714 | | + |
2715 | | + /* include the terminating '\0' into script */ |
2716 | | + value[1].len++; |
2717 | | + |
2718 | | + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
2719 | | + |
2720 | | + sc.cf = cf; |
2721 | | + sc.source = &value[1]; |
2722 | | + sc.lengths = &plcf->upstream.store_lengths; |
2723 | | + sc.values = &plcf->upstream.store_values; |
2724 | | + sc.variables = ngx_http_script_variables_count(&value[1]); |
2725 | | + sc.complete_lengths = 1; |
2726 | | + sc.complete_values = 1; |
2727 | | + |
2728 | | + if (ngx_http_script_compile(&sc) != NGX_OK) { |
2729 | | + return NGX_CONF_ERROR; |
2730 | | + } |
2731 | | + |
2732 | | + return NGX_CONF_OK; |
2733 | | +} |
2734 | | + |
2735 | | + |
2736 | | +#if (NGX_HTTP_CACHE) |
2737 | | + |
2738 | | +static char * |
2739 | | +ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2740 | | +{ |
2741 | | + ngx_http_proxy_loc_conf_t *plcf = conf; |
2742 | | + |
2743 | | + ngx_str_t *value; |
2744 | | + |
2745 | | + value = cf->args->elts; |
2746 | | + |
2747 | | + if (plcf->upstream.cache != NGX_CONF_UNSET_PTR) { |
2748 | | + return "is duplicate"; |
2749 | | + } |
2750 | | + |
2751 | | + if (ngx_strcmp(value[1].data, "off") == 0) { |
2752 | | + plcf->upstream.cache = NULL; |
2753 | | + return NGX_CONF_OK; |
2754 | | + } |
2755 | | + |
2756 | | + if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) { |
2757 | | + return "is incompatible with \"proxy_store\""; |
2758 | | + } |
2759 | | + |
2760 | | + plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, |
2761 | | + &ngx_http_proxy_module); |
2762 | | + if (plcf->upstream.cache == NULL) { |
2763 | | + return NGX_CONF_ERROR; |
2764 | | + } |
2765 | | + |
2766 | | + return NGX_CONF_OK; |
2767 | | +} |
2768 | | + |
2769 | | + |
2770 | | +static char * |
2771 | | +ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2772 | | +{ |
2773 | | + ngx_http_proxy_loc_conf_t *plcf = conf; |
2774 | | + |
2775 | | + ngx_str_t *value; |
2776 | | + ngx_http_compile_complex_value_t ccv; |
2777 | | + |
2778 | | + value = cf->args->elts; |
2779 | | + |
2780 | | + if (plcf->cache_key.value.len) { |
2781 | | + return "is duplicate"; |
2782 | | + } |
2783 | | + |
2784 | | + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
2785 | | + |
2786 | | + ccv.cf = cf; |
2787 | | + ccv.value = &value[1]; |
2788 | | + ccv.complex_value = &plcf->cache_key; |
2789 | | + |
2790 | | + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
2791 | | + return NGX_CONF_ERROR; |
2792 | | + } |
2793 | | + |
2794 | | + return NGX_CONF_OK; |
2795 | | +} |
2796 | | + |
2797 | | +#endif |
2798 | | + |
2799 | | + |
2800 | | +static char * |
2801 | | +ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) |
2802 | | +{ |
2803 | | +#if (NGX_FREEBSD) |
2804 | | + ssize_t *np = data; |
2805 | | + |
2806 | | + if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) { |
2807 | | + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2808 | | + "\"proxy_send_lowat\" must be less than %d " |
2809 | | + "(sysctl net.inet.tcp.sendspace)", |
2810 | | + ngx_freebsd_net_inet_tcp_sendspace); |
2811 | | + |
2812 | | + return NGX_CONF_ERROR; |
2813 | | + } |
2814 | | + |
2815 | | +#elif !(NGX_HAVE_SO_SNDLOWAT) |
2816 | | + ssize_t *np = data; |
2817 | | + |
2818 | | + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
2819 | | + "\"proxy_send_lowat\" is not supported, ignored"); |
2820 | | + |
2821 | | + *np = 0; |
2822 | | + |
2823 | | +#endif |
2824 | | + |
2825 | | + return NGX_CONF_OK; |
2826 | | +} |
2827 | | + |
2828 | | + |
2829 | | +#if (NGX_HTTP_SSL) |
2830 | | + |
2831 | | +static ngx_int_t |
2832 | | +ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) |
2833 | | +{ |
2834 | | + ngx_pool_cleanup_t *cln; |
2835 | | + |
2836 | | + plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); |
2837 | | + if (plcf->upstream.ssl == NULL) { |
2838 | | + return NGX_ERROR; |
2839 | | + } |
2840 | | + |
2841 | | + plcf->upstream.ssl->log = cf->log; |
2842 | | + |
2843 | | + if (ngx_ssl_create(plcf->upstream.ssl, |
2844 | | + NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL) |
2845 | | + != NGX_OK) |
2846 | | + { |
2847 | | + return NGX_ERROR; |
2848 | | + } |
2849 | | + |
2850 | | + cln = ngx_pool_cleanup_add(cf->pool, 0); |
2851 | | + if (cln == NULL) { |
2852 | | + return NGX_ERROR; |
2853 | | + } |
2854 | | + |
2855 | | + cln->handler = ngx_ssl_cleanup_ctx; |
2856 | | + cln->data = plcf->upstream.ssl; |
2857 | | + |
2858 | | + return NGX_OK; |
2859 | | +} |
2860 | | + |
2861 | | +#endif |
2862 | | + |
2863 | | + |
2864 | | +static void |
2865 | | +ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v) |
2866 | | +{ |
2867 | | + if (u->family != AF_UNIX) { |
2868 | | + |
2869 | | + if (u->no_port || u->port == u->default_port) { |
2870 | | + |
2871 | | + v->host_header = u->host; |
2872 | | + |
2873 | | + if (u->default_port == 80) { |
2874 | | + ngx_str_set(&v->port, "80"); |
2875 | | + |
2876 | | + } else { |
2877 | | + ngx_str_set(&v->port, "443"); |
2878 | | + } |
2879 | | + |
2880 | | + } else { |
2881 | | + v->host_header.len = u->host.len + 1 + u->port_text.len; |
2882 | | + v->host_header.data = u->host.data; |
2883 | | + v->port = u->port_text; |
2884 | | + } |
2885 | | + |
2886 | | + v->key_start.len += v->host_header.len; |
2887 | | + |
2888 | | + } else { |
2889 | | + ngx_str_set(&v->host_header, "localhost"); |
2890 | | + ngx_str_null(&v->port); |
2891 | | + v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1; |
2892 | | + } |
2893 | | + |
2894 | | + v->uri = u->uri; |
2895 | | +} |
2896 | | diff -uNr ../nginx-0.8.55/src/http/ngx_http_upstream.h src/http/ngx_http_upstream.h |
2897 | | --- ../nginx-0.8.55/src/http/ngx_http_upstream.h 2010-07-19 02:36:04.000000000 -0700 |
2898 | | +++ src/http/ngx_http_upstream.h 2011-09-13 15:27:08.000000000 -0700 |
2899 | | @@ -177,6 +177,9 @@ |
2900 | | #if (NGX_HTTP_SSL) |
2901 | | ngx_ssl_t *ssl; |
2902 | | ngx_flag_t ssl_session_reuse; |
2903 | | + ngx_uint_t ssl_verify; |
2904 | | + ngx_uint_t ssl_verify_depth; |
2905 | | + ngx_str_t ssl_ca_certificate; |
2906 | | #endif |
2907 | | |
2908 | | } ngx_http_upstream_conf_t; |
2909 | | diff -uNr ../nginx-0.8.55/src/http/ngx_http_upstream.h.orig src/http/ngx_http_upstream.h.orig |
2910 | | --- ../nginx-0.8.55/src/http/ngx_http_upstream.h.orig 1969-12-31 16:00:00.000000000 -0800 |
2911 | | +++ src/http/ngx_http_upstream.h.orig 2010-07-19 02:36:04.000000000 -0700 |
2912 | | @@ -0,0 +1,345 @@ |
2913 | | + |
2914 | | +/* |
2915 | | + * Copyright (C) Igor Sysoev |
2916 | | + */ |
2917 | | + |
2918 | | + |
2919 | | +#ifndef _NGX_HTTP_UPSTREAM_H_INCLUDED_ |
2920 | | +#define _NGX_HTTP_UPSTREAM_H_INCLUDED_ |
2921 | | + |
2922 | | + |
2923 | | +#include <ngx_config.h> |
2924 | | +#include <ngx_core.h> |
2925 | | +#include <ngx_event.h> |
2926 | | +#include <ngx_event_connect.h> |
2927 | | +#include <ngx_event_pipe.h> |
2928 | | +#include <ngx_http.h> |
2929 | | + |
2930 | | + |
2931 | | +#define NGX_HTTP_UPSTREAM_FT_ERROR 0x00000002 |
2932 | | +#define NGX_HTTP_UPSTREAM_FT_TIMEOUT 0x00000004 |
2933 | | +#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER 0x00000008 |
2934 | | +#define NGX_HTTP_UPSTREAM_FT_HTTP_500 0x00000010 |
2935 | | +#define NGX_HTTP_UPSTREAM_FT_HTTP_502 0x00000020 |
2936 | | +#define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040 |
2937 | | +#define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080 |
2938 | | +#define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000100 |
2939 | | +#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000200 |
2940 | | +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000400 |
2941 | | +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000800 |
2942 | | +#define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 |
2943 | | +#define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 |
2944 | | + |
2945 | | +#define NGX_HTTP_UPSTREAM_FT_STATUS (NGX_HTTP_UPSTREAM_FT_HTTP_500 \ |
2946 | | + |NGX_HTTP_UPSTREAM_FT_HTTP_502 \ |
2947 | | + |NGX_HTTP_UPSTREAM_FT_HTTP_503 \ |
2948 | | + |NGX_HTTP_UPSTREAM_FT_HTTP_504 \ |
2949 | | + |NGX_HTTP_UPSTREAM_FT_HTTP_404) |
2950 | | + |
2951 | | +#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40 |
2952 | | + |
2953 | | + |
2954 | | +#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002 |
2955 | | +#define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES 0x00000004 |
2956 | | +#define NGX_HTTP_UPSTREAM_IGN_EXPIRES 0x00000008 |
2957 | | +#define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL 0x00000010 |
2958 | | +#define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE 0x00000020 |
2959 | | + |
2960 | | + |
2961 | | +typedef struct { |
2962 | | + ngx_msec_t bl_time; |
2963 | | + ngx_uint_t bl_state; |
2964 | | + |
2965 | | + ngx_uint_t status; |
2966 | | + time_t response_sec; |
2967 | | + ngx_uint_t response_msec; |
2968 | | + off_t response_length; |
2969 | | + |
2970 | | + ngx_str_t *peer; |
2971 | | +} ngx_http_upstream_state_t; |
2972 | | + |
2973 | | + |
2974 | | +typedef struct { |
2975 | | + ngx_hash_t headers_in_hash; |
2976 | | + ngx_array_t upstreams; |
2977 | | + /* ngx_http_upstream_srv_conf_t */ |
2978 | | +} ngx_http_upstream_main_conf_t; |
2979 | | + |
2980 | | +typedef struct ngx_http_upstream_srv_conf_s ngx_http_upstream_srv_conf_t; |
2981 | | + |
2982 | | +typedef ngx_int_t (*ngx_http_upstream_init_pt)(ngx_conf_t *cf, |
2983 | | + ngx_http_upstream_srv_conf_t *us); |
2984 | | +typedef ngx_int_t (*ngx_http_upstream_init_peer_pt)(ngx_http_request_t *r, |
2985 | | + ngx_http_upstream_srv_conf_t *us); |
2986 | | + |
2987 | | + |
2988 | | +typedef struct { |
2989 | | + ngx_http_upstream_init_pt init_upstream; |
2990 | | + ngx_http_upstream_init_peer_pt init; |
2991 | | + void *data; |
2992 | | +} ngx_http_upstream_peer_t; |
2993 | | + |
2994 | | + |
2995 | | +typedef struct { |
2996 | | + ngx_addr_t *addrs; |
2997 | | + ngx_uint_t naddrs; |
2998 | | + ngx_uint_t weight; |
2999 | | + ngx_uint_t max_fails; |
3000 | | + time_t fail_timeout; |
3001 | | + |
3002 | | + unsigned down:1; |
3003 | | + unsigned backup:1; |
3004 | | +} ngx_http_upstream_server_t; |
3005 | | + |
3006 | | + |
3007 | | +#define NGX_HTTP_UPSTREAM_CREATE 0x0001 |
3008 | | +#define NGX_HTTP_UPSTREAM_WEIGHT 0x0002 |
3009 | | +#define NGX_HTTP_UPSTREAM_MAX_FAILS 0x0004 |
3010 | | +#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT 0x0008 |
3011 | | +#define NGX_HTTP_UPSTREAM_DOWN 0x0010 |
3012 | | +#define NGX_HTTP_UPSTREAM_BACKUP 0x0020 |
3013 | | + |
3014 | | + |
3015 | | +struct ngx_http_upstream_srv_conf_s { |
3016 | | + ngx_http_upstream_peer_t peer; |
3017 | | + void **srv_conf; |
3018 | | + |
3019 | | + ngx_array_t *servers; /* ngx_http_upstream_server_t */ |
3020 | | + |
3021 | | + ngx_uint_t flags; |
3022 | | + ngx_str_t host; |
3023 | | + u_char *file_name; |
3024 | | + ngx_uint_t line; |
3025 | | + in_port_t port; |
3026 | | + in_port_t default_port; |
3027 | | +}; |
3028 | | + |
3029 | | + |
3030 | | +typedef struct { |
3031 | | + ngx_http_upstream_srv_conf_t *upstream; |
3032 | | + |
3033 | | + ngx_msec_t connect_timeout; |
3034 | | + ngx_msec_t send_timeout; |
3035 | | + ngx_msec_t read_timeout; |
3036 | | + ngx_msec_t timeout; |
3037 | | + |
3038 | | + size_t send_lowat; |
3039 | | + size_t buffer_size; |
3040 | | + |
3041 | | + size_t busy_buffers_size; |
3042 | | + size_t max_temp_file_size; |
3043 | | + size_t temp_file_write_size; |
3044 | | + |
3045 | | + size_t busy_buffers_size_conf; |
3046 | | + size_t max_temp_file_size_conf; |
3047 | | + size_t temp_file_write_size_conf; |
3048 | | + |
3049 | | + ngx_bufs_t bufs; |
3050 | | + |
3051 | | + ngx_uint_t ignore_headers; |
3052 | | + ngx_uint_t next_upstream; |
3053 | | + ngx_uint_t store_access; |
3054 | | + ngx_flag_t buffering; |
3055 | | + ngx_flag_t pass_request_headers; |
3056 | | + ngx_flag_t pass_request_body; |
3057 | | + |
3058 | | + ngx_flag_t ignore_client_abort; |
3059 | | + ngx_flag_t intercept_errors; |
3060 | | + ngx_flag_t cyclic_temp_file; |
3061 | | + |
3062 | | + ngx_path_t *temp_path; |
3063 | | + |
3064 | | + ngx_hash_t hide_headers_hash; |
3065 | | + ngx_array_t *hide_headers; |
3066 | | + ngx_array_t *pass_headers; |
3067 | | + |
3068 | | + ngx_addr_t *local; |
3069 | | + |
3070 | | +#if (NGX_HTTP_CACHE) |
3071 | | + ngx_shm_zone_t *cache; |
3072 | | + |
3073 | | + ngx_uint_t cache_min_uses; |
3074 | | + ngx_uint_t cache_use_stale; |
3075 | | + ngx_uint_t cache_methods; |
3076 | | + |
3077 | | + ngx_array_t *cache_valid; |
3078 | | + ngx_array_t *cache_bypass; |
3079 | | + ngx_array_t *no_cache; |
3080 | | +#endif |
3081 | | + |
3082 | | + ngx_array_t *store_lengths; |
3083 | | + ngx_array_t *store_values; |
3084 | | + |
3085 | | + signed store:2; |
3086 | | + unsigned intercept_404:1; |
3087 | | + unsigned change_buffering:1; |
3088 | | + |
3089 | | +#if (NGX_HTTP_SSL) |
3090 | | + ngx_ssl_t *ssl; |
3091 | | + ngx_flag_t ssl_session_reuse; |
3092 | | +#endif |
3093 | | + |
3094 | | +} ngx_http_upstream_conf_t; |
3095 | | + |
3096 | | + |
3097 | | +typedef struct { |
3098 | | + ngx_str_t name; |
3099 | | + ngx_http_header_handler_pt handler; |
3100 | | + ngx_uint_t offset; |
3101 | | + ngx_http_header_handler_pt copy_handler; |
3102 | | + ngx_uint_t conf; |
3103 | | + ngx_uint_t redirect; /* unsigned redirect:1; */ |
3104 | | +} ngx_http_upstream_header_t; |
3105 | | + |
3106 | | + |
3107 | | +typedef struct { |
3108 | | + ngx_list_t headers; |
3109 | | + |
3110 | | + ngx_uint_t status_n; |
3111 | | + ngx_str_t status_line; |
3112 | | + |
3113 | | + ngx_table_elt_t *status; |
3114 | | + ngx_table_elt_t *date; |
3115 | | + ngx_table_elt_t *server; |
3116 | | + ngx_table_elt_t *connection; |
3117 | | + |
3118 | | + ngx_table_elt_t *expires; |
3119 | | + ngx_table_elt_t *etag; |
3120 | | + ngx_table_elt_t *x_accel_expires; |
3121 | | + ngx_table_elt_t *x_accel_redirect; |
3122 | | + ngx_table_elt_t *x_accel_limit_rate; |
3123 | | + |
3124 | | + ngx_table_elt_t *content_type; |
3125 | | + ngx_table_elt_t *content_length; |
3126 | | + |
3127 | | + ngx_table_elt_t *last_modified; |
3128 | | + ngx_table_elt_t *location; |
3129 | | + ngx_table_elt_t *accept_ranges; |
3130 | | + ngx_table_elt_t *www_authenticate; |
3131 | | + |
3132 | | +#if (NGX_HTTP_GZIP) |
3133 | | + ngx_table_elt_t *content_encoding; |
3134 | | +#endif |
3135 | | + |
3136 | | + off_t content_length_n; |
3137 | | + |
3138 | | + ngx_array_t cache_control; |
3139 | | +} ngx_http_upstream_headers_in_t; |
3140 | | + |
3141 | | + |
3142 | | +typedef struct { |
3143 | | + ngx_str_t host; |
3144 | | + in_port_t port; |
3145 | | + ngx_uint_t no_port; /* unsigned no_port:1 */ |
3146 | | + |
3147 | | + ngx_uint_t naddrs; |
3148 | | + in_addr_t *addrs; |
3149 | | + |
3150 | | + struct sockaddr *sockaddr; |
3151 | | + socklen_t socklen; |
3152 | | + |
3153 | | + ngx_resolver_ctx_t *ctx; |
3154 | | +} ngx_http_upstream_resolved_t; |
3155 | | + |
3156 | | + |
3157 | | +typedef void (*ngx_http_upstream_handler_pt)(ngx_http_request_t *r, |
3158 | | + ngx_http_upstream_t *u); |
3159 | | + |
3160 | | + |
3161 | | +struct ngx_http_upstream_s { |
3162 | | + ngx_http_upstream_handler_pt read_event_handler; |
3163 | | + ngx_http_upstream_handler_pt write_event_handler; |
3164 | | + |
3165 | | + ngx_peer_connection_t peer; |
3166 | | + |
3167 | | + ngx_event_pipe_t *pipe; |
3168 | | + |
3169 | | + ngx_chain_t *request_bufs; |
3170 | | + |
3171 | | + ngx_output_chain_ctx_t output; |
3172 | | + ngx_chain_writer_ctx_t writer; |
3173 | | + |
3174 | | + ngx_http_upstream_conf_t *conf; |
3175 | | + |
3176 | | + ngx_http_upstream_headers_in_t headers_in; |
3177 | | + |
3178 | | + ngx_http_upstream_resolved_t *resolved; |
3179 | | + |
3180 | | + ngx_buf_t buffer; |
3181 | | + size_t length; |
3182 | | + |
3183 | | + ngx_chain_t *out_bufs; |
3184 | | + ngx_chain_t *busy_bufs; |
3185 | | + ngx_chain_t *free_bufs; |
3186 | | + |
3187 | | + ngx_int_t (*input_filter_init)(void *data); |
3188 | | + ngx_int_t (*input_filter)(void *data, ssize_t bytes); |
3189 | | + void *input_filter_ctx; |
3190 | | + |
3191 | | +#if (NGX_HTTP_CACHE) |
3192 | | + ngx_int_t (*create_key)(ngx_http_request_t *r); |
3193 | | +#endif |
3194 | | + ngx_int_t (*create_request)(ngx_http_request_t *r); |
3195 | | + ngx_int_t (*reinit_request)(ngx_http_request_t *r); |
3196 | | + ngx_int_t (*process_header)(ngx_http_request_t *r); |
3197 | | + void (*abort_request)(ngx_http_request_t *r); |
3198 | | + void (*finalize_request)(ngx_http_request_t *r, |
3199 | | + ngx_int_t rc); |
3200 | | + ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r, |
3201 | | + ngx_table_elt_t *h, size_t prefix); |
3202 | | + |
3203 | | + ngx_msec_t timeout; |
3204 | | + |
3205 | | + ngx_http_upstream_state_t *state; |
3206 | | + |
3207 | | + ngx_str_t method; |
3208 | | + ngx_str_t schema; |
3209 | | + ngx_str_t uri; |
3210 | | + |
3211 | | + ngx_http_cleanup_pt *cleanup; |
3212 | | + |
3213 | | + unsigned store:1; |
3214 | | + unsigned cacheable:1; |
3215 | | + unsigned accel:1; |
3216 | | + unsigned ssl:1; |
3217 | | +#if (NGX_HTTP_CACHE) |
3218 | | + unsigned cache_status:3; |
3219 | | +#endif |
3220 | | + |
3221 | | + unsigned buffering:1; |
3222 | | + |
3223 | | + unsigned request_sent:1; |
3224 | | + unsigned header_sent:1; |
3225 | | +}; |
3226 | | + |
3227 | | + |
3228 | | +typedef struct { |
3229 | | + ngx_uint_t status; |
3230 | | + ngx_uint_t mask; |
3231 | | +} ngx_http_upstream_next_t; |
3232 | | + |
3233 | | + |
3234 | | +ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, |
3235 | | + ngx_http_variable_value_t *v, uintptr_t data); |
3236 | | + |
3237 | | +ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r); |
3238 | | +void ngx_http_upstream_init(ngx_http_request_t *r); |
3239 | | +ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf, |
3240 | | + ngx_url_t *u, ngx_uint_t flags); |
3241 | | +char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, |
3242 | | + void *conf); |
3243 | | +ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, |
3244 | | + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev, |
3245 | | + ngx_str_t *default_hide_headers, ngx_hash_init_t *hash); |
3246 | | + |
3247 | | + |
3248 | | +#define ngx_http_conf_upstream_srv_conf(uscf, module) \ |
3249 | | + uscf->srv_conf[module.ctx_index] |
3250 | | + |
3251 | | + |
3252 | | +extern ngx_module_t ngx_http_upstream_module; |
3253 | | +extern ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[]; |
3254 | | +extern ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[]; |
3255 | | + |
3256 | | + |
3257 | | +#endif /* _NGX_HTTP_UPSTREAM_H_INCLUDED_ */ |
3258 | | |
3259 | | }}} |
| 1 | Proxy should be able to verify peer's SSL certificate. |