blob: 325a1a00b739ee2c991669d852b2f6b8f61cf494 [file] [log] [blame]
Igor Sysoev02f742b2005-04-08 15:18:55 +00001
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002/*
Igor Sysoev02f742b2005-04-08 15:18:55 +00003 * Copyright (C) Igor Sysoev
4 */
5
6
7#include <ngx_config.h>
8#include <ngx_core.h>
Igor Sysoev02f742b2005-04-08 15:18:55 +00009#include <ngx_http.h>
10
11
Igor Sysoev899b44e2005-05-12 14:58:06 +000012typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t;
13
14typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
15 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
16
17struct ngx_http_proxy_redirect_s {
Igor Sysoev6f134cc2006-05-23 14:54:58 +000018 ngx_http_proxy_redirect_pt handler;
19 ngx_str_t redirect;
Igor Sysoev899b44e2005-05-12 14:58:06 +000020
21 union {
Igor Sysoev6f134cc2006-05-23 14:54:58 +000022 ngx_str_t text;
Igor Sysoev899b44e2005-05-12 14:58:06 +000023
24 struct {
Igor Sysoev6f134cc2006-05-23 14:54:58 +000025 void *lengths;
26 void *values;
Igor Sysoev899b44e2005-05-12 14:58:06 +000027 } vars;
28
Igor Sysoev6f134cc2006-05-23 14:54:58 +000029 void *regex;
Igor Sysoev899b44e2005-05-12 14:58:06 +000030 } replacement;
31};
32
33
Igor Sysoev02f742b2005-04-08 15:18:55 +000034typedef struct {
Igor Sysoev52859f22009-03-23 13:14:51 +000035 ngx_str_t key_start;
Igor Sysoev73c31212008-12-10 14:44:48 +000036 ngx_str_t schema;
Igor Sysoev96dd8af2007-11-27 13:34:13 +000037 ngx_str_t host_header;
38 ngx_str_t port;
39 ngx_str_t uri;
40} ngx_http_proxy_vars_t;
41
42
43typedef struct {
Igor Sysoev6f134cc2006-05-23 14:54:58 +000044 ngx_http_upstream_conf_t upstream;
Igor Sysoev02f742b2005-04-08 15:18:55 +000045
Igor Sysoev6f134cc2006-05-23 14:54:58 +000046 ngx_array_t *flushes;
47 ngx_array_t *body_set_len;
48 ngx_array_t *body_set;
49 ngx_array_t *headers_set_len;
50 ngx_array_t *headers_set;
51 ngx_hash_t headers_set_hash;
Igor Sysoev02f742b2005-04-08 15:18:55 +000052
Igor Sysoev6f134cc2006-05-23 14:54:58 +000053 ngx_array_t *headers_source;
Igor Sysoev02f742b2005-04-08 15:18:55 +000054
Igor Sysoev96dd8af2007-11-27 13:34:13 +000055 ngx_array_t *proxy_lengths;
56 ngx_array_t *proxy_values;
57
Igor Sysoev6f134cc2006-05-23 14:54:58 +000058 ngx_array_t *redirects;
Igor Sysoev02f742b2005-04-08 15:18:55 +000059
Igor Sysoev6f134cc2006-05-23 14:54:58 +000060 ngx_str_t body_source;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000061
Igor Sysoev6f134cc2006-05-23 14:54:58 +000062 ngx_str_t method;
Igor Sysoev96dd8af2007-11-27 13:34:13 +000063 ngx_str_t location;
64 ngx_str_t url;
65
Igor Sysoev44a69c82009-04-06 08:58:44 +000066#if (NGX_HTTP_CACHE)
67 ngx_http_complex_value_t cache_key;
68#endif
69
Igor Sysoev96dd8af2007-11-27 13:34:13 +000070 ngx_http_proxy_vars_t vars;
Igor Sysoev02f742b2005-04-08 15:18:55 +000071
Igor Sysoev6f134cc2006-05-23 14:54:58 +000072 ngx_flag_t redirect;
Igor Sysoev8a19bff2007-04-22 20:21:59 +000073
74 ngx_uint_t headers_hash_max_size;
75 ngx_uint_t headers_hash_bucket_size;
Igor Sysoev02f742b2005-04-08 15:18:55 +000076} ngx_http_proxy_loc_conf_t;
77
78
79typedef struct {
Igor Sysoev54b35b02010-06-15 15:15:06 +000080 ngx_http_status_t status;
Igor Sysoev96dd8af2007-11-27 13:34:13 +000081 ngx_http_proxy_vars_t vars;
Igor Sysoev6f134cc2006-05-23 14:54:58 +000082 size_t internal_body_length;
Igor Sysoev899b44e2005-05-12 14:58:06 +000083} ngx_http_proxy_ctx_t;
Igor Sysoev02f742b2005-04-08 15:18:55 +000084
Igor Sysoev02f742b2005-04-08 15:18:55 +000085
Igor Sysoev96dd8af2007-11-27 13:34:13 +000086static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
87 ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
Igor Sysoev52859f22009-03-23 13:14:51 +000088#if (NGX_HTTP_CACHE)
89static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
90#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +000091static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
92static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
Igor Sysoev899b44e2005-05-12 14:58:06 +000093static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
Igor Sysoev02f742b2005-04-08 15:18:55 +000094static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
Igor Sysoev02f742b2005-04-08 15:18:55 +000095static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
96static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
97 ngx_int_t rc);
98
Igor Sysoev09c684b2005-11-09 17:25:55 +000099static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
100 ngx_http_variable_value_t *v, uintptr_t data);
101static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
102 ngx_http_variable_value_t *v, uintptr_t data);
103static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +0000104 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
Igor Sysoev09c684b2005-11-09 17:25:55 +0000105 ngx_http_variable_value_t *v, uintptr_t data);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000106static ngx_int_t
107 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
108 ngx_http_variable_value_t *v, uintptr_t data);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000109static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
110 ngx_table_elt_t *h, size_t prefix);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000111
Igor Sysoev899b44e2005-05-12 14:58:06 +0000112static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000113static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
114static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
115 void *parent, void *child);
Igor Sysoev52859f22009-03-23 13:14:51 +0000116static ngx_int_t ngx_http_proxy_merge_headers(ngx_conf_t *cf,
117 ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000118
119static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
120 void *conf);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000121static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000122 void *conf);
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000123static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
124 void *conf);
Igor Sysoev52859f22009-03-23 13:14:51 +0000125#if (NGX_HTTP_CACHE)
126static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
127 void *conf);
Igor Sysoev44a69c82009-04-06 08:58:44 +0000128static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
129 void *conf);
Igor Sysoev52859f22009-03-23 13:14:51 +0000130#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +0000131
Igor Sysoev02f742b2005-04-08 15:18:55 +0000132static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
133
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000134#if (NGX_HTTP_SSL)
135static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
136 ngx_http_proxy_loc_conf_t *plcf);
137#endif
Igor Sysoev52859f22009-03-23 13:14:51 +0000138static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000139
Igor Sysoev899b44e2005-05-12 14:58:06 +0000140
Igor Sysoev02f742b2005-04-08 15:18:55 +0000141static ngx_conf_post_t ngx_http_proxy_lowat_post =
Igor Sysoev899b44e2005-05-12 14:58:06 +0000142 { ngx_http_proxy_lowat_check };
143
Igor Sysoev02f742b2005-04-08 15:18:55 +0000144
145static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
146 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
147 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
148 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
149 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
Igor Sysoev797c6ef2008-09-30 15:39:02 +0000150 { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
Igor Sysoev8fea8852006-03-15 09:53:04 +0000151 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
Igor Sysoev797c6ef2008-09-30 15:39:02 +0000152 { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000153 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
Igor Sysoev55192e72009-06-06 18:49:47 +0000154 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000155 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000156 { ngx_null_string, 0 }
157};
158
159
Igor Sysoev52859f22009-03-23 13:14:51 +0000160ngx_module_t ngx_http_proxy_module;
161
162
Igor Sysoev02f742b2005-04-08 15:18:55 +0000163static ngx_command_t ngx_http_proxy_commands[] = {
164
165 { ngx_string("proxy_pass"),
Igor Sysoeve927b1e2006-11-14 12:43:14 +0000166 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000167 ngx_http_proxy_pass,
168 NGX_HTTP_LOC_CONF_OFFSET,
169 0,
170 NULL },
171
Igor Sysoev899b44e2005-05-12 14:58:06 +0000172 { ngx_string("proxy_redirect"),
173 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
174 ngx_http_proxy_redirect,
175 NGX_HTTP_LOC_CONF_OFFSET,
176 0,
177 NULL },
178
Igor Sysoev58feb532007-07-12 11:19:05 +0000179 { ngx_string("proxy_store"),
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000180 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
181 ngx_http_proxy_store,
182 NGX_HTTP_LOC_CONF_OFFSET,
183 0,
184 NULL },
185
186 { ngx_string("proxy_store_access"),
Igor Sysoev58feb532007-07-12 11:19:05 +0000187 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
188 ngx_conf_set_access_slot,
189 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000190 offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access),
Igor Sysoev58feb532007-07-12 11:19:05 +0000191 NULL },
192
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000193 { ngx_string("proxy_buffering"),
194 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
195 ngx_conf_set_flag_slot,
196 NGX_HTTP_LOC_CONF_OFFSET,
197 offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
198 NULL },
199
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000200 { ngx_string("proxy_ignore_client_abort"),
201 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
202 ngx_conf_set_flag_slot,
203 NGX_HTTP_LOC_CONF_OFFSET,
204 offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
205 NULL },
206
Igor Sysoev72e92872009-11-02 15:24:02 +0000207 { ngx_string("proxy_bind"),
208 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoevbd375b92009-12-23 14:22:17 +0000209 ngx_http_upstream_bind_set_slot,
Igor Sysoev72e92872009-11-02 15:24:02 +0000210 NGX_HTTP_LOC_CONF_OFFSET,
211 offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
212 NULL },
213
Igor Sysoev02f742b2005-04-08 15:18:55 +0000214 { ngx_string("proxy_connect_timeout"),
215 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
216 ngx_conf_set_msec_slot,
217 NGX_HTTP_LOC_CONF_OFFSET,
218 offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
219 NULL },
220
221 { ngx_string("proxy_send_timeout"),
222 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
223 ngx_conf_set_msec_slot,
224 NGX_HTTP_LOC_CONF_OFFSET,
225 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
226 NULL },
227
228 { ngx_string("proxy_send_lowat"),
229 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
230 ngx_conf_set_size_slot,
231 NGX_HTTP_LOC_CONF_OFFSET,
232 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
233 &ngx_http_proxy_lowat_post },
234
Igor Sysoevef809b82006-06-28 16:00:26 +0000235 { ngx_string("proxy_intercept_errors"),
236 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
237 ngx_conf_set_flag_slot,
238 NGX_HTTP_LOC_CONF_OFFSET,
239 offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors),
240 NULL },
241
Igor Sysoev899b44e2005-05-12 14:58:06 +0000242 { ngx_string("proxy_set_header"),
243 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000244 ngx_conf_set_keyval_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000245 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000246 offsetof(ngx_http_proxy_loc_conf_t, headers_source),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000247 NULL },
248
Igor Sysoev8a19bff2007-04-22 20:21:59 +0000249 { ngx_string("proxy_headers_hash_max_size"),
250 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
251 ngx_conf_set_num_slot,
252 NGX_HTTP_LOC_CONF_OFFSET,
253 offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size),
254 NULL },
255
256 { ngx_string("proxy_headers_hash_bucket_size"),
257 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
258 ngx_conf_set_num_slot,
259 NGX_HTTP_LOC_CONF_OFFSET,
260 offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size),
261 NULL },
262
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000263 { ngx_string("proxy_set_body"),
264 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
265 ngx_conf_set_str_slot,
266 NGX_HTTP_LOC_CONF_OFFSET,
267 offsetof(ngx_http_proxy_loc_conf_t, body_source),
268 NULL },
269
Igor Sysoev899b44e2005-05-12 14:58:06 +0000270 { ngx_string("proxy_method"),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000271 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev78452232005-10-12 13:50:36 +0000272 ngx_conf_set_str_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000273 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev78452232005-10-12 13:50:36 +0000274 offsetof(ngx_http_proxy_loc_conf_t, method),
275 NULL },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000276
Igor Sysoev899b44e2005-05-12 14:58:06 +0000277 { ngx_string("proxy_pass_request_headers"),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000278 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
279 ngx_conf_set_flag_slot,
280 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000281 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
282 NULL },
283
284 { ngx_string("proxy_pass_request_body"),
285 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
286 ngx_conf_set_flag_slot,
287 NGX_HTTP_LOC_CONF_OFFSET,
288 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000289 NULL },
290
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000291 { ngx_string("proxy_buffer_size"),
292 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
293 ngx_conf_set_size_slot,
294 NGX_HTTP_LOC_CONF_OFFSET,
295 offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size),
296 NULL },
297
Igor Sysoev02f742b2005-04-08 15:18:55 +0000298 { ngx_string("proxy_read_timeout"),
299 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
300 ngx_conf_set_msec_slot,
301 NGX_HTTP_LOC_CONF_OFFSET,
302 offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
303 NULL },
304
305 { ngx_string("proxy_buffers"),
306 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
307 ngx_conf_set_bufs_slot,
308 NGX_HTTP_LOC_CONF_OFFSET,
309 offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
310 NULL },
311
312 { ngx_string("proxy_busy_buffers_size"),
313 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
314 ngx_conf_set_size_slot,
315 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000316 offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000317 NULL },
318
Igor Sysoev52859f22009-03-23 13:14:51 +0000319#if (NGX_HTTP_CACHE)
320
321 { ngx_string("proxy_cache"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000322 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev52859f22009-03-23 13:14:51 +0000323 ngx_http_proxy_cache,
Igor Sysoev0ded9db2009-03-23 16:40:11 +0000324 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev64416aa2009-03-23 15:57:57 +0000325 0,
Igor Sysoev52859f22009-03-23 13:14:51 +0000326 NULL },
327
Igor Sysoev44a69c82009-04-06 08:58:44 +0000328 { ngx_string("proxy_cache_key"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000329 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev44a69c82009-04-06 08:58:44 +0000330 ngx_http_proxy_cache_key,
331 NGX_HTTP_LOC_CONF_OFFSET,
332 0,
333 NULL },
334
Igor Sysoev52859f22009-03-23 13:14:51 +0000335 { ngx_string("proxy_cache_path"),
336 NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
337 ngx_http_file_cache_set_slot,
338 0,
339 0,
340 &ngx_http_proxy_module },
341
Igor Sysoevf7d659a2010-07-19 09:36:04 +0000342 { ngx_string("proxy_cache_bypass"),
343 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
344 ngx_http_set_predicate_slot,
345 NGX_HTTP_LOC_CONF_OFFSET,
346 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
347 NULL },
348
Igor Sysoev9b2763a2010-05-24 11:01:05 +0000349 { ngx_string("proxy_no_cache"),
350 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
Igor Sysoevf3870c62010-07-14 11:15:45 +0000351 ngx_http_set_predicate_slot,
Igor Sysoev9b2763a2010-05-24 11:01:05 +0000352 NGX_HTTP_LOC_CONF_OFFSET,
353 offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
354 NULL },
355
Igor Sysoev52859f22009-03-23 13:14:51 +0000356 { ngx_string("proxy_cache_valid"),
357 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
358 ngx_http_file_cache_valid_set_slot,
359 NGX_HTTP_LOC_CONF_OFFSET,
360 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
361 NULL },
362
363 { ngx_string("proxy_cache_min_uses"),
364 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
365 ngx_conf_set_num_slot,
366 NGX_HTTP_LOC_CONF_OFFSET,
367 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
368 NULL },
369
370 { ngx_string("proxy_cache_use_stale"),
371 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
372 ngx_conf_set_bitmask_slot,
373 NGX_HTTP_LOC_CONF_OFFSET,
374 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
375 &ngx_http_proxy_next_upstream_masks },
376
Igor Sysoev5ed36912009-05-19 13:27:27 +0000377 { ngx_string("proxy_cache_methods"),
378 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
379 ngx_conf_set_bitmask_slot,
380 NGX_HTTP_LOC_CONF_OFFSET,
381 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
382 &ngx_http_upstream_cache_method_mask },
383
Igor Sysoev52859f22009-03-23 13:14:51 +0000384#endif
385
Igor Sysoev02f742b2005-04-08 15:18:55 +0000386 { ngx_string("proxy_temp_path"),
387 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
388 ngx_conf_set_path_slot,
389 NGX_HTTP_LOC_CONF_OFFSET,
390 offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
Igor Sysoev52859f22009-03-23 13:14:51 +0000391 NULL },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000392
393 { ngx_string("proxy_max_temp_file_size"),
394 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
395 ngx_conf_set_size_slot,
396 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000397 offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000398 NULL },
399
400 { ngx_string("proxy_temp_file_write_size"),
401 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
402 ngx_conf_set_size_slot,
403 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000404 offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000405 NULL },
406
407 { ngx_string("proxy_next_upstream"),
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000408 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000409 ngx_conf_set_bitmask_slot,
410 NGX_HTTP_LOC_CONF_OFFSET,
411 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
412 &ngx_http_proxy_next_upstream_masks },
413
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000414 { ngx_string("proxy_pass_header"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000415 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000416 ngx_conf_set_str_array_slot,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000417 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000418 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000419 NULL },
420
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000421 { ngx_string("proxy_hide_header"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000422 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000423 ngx_conf_set_str_array_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000424 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000425 offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000426 NULL },
427
Igor Sysoevb01c9cc2009-04-30 16:15:07 +0000428 { ngx_string("proxy_ignore_headers"),
429 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
430 ngx_conf_set_bitmask_slot,
431 NGX_HTTP_LOC_CONF_OFFSET,
432 offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
Igor Sysoev7e14b502010-07-02 09:25:38 +0000433 &ngx_http_upstream_ignore_headers_masks },
Igor Sysoevb01c9cc2009-04-30 16:15:07 +0000434
Igor Sysoev916ee8e2008-08-17 17:47:52 +0000435#if (NGX_HTTP_SSL)
436
437 { ngx_string("proxy_ssl_session_reuse"),
438 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
439 ngx_conf_set_flag_slot,
440 NGX_HTTP_LOC_CONF_OFFSET,
441 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
442 NULL },
443
444#endif
445
Igor Sysoev02f742b2005-04-08 15:18:55 +0000446 ngx_null_command
447};
448
449
Igor Sysoev8f125582006-07-28 15:16:17 +0000450static ngx_http_module_t ngx_http_proxy_module_ctx = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000451 ngx_http_proxy_add_variables, /* preconfiguration */
452 NULL, /* postconfiguration */
Igor Sysoev02f742b2005-04-08 15:18:55 +0000453
454 NULL, /* create main configuration */
455 NULL, /* init main configuration */
456
457 NULL, /* create server configuration */
458 NULL, /* merge server configuration */
459
460 ngx_http_proxy_create_loc_conf, /* create location configration */
461 ngx_http_proxy_merge_loc_conf /* merge location configration */
462};
463
464
465ngx_module_t ngx_http_proxy_module = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000466 NGX_MODULE_V1,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000467 &ngx_http_proxy_module_ctx, /* module context */
468 ngx_http_proxy_commands, /* module directives */
469 NGX_HTTP_MODULE, /* module type */
Igor Sysoeve5733802005-09-08 14:36:09 +0000470 NULL, /* init master */
Igor Sysoev899b44e2005-05-12 14:58:06 +0000471 NULL, /* init module */
Igor Sysoeve5733802005-09-08 14:36:09 +0000472 NULL, /* init process */
473 NULL, /* init thread */
474 NULL, /* exit thread */
475 NULL, /* exit process */
476 NULL, /* exit master */
477 NGX_MODULE_V1_PADDING
Igor Sysoev02f742b2005-04-08 15:18:55 +0000478};
479
480
Igor Sysoev02f742b2005-04-08 15:18:55 +0000481static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
482
Igor Sysoev899b44e2005-05-12 14:58:06 +0000483
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000484static ngx_keyval_t ngx_http_proxy_headers[] = {
485 { ngx_string("Host"), ngx_string("$proxy_host") },
486 { ngx_string("Connection"), ngx_string("close") },
487 { ngx_string("Keep-Alive"), ngx_string("") },
Igor Sysoev1e1f4c82008-06-26 13:00:39 +0000488 { ngx_string("Expect"), ngx_string("") },
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000489 { ngx_null_string, ngx_null_string }
490};
491
492
Igor Sysoev2b89d202009-04-15 11:42:49 +0000493static ngx_str_t ngx_http_proxy_hide_headers[] = {
494 ngx_string("Date"),
495 ngx_string("Server"),
496 ngx_string("X-Pad"),
497 ngx_string("X-Accel-Expires"),
498 ngx_string("X-Accel-Redirect"),
499 ngx_string("X-Accel-Limit-Rate"),
500 ngx_string("X-Accel-Buffering"),
501 ngx_string("X-Accel-Charset"),
502 ngx_null_string
503};
504
505
Igor Sysoev081662a2009-04-15 11:21:12 +0000506#if (NGX_HTTP_CACHE)
507
508static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
509 { ngx_string("Host"), ngx_string("$proxy_host") },
510 { ngx_string("Connection"), ngx_string("close") },
511 { ngx_string("Keep-Alive"), ngx_string("") },
512 { ngx_string("Expect"), ngx_string("") },
513 { ngx_string("If-Modified-Since"), ngx_string("") },
514 { ngx_string("If-Unmodified-Since"), ngx_string("") },
Igor Sysoevc7c0d612009-12-22 16:41:34 +0000515 { ngx_string("If-None-Match"), ngx_string("") },
Igor Sysoev081662a2009-04-15 11:21:12 +0000516 { ngx_string("If-Match"), ngx_string("") },
517 { ngx_string("Range"), ngx_string("") },
518 { ngx_string("If-Range"), ngx_string("") },
519 { ngx_null_string, ngx_null_string }
520};
521
Igor Sysoev2b89d202009-04-15 11:42:49 +0000522#endif
523
Igor Sysoev899b44e2005-05-12 14:58:06 +0000524
525static ngx_http_variable_t ngx_http_proxy_vars[] = {
526
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000527 { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
Igor Sysoev20612592008-03-11 14:10:11 +0000528 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000529
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000530 { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
Igor Sysoev20612592008-03-11 14:10:11 +0000531 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000532
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000533 { ngx_string("proxy_add_x_forwarded_for"), NULL,
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000534 ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000535
536#if 0
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000537 { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000538#endif
539
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000540 { ngx_string("proxy_internal_body_length"), NULL,
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000541 ngx_http_proxy_internal_body_length_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000542
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000543 { ngx_null_string, NULL, NULL, 0, 0, 0 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000544};
Igor Sysoev02f742b2005-04-08 15:18:55 +0000545
546
Igor Sysoev52859f22009-03-23 13:14:51 +0000547static ngx_path_init_t ngx_http_proxy_temp_path = {
548 ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
549};
550
551
Igor Sysoev02f742b2005-04-08 15:18:55 +0000552static ngx_int_t
553ngx_http_proxy_handler(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000554{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000555 ngx_int_t rc;
556 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000557 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000558 ngx_http_proxy_loc_conf_t *plcf;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000559
Igor Sysoev15b74202009-07-27 13:25:29 +0000560 if (ngx_http_upstream_create(r) != NGX_OK) {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000561 return NGX_HTTP_INTERNAL_SERVER_ERROR;
562 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000563
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000564 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
565 if (ctx == NULL) {
566 return NGX_ERROR;
567 }
568
569 ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
570
571 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
572
Igor Sysoev15b74202009-07-27 13:25:29 +0000573 u = r->upstream;
574
Igor Sysoeve4994fb2010-08-03 12:53:06 +0000575 if (plcf->proxy_lengths == NULL) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000576 ctx->vars = plcf->vars;
Igor Sysoev73c31212008-12-10 14:44:48 +0000577 u->schema = plcf->vars.schema;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000578#if (NGX_HTTP_SSL)
579 u->ssl = (plcf->upstream.ssl != NULL);
580#endif
581
582 } else {
583 if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
584 return NGX_HTTP_INTERNAL_SERVER_ERROR;
585 }
586 }
587
Igor Sysoev02f742b2005-04-08 15:18:55 +0000588 u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
589
590 u->conf = &plcf->upstream;
591
Igor Sysoev52859f22009-03-23 13:14:51 +0000592#if (NGX_HTTP_CACHE)
593 u->create_key = ngx_http_proxy_create_key;
594#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +0000595 u->create_request = ngx_http_proxy_create_request;
596 u->reinit_request = ngx_http_proxy_reinit_request;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000597 u->process_header = ngx_http_proxy_process_status_line;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000598 u->abort_request = ngx_http_proxy_abort_request;
599 u->finalize_request = ngx_http_proxy_finalize_request;
Igor Sysoevaed1ac12010-03-25 13:27:52 +0000600 r->state = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000601
Igor Sysoev899b44e2005-05-12 14:58:06 +0000602 if (plcf->redirects) {
603 u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
604 }
605
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000606 u->buffering = plcf->upstream.buffering;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000607
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000608 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
609 if (u->pipe == NULL) {
610 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000611 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000612
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000613 u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
614
Igor Sysoev899b44e2005-05-12 14:58:06 +0000615 u->accel = 1;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000616
Igor Sysoev02f742b2005-04-08 15:18:55 +0000617 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
618
619 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
620 return rc;
621 }
622
623 return NGX_DONE;
624}
625
626
627static ngx_int_t
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000628ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
629 ngx_http_proxy_loc_conf_t *plcf)
630{
Igor Sysoev52859f22009-03-23 13:14:51 +0000631 u_char *p;
632 size_t add;
633 u_short port;
634 ngx_str_t proxy;
635 ngx_url_t url;
636 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000637
638 if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
639 plcf->proxy_values->elts)
640 == NULL)
641 {
642 return NGX_ERROR;
643 }
644
645 if (ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0) {
646
647 add = 7;
648 port = 80;
649
650#if (NGX_HTTP_SSL)
651
652 } else if (ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0) {
653
654 add = 8;
655 port = 443;
656 r->upstream->ssl = 1;
657
658#endif
659
660 } else {
661 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
662 "invalid URL prefix in \"%V\"", &proxy);
663 return NGX_ERROR;
664 }
665
Igor Sysoev52859f22009-03-23 13:14:51 +0000666 u = r->upstream;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000667
Igor Sysoev52859f22009-03-23 13:14:51 +0000668 u->schema.len = add;
669 u->schema.data = proxy.data;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000670
Igor Sysoev52859f22009-03-23 13:14:51 +0000671 ngx_memzero(&url, sizeof(ngx_url_t));
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000672
Igor Sysoev52859f22009-03-23 13:14:51 +0000673 url.url.len = proxy.len - add;
674 url.url.data = proxy.data + add;
675 url.default_port = port;
676 url.uri_part = 1;
677 url.no_resolve = 1;
678
679 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
680 if (url.err) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000681 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev52859f22009-03-23 13:14:51 +0000682 "%s in upstream \"%V\"", url.err, &url.url);
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000683 }
684
685 return NGX_ERROR;
686 }
687
Igor Sysoev6c71b882009-11-15 11:36:12 +0000688 if (url.uri.len) {
689 if (url.uri.data[0] == '?') {
690 p = ngx_pnalloc(r->pool, url.uri.len + 1);
691 if (p == NULL) {
692 return NGX_ERROR;
693 }
694
695 *p++ = '/';
696 ngx_memcpy(p, url.uri.data, url.uri.len);
697
698 url.uri.len++;
699 url.uri.data = p - 1;
Igor Sysoev164abfb2008-10-24 19:34:24 +0000700 }
701
Igor Sysoev6c71b882009-11-15 11:36:12 +0000702 } else {
703 url.uri = r->unparsed_uri;
Igor Sysoev164abfb2008-10-24 19:34:24 +0000704 }
705
Igor Sysoev52859f22009-03-23 13:14:51 +0000706 ctx->vars.key_start = u->schema;
707
708 ngx_http_proxy_set_vars(&url, &ctx->vars);
709
710 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
711 if (u->resolved == NULL) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000712 return NGX_ERROR;
713 }
714
Igor Sysoev52859f22009-03-23 13:14:51 +0000715 if (url.addrs && url.addrs[0].sockaddr) {
716 u->resolved->sockaddr = url.addrs[0].sockaddr;
717 u->resolved->socklen = url.addrs[0].socklen;
718 u->resolved->naddrs = 1;
719 u->resolved->host = url.addrs[0].name;
Igor Sysoev302cedc2008-12-23 19:35:12 +0000720
721 } else {
Igor Sysoev52859f22009-03-23 13:14:51 +0000722 u->resolved->host = url.host;
723 u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
724 u->resolved->no_port = url.no_port;
Igor Sysoev302cedc2008-12-23 19:35:12 +0000725 }
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000726
727 return NGX_OK;
728}
729
730
Igor Sysoev52859f22009-03-23 13:14:51 +0000731#if (NGX_HTTP_CACHE)
732
733static ngx_int_t
734ngx_http_proxy_create_key(ngx_http_request_t *r)
735{
736 size_t len, loc_len;
737 u_char *p;
738 uintptr_t escape;
739 ngx_str_t *key;
740 ngx_http_upstream_t *u;
741 ngx_http_proxy_ctx_t *ctx;
742 ngx_http_proxy_loc_conf_t *plcf;
743
744 u = r->upstream;
745
746 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
747
748 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
749
750 key = ngx_array_push(&r->cache->keys);
751 if (key == NULL) {
752 return NGX_ERROR;
753 }
754
Igor Sysoev44a69c82009-04-06 08:58:44 +0000755 if (plcf->cache_key.value.len) {
756
757 if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
758 return NGX_ERROR;
759 }
760
761 return NGX_OK;
762 }
763
Igor Sysoev52859f22009-03-23 13:14:51 +0000764 *key = ctx->vars.key_start;
765
766 key = ngx_array_push(&r->cache->keys);
767 if (key == NULL) {
768 return NGX_ERROR;
769 }
770
771 if (plcf->proxy_lengths) {
772
773 *key = ctx->vars.uri;
774 u->uri = ctx->vars.uri;
775
776 return NGX_OK;
777
778 } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
779 {
780 *key = r->unparsed_uri;
781 u->uri = r->unparsed_uri;
782
783 return NGX_OK;
784 }
785
786 loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
787
788 if (r->quoted_uri || r->internal) {
789 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
790 r->uri.len - loc_len, NGX_ESCAPE_URI);
791 } else {
792 escape = 0;
793 }
794
795 len = ctx->vars.uri.len + r->uri.len - loc_len + escape
796 + sizeof("?") - 1 + r->args.len;
797
798 p = ngx_pnalloc(r->pool, len);
799 if (p == NULL) {
800 return NGX_ERROR;
801 }
802
803 key->data = p;
804
805 if (r->valid_location) {
806 p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
807 }
808
809 if (escape) {
810 ngx_escape_uri(p, r->uri.data + loc_len,
811 r->uri.len - loc_len, NGX_ESCAPE_URI);
812 p += r->uri.len - loc_len + escape;
813
814 } else {
815 p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
816 }
817
818 if (r->args.len > 0) {
819 *p++ = '?';
820 p = ngx_copy(p, r->args.data, r->args.len);
821 }
822
823 key->len = p - key->data;
824 u->uri = *key;
825
826 return NGX_OK;
827}
828
829#endif
830
831
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000832static ngx_int_t
Igor Sysoev02f742b2005-04-08 15:18:55 +0000833ngx_http_proxy_create_request(ngx_http_request_t *r)
834{
Igor Sysoev52859f22009-03-23 13:14:51 +0000835 size_t len, uri_len, loc_len, body_len;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000836 uintptr_t escape;
837 ngx_buf_t *b;
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000838 ngx_str_t method;
839 ngx_uint_t i, unparsed_uri;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000840 ngx_chain_t *cl, *body;
841 ngx_list_part_t *part;
842 ngx_table_elt_t *header;
843 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000844 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000845 ngx_http_script_code_pt code;
846 ngx_http_script_engine_t e, le;
847 ngx_http_proxy_loc_conf_t *plcf;
848 ngx_http_script_len_code_pt lcode;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000849
850 u = r->upstream;
851
852 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
853
Igor Sysoev78452232005-10-12 13:50:36 +0000854 if (u->method.len) {
855 /* HEAD was changed to GET to cache response */
856 method = u->method;
857 method.len++;
858
859 } else if (plcf->method.len) {
860 method = plcf->method;
861
Igor Sysoev02f742b2005-04-08 15:18:55 +0000862 } else {
Igor Sysoev78452232005-10-12 13:50:36 +0000863 method = r->method_name;
864 method.len++;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000865 }
866
Igor Sysoevfa626562007-11-28 15:06:05 +0000867 len = method.len + sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
868
Igor Sysoev02f742b2005-04-08 15:18:55 +0000869 escape = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000870 loc_len = 0;
871 unparsed_uri = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000872
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000873 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000874
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000875 if (plcf->proxy_lengths) {
Igor Sysoev52859f22009-03-23 13:14:51 +0000876 uri_len = ctx->vars.uri.len;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000877
878 } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
879 {
Igor Sysoev8290d282006-02-03 12:58:48 +0000880 unparsed_uri = 1;
Igor Sysoev52859f22009-03-23 13:14:51 +0000881 uri_len = r->unparsed_uri.len;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000882
883 } else {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000884 loc_len = (r->valid_location && ctx->vars.uri.len) ?
885 plcf->location.len : 0;
886
Igor Sysoevda7b5e12010-06-15 09:31:19 +0000887 if (r->quoted_uri || r->space_in_uri || r->internal) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000888 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
889 r->uri.len - loc_len, NGX_ESCAPE_URI);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000890 }
891
Igor Sysoev52859f22009-03-23 13:14:51 +0000892 uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
893 + sizeof("?") - 1 + r->args.len;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000894 }
895
Igor Sysoev52859f22009-03-23 13:14:51 +0000896 if (uri_len == 0) {
897 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
898 "zero length URI to proxy");
899 return NGX_ERROR;
900 }
901
902 len += uri_len;
903
Igor Sysoev2d3f3f62007-10-14 18:56:15 +0000904 ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
Igor Sysoev09c684b2005-11-09 17:25:55 +0000905
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000906 if (plcf->body_set_len) {
907 le.ip = plcf->body_set_len->elts;
908 le.request = r;
909 le.flushed = 1;
910 body_len = 0;
911
912 while (*(uintptr_t *) le.ip) {
913 lcode = *(ngx_http_script_len_code_pt *) le.ip;
914 body_len += lcode(&le);
915 }
916
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000917 ctx->internal_body_length = body_len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000918 len += body_len;
919 }
920
Igor Sysoev899b44e2005-05-12 14:58:06 +0000921 le.ip = plcf->headers_set_len->elts;
922 le.request = r;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000923 le.flushed = 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000924
925 while (*(uintptr_t *) le.ip) {
926 while (*(uintptr_t *) le.ip) {
927 lcode = *(ngx_http_script_len_code_pt *) le.ip;
928 len += lcode(&le);
929 }
930 le.ip += sizeof(uintptr_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000931 }
932
933
Igor Sysoev899b44e2005-05-12 14:58:06 +0000934 if (plcf->upstream.pass_request_headers) {
935 part = &r->headers_in.headers.part;
936 header = part->elts;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000937
Igor Sysoev899b44e2005-05-12 14:58:06 +0000938 for (i = 0; /* void */; i++) {
939
940 if (i >= part->nelts) {
941 if (part->next == NULL) {
942 break;
943 }
944
945 part = part->next;
946 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000947 i = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000948 }
949
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000950 if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
951 header[i].lowcase_key, header[i].key.len))
Igor Sysoev899b44e2005-05-12 14:58:06 +0000952 {
953 continue;
954 }
955
956 len += header[i].key.len + sizeof(": ") - 1
957 + header[i].value.len + sizeof(CRLF) - 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000958 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000959 }
960
Igor Sysoev899b44e2005-05-12 14:58:06 +0000961
Igor Sysoev02f742b2005-04-08 15:18:55 +0000962 b = ngx_create_temp_buf(r->pool, len);
963 if (b == NULL) {
964 return NGX_ERROR;
965 }
966
967 cl = ngx_alloc_chain_link(r->pool);
968 if (cl == NULL) {
969 return NGX_ERROR;
970 }
971
972 cl->buf = b;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000973
974
975 /* the request line */
976
Igor Sysoev09c684b2005-11-09 17:25:55 +0000977 b->last = ngx_copy(b->last, method.data, method.len);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000978
Igor Sysoeva2573672005-10-05 14:46:21 +0000979 u->uri.data = b->last;
980
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000981 if (plcf->proxy_lengths) {
982 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
983
984 } else if (unparsed_uri) {
Igor Sysoev09c684b2005-11-09 17:25:55 +0000985 b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
986
Igor Sysoev02f742b2005-04-08 15:18:55 +0000987 } else {
Igor Sysoeva2573672005-10-05 14:46:21 +0000988 if (r->valid_location) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000989 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
Igor Sysoeva2573672005-10-05 14:46:21 +0000990 }
Igor Sysoev82dc95e2005-10-03 12:53:14 +0000991
Igor Sysoev02f742b2005-04-08 15:18:55 +0000992 if (escape) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000993 ngx_escape_uri(b->last, r->uri.data + loc_len,
994 r->uri.len - loc_len, NGX_ESCAPE_URI);
995 b->last += r->uri.len - loc_len + escape;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000996
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000997 } else {
Igor Sysoev09c684b2005-11-09 17:25:55 +0000998 b->last = ngx_copy(b->last, r->uri.data + loc_len,
999 r->uri.len - loc_len);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001000 }
1001
1002 if (r->args.len > 0) {
1003 *b->last++ = '?';
Igor Sysoev09c684b2005-11-09 17:25:55 +00001004 b->last = ngx_copy(b->last, r->args.data, r->args.len);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001005 }
1006 }
1007
Igor Sysoeva2573672005-10-05 14:46:21 +00001008 u->uri.len = b->last - u->uri.data;
1009
Igor Sysoev02f742b2005-04-08 15:18:55 +00001010 b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
1011 sizeof(ngx_http_proxy_version) - 1);
1012
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001013 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
Igor Sysoev02f742b2005-04-08 15:18:55 +00001014
1015 e.ip = plcf->headers_set->elts;
1016 e.pos = b->last;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001017 e.request = r;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001018 e.flushed = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001019
Igor Sysoev899b44e2005-05-12 14:58:06 +00001020 le.ip = plcf->headers_set_len->elts;
1021
1022 while (*(uintptr_t *) le.ip) {
1023 lcode = *(ngx_http_script_len_code_pt *) le.ip;
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001024
1025 /* skip the header line name length */
1026 (void) lcode(&le);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001027
1028 if (*(ngx_http_script_len_code_pt *) le.ip) {
1029
1030 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1031 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1032 }
1033
1034 e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0;
1035
1036 } else {
1037 e.skip = 0;
1038 }
1039
1040 le.ip += sizeof(uintptr_t);
1041
1042 while (*(uintptr_t *) e.ip) {
1043 code = *(ngx_http_script_code_pt *) e.ip;
1044 code((ngx_http_script_engine_t *) &e);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001045 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001046 e.ip += sizeof(uintptr_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001047 }
1048
1049 b->last = e.pos;
1050
1051
Igor Sysoev899b44e2005-05-12 14:58:06 +00001052 if (plcf->upstream.pass_request_headers) {
1053 part = &r->headers_in.headers.part;
1054 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001055
Igor Sysoev899b44e2005-05-12 14:58:06 +00001056 for (i = 0; /* void */; i++) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001057
Igor Sysoev899b44e2005-05-12 14:58:06 +00001058 if (i >= part->nelts) {
1059 if (part->next == NULL) {
1060 break;
1061 }
1062
1063 part = part->next;
1064 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001065 i = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001066 }
1067
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001068 if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
1069 header[i].lowcase_key, header[i].key.len))
Igor Sysoev899b44e2005-05-12 14:58:06 +00001070 {
1071 continue;
1072 }
1073
Igor Sysoev09c684b2005-11-09 17:25:55 +00001074 b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001075
1076 *b->last++ = ':'; *b->last++ = ' ';
1077
Igor Sysoev09c684b2005-11-09 17:25:55 +00001078 b->last = ngx_copy(b->last, header[i].value.data,
1079 header[i].value.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001080
1081 *b->last++ = CR; *b->last++ = LF;
1082
1083 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1084 "http proxy header: \"%V: %V\"",
1085 &header[i].key, &header[i].value);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001086 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001087 }
1088
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001089
Igor Sysoev02f742b2005-04-08 15:18:55 +00001090 /* add "\r\n" at the header end */
1091 *b->last++ = CR; *b->last++ = LF;
1092
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001093 if (plcf->body_set) {
1094 e.ip = plcf->body_set->elts;
1095 e.pos = b->last;
1096
1097 while (*(uintptr_t *) e.ip) {
1098 code = *(ngx_http_script_code_pt *) e.ip;
1099 code((ngx_http_script_engine_t *) &e);
1100 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001101
Igor Sysoevb141f2b2005-11-15 14:49:57 +00001102 b->last = e.pos;
1103 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001104
Igor Sysoevd02661a2007-12-24 17:05:31 +00001105 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1106 "http proxy header:\n\"%*s\"",
1107 (size_t) (b->last - b->pos), b->pos);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001108
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001109 if (plcf->body_set == NULL && plcf->upstream.pass_request_body) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001110
1111 body = u->request_bufs;
1112 u->request_bufs = cl;
1113
1114 while (body) {
1115 b = ngx_alloc_buf(r->pool);
1116 if (b == NULL) {
1117 return NGX_ERROR;
1118 }
1119
1120 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
1121
1122 cl->next = ngx_alloc_chain_link(r->pool);
1123 if (cl->next == NULL) {
1124 return NGX_ERROR;
1125 }
1126
1127 cl = cl->next;
1128 cl->buf = b;
1129
1130 body = body->next;
1131 }
1132
Igor Sysoevffe71442006-02-08 15:33:12 +00001133 b->flush = 1;
1134
Igor Sysoev899b44e2005-05-12 14:58:06 +00001135 } else {
1136 u->request_bufs = cl;
1137 }
1138
1139 cl->next = NULL;
1140
Igor Sysoev02f742b2005-04-08 15:18:55 +00001141 return NGX_OK;
1142}
1143
1144
1145static ngx_int_t
1146ngx_http_proxy_reinit_request(ngx_http_request_t *r)
1147{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001148 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001149
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001150 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001151
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001152 if (ctx == NULL) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001153 return NGX_OK;
1154 }
1155
Igor Sysoev54b35b02010-06-15 15:15:06 +00001156 ctx->status.code = 0;
1157 ctx->status.count = 0;
1158 ctx->status.start = NULL;
1159 ctx->status.end = NULL;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001160
1161 r->upstream->process_header = ngx_http_proxy_process_status_line;
Igor Sysoevaed1ac12010-03-25 13:27:52 +00001162 r->state = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001163
1164 return NGX_OK;
1165}
1166
1167
1168static ngx_int_t
1169ngx_http_proxy_process_status_line(ngx_http_request_t *r)
1170{
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001171 size_t len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001172 ngx_int_t rc;
1173 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001174 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001175
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001176 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001177
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001178 if (ctx == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001179 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001180 }
1181
Igor Sysoev54b35b02010-06-15 15:15:06 +00001182 u = r->upstream;
1183
1184 rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001185
1186 if (rc == NGX_AGAIN) {
1187 return rc;
1188 }
1189
Igor Sysoev54b35b02010-06-15 15:15:06 +00001190 if (rc == NGX_ERROR) {
Igor Sysoev52859f22009-03-23 13:14:51 +00001191
1192#if (NGX_HTTP_CACHE)
1193
1194 if (r->cache) {
1195 r->http_version = NGX_HTTP_VERSION_9;
Igor Sysoev52859f22009-03-23 13:14:51 +00001196 return NGX_OK;
1197 }
1198
1199#endif
1200
Igor Sysoev899b44e2005-05-12 14:58:06 +00001201 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001202 "upstream sent no valid HTTP/1.0 header");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001203
Igor Sysoev13c68742006-03-10 12:51:52 +00001204#if 0
Igor Sysoev899b44e2005-05-12 14:58:06 +00001205 if (u->accel) {
1206 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1207 }
Igor Sysoev13c68742006-03-10 12:51:52 +00001208#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +00001209
1210 r->http_version = NGX_HTTP_VERSION_9;
Igor Sysoevd7cf1a62007-11-06 15:01:13 +00001211 u->state->status = NGX_HTTP_OK;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001212
Igor Sysoev899b44e2005-05-12 14:58:06 +00001213 return NGX_OK;
1214 }
1215
Igor Sysoev52859f22009-03-23 13:14:51 +00001216 if (u->state) {
Igor Sysoev54b35b02010-06-15 15:15:06 +00001217 u->state->status = ctx->status.code;
Igor Sysoev52859f22009-03-23 13:14:51 +00001218 }
1219
Igor Sysoev54b35b02010-06-15 15:15:06 +00001220 u->headers_in.status_n = ctx->status.code;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001221
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001222 len = ctx->status.end - ctx->status.start;
1223 u->headers_in.status_line.len = len;
1224
1225 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
Igor Sysoev187b7d92005-07-14 12:51:53 +00001226 if (u->headers_in.status_line.data == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001227 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001228 }
Igor Sysoev09c684b2005-11-09 17:25:55 +00001229
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001230 ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001231
1232 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1233 "http proxy status %ui \"%V\"",
Igor Sysoev4e08b9c2006-12-20 19:38:06 +00001234 u->headers_in.status_n, &u->headers_in.status_line);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001235
1236 u->process_header = ngx_http_proxy_process_header;
1237
1238 return ngx_http_proxy_process_header(r);
1239}
1240
1241
1242static ngx_int_t
Igor Sysoev02f742b2005-04-08 15:18:55 +00001243ngx_http_proxy_process_header(ngx_http_request_t *r)
1244{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001245 ngx_int_t rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001246 ngx_table_elt_t *h;
1247 ngx_http_upstream_header_t *hh;
1248 ngx_http_upstream_main_conf_t *umcf;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001249
Igor Sysoev899b44e2005-05-12 14:58:06 +00001250 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001251
Igor Sysoev3b304762008-05-22 12:09:41 +00001252 for ( ;; ) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001253
Igor Sysoev753792e2008-09-24 14:02:50 +00001254 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001255
1256 if (rc == NGX_OK) {
1257
1258 /* a header line has been parsed successfully */
1259
1260 h = ngx_list_push(&r->upstream->headers_in.headers);
1261 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001262 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001263 }
1264
1265 h->hash = r->header_hash;
1266
1267 h->key.len = r->header_name_end - r->header_name_start;
1268 h->value.len = r->header_end - r->header_start;
1269
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001270 h->key.data = ngx_pnalloc(r->pool,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001271 h->key.len + 1 + h->value.len + 1 + h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001272 if (h->key.data == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001273 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001274 }
1275
1276 h->value.data = h->key.data + h->key.len + 1;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001277 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001278
1279 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
1280 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
1281
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001282 if (h->key.len == r->lowcase_index) {
1283 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001284
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001285 } else {
Igor Sysoev777b0192008-08-04 10:07:00 +00001286 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001287 }
1288
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001289 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
1290 h->lowcase_key, h->key.len);
1291
1292 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001293 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001294 }
1295
Igor Sysoev899b44e2005-05-12 14:58:06 +00001296 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1297 "http proxy header: \"%V: %V\"",
1298 &h->key, &h->value);
1299
1300 continue;
1301 }
1302
1303 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1304
1305 /* a whole header has been parsed successfully */
1306
1307 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1308 "http proxy header done");
1309
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001310 /*
1311 * if no "Server" and "Date" in header line,
1312 * then add the special empty headers
1313 */
1314
1315 if (r->upstream->headers_in.server == NULL) {
1316 h = ngx_list_push(&r->upstream->headers_in.headers);
1317 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001318 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001319 }
1320
1321 h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
1322 ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
1323
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001324 ngx_str_set(&h->key, "Server");
1325 ngx_str_null(&h->value);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001326 h->lowcase_key = (u_char *) "server";
1327 }
1328
1329 if (r->upstream->headers_in.date == NULL) {
1330 h = ngx_list_push(&r->upstream->headers_in.headers);
1331 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001332 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001333 }
1334
1335 h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
1336
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001337 ngx_str_set(&h->key, "Date");
1338 ngx_str_null(&h->value);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001339 h->lowcase_key = (u_char *) "date";
1340 }
1341
Igor Sysoev899b44e2005-05-12 14:58:06 +00001342 return NGX_OK;
1343 }
1344
Igor Sysoev7b190b42005-06-07 15:56:31 +00001345 if (rc == NGX_AGAIN) {
1346 return NGX_AGAIN;
1347 }
1348
Igor Sysoev899b44e2005-05-12 14:58:06 +00001349 /* there was error while a header line parsing */
1350
1351 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev13c68742006-03-10 12:51:52 +00001352 "upstream sent invalid header");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001353
1354 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1355 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001356}
1357
1358
1359static void
1360ngx_http_proxy_abort_request(ngx_http_request_t *r)
1361{
1362 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1363 "abort http proxy request");
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001364
Igor Sysoev02f742b2005-04-08 15:18:55 +00001365 return;
1366}
1367
1368
1369static void
1370ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001371{
Igor Sysoev02f742b2005-04-08 15:18:55 +00001372 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1373 "finalize http proxy request");
1374
1375 return;
1376}
1377
1378
Igor Sysoev09c684b2005-11-09 17:25:55 +00001379static ngx_int_t
1380ngx_http_proxy_host_variable(ngx_http_request_t *r,
1381 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev02f742b2005-04-08 15:18:55 +00001382{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001383 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001384
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001385 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001386
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001387 if (ctx == NULL) {
1388 v->not_found = 1;
1389 return NGX_OK;
1390 }
1391
1392 v->len = ctx->vars.host_header.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001393 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00001394 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001395 v->not_found = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001396 v->data = ctx->vars.host_header.data;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001397
Igor Sysoev09c684b2005-11-09 17:25:55 +00001398 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001399}
1400
1401
Igor Sysoev09c684b2005-11-09 17:25:55 +00001402static ngx_int_t
1403ngx_http_proxy_port_variable(ngx_http_request_t *r,
1404 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev899b44e2005-05-12 14:58:06 +00001405{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001406 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001407
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001408 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001409
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001410 if (ctx == NULL) {
1411 v->not_found = 1;
1412 return NGX_OK;
1413 }
1414
1415 v->len = ctx->vars.port.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001416 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00001417 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001418 v->not_found = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001419 v->data = ctx->vars.port.data;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001420
Igor Sysoev09c684b2005-11-09 17:25:55 +00001421 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001422}
1423
1424
Igor Sysoev09c684b2005-11-09 17:25:55 +00001425static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001426ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
Igor Sysoev09c684b2005-11-09 17:25:55 +00001427 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev899b44e2005-05-12 14:58:06 +00001428{
Igor Sysoev09c684b2005-11-09 17:25:55 +00001429 u_char *p;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001430
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001431 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00001432 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001433 v->not_found = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001434
1435 if (r->headers_in.x_forwarded_for == NULL) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00001436 v->len = r->connection->addr_text.len;
1437 v->data = r->connection->addr_text.data;
1438 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001439 }
1440
Igor Sysoev09c684b2005-11-09 17:25:55 +00001441 v->len = r->headers_in.x_forwarded_for->value.len
1442 + sizeof(", ") - 1 + r->connection->addr_text.len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001443
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001444 p = ngx_pnalloc(r->pool, v->len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001445 if (p == NULL) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00001446 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001447 }
1448
Igor Sysoev09c684b2005-11-09 17:25:55 +00001449 v->data = p;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001450
Igor Sysoev09c684b2005-11-09 17:25:55 +00001451 p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
1452 r->headers_in.x_forwarded_for->value.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001453
1454 *p++ = ','; *p++ = ' ';
1455
1456 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
1457
Igor Sysoev09c684b2005-11-09 17:25:55 +00001458 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001459}
1460
1461
1462static ngx_int_t
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001463ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
1464 ngx_http_variable_value_t *v, uintptr_t data)
1465{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001466 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001467
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001468 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001469
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001470 if (ctx == NULL) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001471 v->not_found = 1;
1472 return NGX_OK;
1473 }
1474
1475 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00001476 v->no_cacheable = 0;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001477 v->not_found = 0;
1478
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001479 v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001480
1481 if (v->data == NULL) {
1482 return NGX_ERROR;
1483 }
1484
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001485 v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001486
1487 return NGX_OK;
1488}
1489
1490
1491static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001492ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
1493 size_t prefix)
1494{
1495 ngx_int_t rc;
1496 ngx_uint_t i;
1497 ngx_http_proxy_loc_conf_t *plcf;
1498 ngx_http_proxy_redirect_t *pr;
1499
1500 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1501
1502 pr = plcf->redirects->elts;
1503
1504 if (pr == NULL) {
1505 return NGX_DECLINED;
1506 }
1507
1508 for (i = 0; i < plcf->redirects->nelts; i++) {
Igor Sysoev9e580192006-02-01 18:22:15 +00001509 rc = pr[i].handler(r, h, prefix, &pr[i]);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001510
1511 if (rc != NGX_DECLINED) {
1512 return rc;
1513 }
1514 }
1515
1516 return NGX_DECLINED;
1517}
1518
1519
1520static ngx_int_t
1521ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
1522 size_t prefix, ngx_http_proxy_redirect_t *pr)
1523{
1524 size_t len;
1525 u_char *data, *p;
1526
1527 if (pr->redirect.len > h->value.len - prefix
1528 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
1529 pr->redirect.len) != 0)
1530 {
1531 return NGX_DECLINED;
1532 }
1533
Igor Sysoev82e19332010-06-07 14:33:50 +00001534 len = pr->replacement.text.len + h->value.len - pr->redirect.len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001535
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001536 data = ngx_pnalloc(r->pool, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001537 if (data == NULL) {
1538 return NGX_ERROR;
1539 }
1540
Igor Sysoev27b54fd2010-06-07 14:37:56 +00001541 p = ngx_copy(data, h->value.data, prefix);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001542
Igor Sysoevafd7ec52006-05-29 17:28:12 +00001543 if (pr->replacement.text.len) {
1544 p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
1545 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001546
1547 ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
1548 h->value.len - pr->redirect.len - prefix);
1549
1550 h->value.len = len;
1551 h->value.data = data;
1552
1553 return NGX_OK;
1554}
1555
1556
1557static ngx_int_t
1558ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h,
1559 size_t prefix, ngx_http_proxy_redirect_t *pr)
1560{
1561 size_t len;
1562 u_char *data, *p;
1563 ngx_http_script_code_pt code;
1564 ngx_http_script_engine_t e;
1565 ngx_http_script_len_code_pt lcode;
1566
1567 if (pr->redirect.len > h->value.len - prefix
1568 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
1569 pr->redirect.len) != 0)
1570 {
1571 return NGX_DECLINED;
1572 }
1573
1574 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1575
1576 e.ip = pr->replacement.vars.lengths;
1577 e.request = r;
1578
Igor Sysoev82e19332010-06-07 14:33:50 +00001579 len = h->value.len - pr->redirect.len;
Igor Sysoevc9098082006-09-26 21:15:52 +00001580
1581 while (*(uintptr_t *) e.ip) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001582 lcode = *(ngx_http_script_len_code_pt *) e.ip;
Igor Sysoevc9098082006-09-26 21:15:52 +00001583 len += lcode(&e);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001584 }
1585
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001586 data = ngx_pnalloc(r->pool, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001587 if (data == NULL) {
1588 return NGX_ERROR;
1589 }
1590
Igor Sysoev27b54fd2010-06-07 14:37:56 +00001591 p = ngx_copy(data, h->value.data, prefix);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001592
1593 e.ip = pr->replacement.vars.values;
1594 e.pos = p;
1595
1596 while (*(uintptr_t *) e.ip) {
1597 code = *(ngx_http_script_code_pt *) e.ip;
1598 code(&e);
1599 }
1600
Igor Sysoevc9098082006-09-26 21:15:52 +00001601 ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
1602 h->value.len - pr->redirect.len - prefix);
1603
Igor Sysoev899b44e2005-05-12 14:58:06 +00001604 h->value.len = len;
1605 h->value.data = data;
1606
1607 return NGX_OK;
1608}
1609
1610
1611static ngx_int_t
1612ngx_http_proxy_add_variables(ngx_conf_t *cf)
1613{
1614 ngx_http_variable_t *var, *v;
1615
1616 for (v = ngx_http_proxy_vars; v->name.len; v++) {
1617 var = ngx_http_add_variable(cf, &v->name, v->flags);
1618 if (var == NULL) {
1619 return NGX_ERROR;
1620 }
1621
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001622 var->get_handler = v->get_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001623 var->data = v->data;
1624 }
1625
1626 return NGX_OK;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001627}
1628
1629
1630static void *
1631ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
1632{
1633 ngx_http_proxy_loc_conf_t *conf;
1634
1635 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
1636 if (conf == NULL) {
Igor Sysoev260c4322009-06-02 16:09:44 +00001637 return NULL;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001638 }
1639
1640 /*
1641 * set by ngx_pcalloc():
1642 *
1643 * conf->upstream.bufs.num = 0;
Igor Sysoevb01c9cc2009-04-30 16:15:07 +00001644 * conf->upstream.ignore_headers = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001645 * conf->upstream.next_upstream = 0;
Igor Sysoev5ed36912009-05-19 13:27:27 +00001646 * conf->upstream.cache_use_stale = 0;
1647 * conf->upstream.cache_methods = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001648 * conf->upstream.temp_path = NULL;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001649 * conf->upstream.hide_headers_hash = { NULL, 0 };
Igor Sysoev899b44e2005-05-12 14:58:06 +00001650 * conf->upstream.uri = { 0, NULL };
1651 * conf->upstream.location = NULL;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00001652 * conf->upstream.store_lengths = NULL;
1653 * conf->upstream.store_values = NULL;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001654 *
Igor Sysoev78452232005-10-12 13:50:36 +00001655 * conf->method = NULL;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001656 * conf->headers_source = NULL;
1657 * conf->headers_set_len = NULL;
1658 * conf->headers_set = NULL;
1659 * conf->headers_set_hash = NULL;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001660 * conf->body_set_len = NULL;
1661 * conf->body_set = NULL;
1662 * conf->body_source = { 0, NULL };
Igor Sysoev931d88c2010-03-10 14:37:18 +00001663 * conf->redirects = NULL;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001664 */
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001665
Igor Sysoevfbd9b432007-07-13 08:30:34 +00001666 conf->upstream.store = NGX_CONF_UNSET;
1667 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001668 conf->upstream.buffering = NGX_CONF_UNSET;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001669 conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001670
Igor Sysoev02f742b2005-04-08 15:18:55 +00001671 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
1672 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
1673 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
1674
1675 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001676 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001677
1678 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001679 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001680 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001681
Igor Sysoev899b44e2005-05-12 14:58:06 +00001682 conf->upstream.pass_request_headers = NGX_CONF_UNSET;
1683 conf->upstream.pass_request_body = NGX_CONF_UNSET;
Igor Sysoev78452232005-10-12 13:50:36 +00001684
Igor Sysoev52859f22009-03-23 13:14:51 +00001685#if (NGX_HTTP_CACHE)
1686 conf->upstream.cache = NGX_CONF_UNSET_PTR;
1687 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
Igor Sysoevf7d659a2010-07-19 09:36:04 +00001688 conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
Igor Sysoev9b2763a2010-05-24 11:01:05 +00001689 conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
Igor Sysoev52859f22009-03-23 13:14:51 +00001690 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1691#endif
1692
Igor Sysoevcb540612007-12-09 18:03:20 +00001693 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
1694 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
1695
Igor Sysoevef809b82006-06-28 16:00:26 +00001696 conf->upstream.intercept_errors = NGX_CONF_UNSET;
Igor Sysoev916ee8e2008-08-17 17:47:52 +00001697#if (NGX_HTTP_SSL)
1698 conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
1699#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +00001700
1701 /* "proxy_cyclic_temp_file" is disabled */
1702 conf->upstream.cyclic_temp_file = 0;
1703
Igor Sysoev899b44e2005-05-12 14:58:06 +00001704 conf->redirect = NGX_CONF_UNSET;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001705 conf->upstream.change_buffering = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001706
Igor Sysoev8a19bff2007-04-22 20:21:59 +00001707 conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
1708 conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
1709
Igor Sysoev02f742b2005-04-08 15:18:55 +00001710 return conf;
1711}
1712
1713
1714static char *
1715ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1716{
1717 ngx_http_proxy_loc_conf_t *prev = parent;
1718 ngx_http_proxy_loc_conf_t *conf = child;
1719
Igor Sysoev52859f22009-03-23 13:14:51 +00001720 size_t size;
1721 ngx_keyval_t *s;
1722 ngx_hash_init_t hash;
Igor Sysoev90f95522010-08-03 09:24:25 +00001723 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev52859f22009-03-23 13:14:51 +00001724 ngx_http_proxy_redirect_t *pr;
1725 ngx_http_script_compile_t sc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001726
Igor Sysoevfbd9b432007-07-13 08:30:34 +00001727 if (conf->upstream.store != 0) {
1728 ngx_conf_merge_value(conf->upstream.store,
Igor Sysoevda28ef82009-05-28 13:31:43 +00001729 prev->upstream.store, 0);
Igor Sysoevfbd9b432007-07-13 08:30:34 +00001730
1731 if (conf->upstream.store_lengths == NULL) {
1732 conf->upstream.store_lengths = prev->upstream.store_lengths;
1733 conf->upstream.store_values = prev->upstream.store_values;
1734 }
1735 }
1736
1737 ngx_conf_merge_uint_value(conf->upstream.store_access,
1738 prev->upstream.store_access, 0600);
Igor Sysoev58feb532007-07-12 11:19:05 +00001739
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001740 ngx_conf_merge_value(conf->upstream.buffering,
1741 prev->upstream.buffering, 1);
1742
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001743 ngx_conf_merge_value(conf->upstream.ignore_client_abort,
1744 prev->upstream.ignore_client_abort, 0);
1745
Igor Sysoev02f742b2005-04-08 15:18:55 +00001746 ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
1747 prev->upstream.connect_timeout, 60000);
1748
1749 ngx_conf_merge_msec_value(conf->upstream.send_timeout,
1750 prev->upstream.send_timeout, 60000);
1751
1752 ngx_conf_merge_msec_value(conf->upstream.read_timeout,
1753 prev->upstream.read_timeout, 60000);
1754
1755 ngx_conf_merge_size_value(conf->upstream.send_lowat,
1756 prev->upstream.send_lowat, 0);
1757
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001758 ngx_conf_merge_size_value(conf->upstream.buffer_size,
1759 prev->upstream.buffer_size,
Igor Sysoev02f742b2005-04-08 15:18:55 +00001760 (size_t) ngx_pagesize);
1761
1762 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
1763 8, ngx_pagesize);
1764
1765 if (conf->upstream.bufs.num < 2) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001766 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev02f742b2005-04-08 15:18:55 +00001767 "there must be at least 2 \"proxy_buffers\"");
1768 return NGX_CONF_ERROR;
1769 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001770
Igor Sysoev02f742b2005-04-08 15:18:55 +00001771
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001772 size = conf->upstream.buffer_size;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001773 if (size < conf->upstream.bufs.size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001774 size = conf->upstream.bufs.size;
1775 }
1776
1777
Igor Sysoev187b7d92005-07-14 12:51:53 +00001778 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
1779 prev->upstream.busy_buffers_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00001780 NGX_CONF_UNSET_SIZE);
1781
Igor Sysoev187b7d92005-07-14 12:51:53 +00001782 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001783 conf->upstream.busy_buffers_size = 2 * size;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001784 } else {
1785 conf->upstream.busy_buffers_size =
1786 conf->upstream.busy_buffers_size_conf;
1787 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001788
Igor Sysoev187b7d92005-07-14 12:51:53 +00001789 if (conf->upstream.busy_buffers_size < size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001790 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1791 "\"proxy_busy_buffers_size\" must be equal or bigger than "
Igor Sysoevf259a3f2007-02-21 11:50:39 +00001792 "maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev02f742b2005-04-08 15:18:55 +00001793 "one of the \"proxy_buffers\"");
1794
1795 return NGX_CONF_ERROR;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001796 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001797
Igor Sysoev187b7d92005-07-14 12:51:53 +00001798 if (conf->upstream.busy_buffers_size
1799 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
Igor Sysoev02f742b2005-04-08 15:18:55 +00001800 {
1801 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1802 "\"proxy_busy_buffers_size\" must be less than "
1803 "the size of all \"proxy_buffers\" minus one buffer");
1804
1805 return NGX_CONF_ERROR;
1806 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001807
Igor Sysoev187b7d92005-07-14 12:51:53 +00001808
1809 ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
1810 prev->upstream.temp_file_write_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00001811 NGX_CONF_UNSET_SIZE);
1812
Igor Sysoev187b7d92005-07-14 12:51:53 +00001813 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001814 conf->upstream.temp_file_write_size = 2 * size;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001815 } else {
1816 conf->upstream.temp_file_write_size =
1817 conf->upstream.temp_file_write_size_conf;
1818 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001819
Igor Sysoev187b7d92005-07-14 12:51:53 +00001820 if (conf->upstream.temp_file_write_size < size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001821 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1822 "\"proxy_temp_file_write_size\" must be equal or bigger than "
Igor Sysoevf259a3f2007-02-21 11:50:39 +00001823 "maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev02f742b2005-04-08 15:18:55 +00001824 "one of the \"proxy_buffers\"");
1825
1826 return NGX_CONF_ERROR;
1827 }
1828
Igor Sysoev187b7d92005-07-14 12:51:53 +00001829 ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
1830 prev->upstream.max_temp_file_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00001831 NGX_CONF_UNSET_SIZE);
1832
Igor Sysoev187b7d92005-07-14 12:51:53 +00001833 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001834 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
Igor Sysoev187b7d92005-07-14 12:51:53 +00001835 } else {
1836 conf->upstream.max_temp_file_size =
1837 conf->upstream.max_temp_file_size_conf;
1838 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001839
Igor Sysoev187b7d92005-07-14 12:51:53 +00001840 if (conf->upstream.max_temp_file_size != 0
1841 && conf->upstream.max_temp_file_size < size)
Igor Sysoev02f742b2005-04-08 15:18:55 +00001842 {
1843 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev78452232005-10-12 13:50:36 +00001844 "\"proxy_max_temp_file_size\" must be equal to zero to disable "
Igor Sysoev02f742b2005-04-08 15:18:55 +00001845 "the temporary files usage or must be equal or bigger than "
Igor Sysoevf259a3f2007-02-21 11:50:39 +00001846 "maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev78452232005-10-12 13:50:36 +00001847 "one of the \"proxy_buffers\"");
Igor Sysoev02f742b2005-04-08 15:18:55 +00001848
1849 return NGX_CONF_ERROR;
1850 }
1851
Igor Sysoev187b7d92005-07-14 12:51:53 +00001852
Igor Sysoevb01c9cc2009-04-30 16:15:07 +00001853 ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
1854 prev->upstream.ignore_headers,
1855 NGX_CONF_BITMASK_SET);
1856
1857
Igor Sysoev02f742b2005-04-08 15:18:55 +00001858 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
1859 prev->upstream.next_upstream,
1860 (NGX_CONF_BITMASK_SET
1861 |NGX_HTTP_UPSTREAM_FT_ERROR
1862 |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
1863
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001864 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
1865 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
1866 |NGX_HTTP_UPSTREAM_FT_OFF;
1867 }
1868
Igor Sysoev52859f22009-03-23 13:14:51 +00001869 if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001870 prev->upstream.temp_path,
Igor Sysoev52859f22009-03-23 13:14:51 +00001871 &ngx_http_proxy_temp_path)
1872 != NGX_OK)
1873 {
1874 return NGX_CONF_ERROR;
1875 }
1876
1877
1878#if (NGX_HTTP_CACHE)
1879
1880 ngx_conf_merge_ptr_value(conf->upstream.cache,
1881 prev->upstream.cache, NULL);
1882
1883 if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
1884 ngx_shm_zone_t *shm_zone;
1885
1886 shm_zone = conf->upstream.cache;
1887
1888 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1889 "\"proxy_cache\" zone \"%V\" is unknown",
Igor Sysoevc7f876b2009-04-16 19:25:09 +00001890 &shm_zone->shm.name);
Igor Sysoev52859f22009-03-23 13:14:51 +00001891
1892 return NGX_CONF_ERROR;
1893 }
1894
1895 ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
1896 prev->upstream.cache_min_uses, 1);
1897
1898 ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
1899 prev->upstream.cache_use_stale,
1900 (NGX_CONF_BITMASK_SET
1901 |NGX_HTTP_UPSTREAM_FT_OFF));
1902
Igor Sysoev5ed36912009-05-19 13:27:27 +00001903 if (conf->upstream.cache_methods == 0) {
1904 conf->upstream.cache_methods = prev->upstream.cache_methods;
1905 }
1906
1907 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
1908
Igor Sysoev52859f22009-03-23 13:14:51 +00001909 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
1910 conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
1911 |NGX_HTTP_UPSTREAM_FT_OFF;
1912 }
1913
Igor Sysoevf7d659a2010-07-19 09:36:04 +00001914 ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
1915 prev->upstream.cache_bypass, NULL);
1916
Igor Sysoev9b2763a2010-05-24 11:01:05 +00001917 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
1918 prev->upstream.no_cache, NULL);
1919
Igor Sysoev47f5f942010-07-19 09:55:43 +00001920 if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
1921 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1922 "\"proxy_no_cache\" functionality has been changed in 0.8.46, "
1923 "now it should be used together with \"proxy_cache_bypass\"");
1924 }
1925
Igor Sysoev52859f22009-03-23 13:14:51 +00001926 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
1927 prev->upstream.cache_valid, NULL);
1928
Igor Sysoev44a69c82009-04-06 08:58:44 +00001929 if (conf->cache_key.value.data == NULL) {
1930 conf->cache_key = prev->cache_key;
1931 }
1932
Igor Sysoev52859f22009-03-23 13:14:51 +00001933#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +00001934
Igor Sysoev78452232005-10-12 13:50:36 +00001935 if (conf->method.len == 0) {
1936 conf->method = prev->method;
1937
1938 } else {
1939 conf->method.data[conf->method.len] = ' ';
1940 conf->method.len++;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001941 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001942
Igor Sysoev899b44e2005-05-12 14:58:06 +00001943 ngx_conf_merge_value(conf->upstream.pass_request_headers,
1944 prev->upstream.pass_request_headers, 1);
1945 ngx_conf_merge_value(conf->upstream.pass_request_body,
1946 prev->upstream.pass_request_body, 1);
1947
Igor Sysoevef809b82006-06-28 16:00:26 +00001948 ngx_conf_merge_value(conf->upstream.intercept_errors,
1949 prev->upstream.intercept_errors, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001950
Igor Sysoev916ee8e2008-08-17 17:47:52 +00001951#if (NGX_HTTP_SSL)
1952 ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
1953 prev->upstream.ssl_session_reuse, 1);
1954#endif
1955
Igor Sysoev899b44e2005-05-12 14:58:06 +00001956 ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
1957
1958 if (conf->redirect) {
1959
1960 if (conf->redirects == NULL) {
1961 conf->redirects = prev->redirects;
1962 }
1963
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001964 if (conf->redirects == NULL && conf->url.data) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001965
1966 conf->redirects = ngx_array_create(cf->pool, 1,
1967 sizeof(ngx_http_proxy_redirect_t));
1968 if (conf->redirects == NULL) {
1969 return NGX_CONF_ERROR;
1970 }
1971
1972 pr = ngx_array_push(conf->redirects);
1973 if (pr == NULL) {
1974 return NGX_CONF_ERROR;
1975 }
1976
1977 pr->handler = ngx_http_proxy_rewrite_redirect_text;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001978 pr->redirect = conf->url;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00001979
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001980 if (conf->vars.uri.len) {
1981 pr->replacement.text = conf->location;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00001982
1983 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001984 ngx_str_null(&pr->replacement.text);
Igor Sysoevafd7ec52006-05-29 17:28:12 +00001985 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001986 }
1987 }
1988
Igor Sysoev22380562009-04-24 19:56:09 +00001989#if (NGX_HTTP_SSL)
1990 if (conf->upstream.ssl == NULL) {
1991 conf->upstream.ssl = prev->upstream.ssl;
1992 }
1993#endif
1994
Igor Sysoev8a19bff2007-04-22 20:21:59 +00001995 ngx_conf_merge_uint_value(conf->headers_hash_max_size,
1996 prev->headers_hash_max_size, 512);
1997
1998 ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
1999 prev->headers_hash_bucket_size, 64);
2000
2001 conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
2002 ngx_cacheline_size);
2003
Igor Sysoevcb540612007-12-09 18:03:20 +00002004 hash.max_size = conf->headers_hash_max_size;
2005 hash.bucket_size = conf->headers_hash_bucket_size;
2006 hash.name = "proxy_headers_hash";
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002007
Igor Sysoevcb540612007-12-09 18:03:20 +00002008 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
Igor Sysoev0cb0c672010-07-02 10:05:40 +00002009 &prev->upstream, ngx_http_proxy_hide_headers, &hash)
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002010 != NGX_OK)
2011 {
2012 return NGX_CONF_ERROR;
2013 }
2014
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002015 if (conf->upstream.upstream == NULL) {
2016 conf->upstream.upstream = prev->upstream.upstream;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002017 conf->vars = prev->vars;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002018 }
2019
Igor Sysoev81cd5e42010-08-03 12:59:14 +00002020 if (conf->proxy_lengths == NULL) {
2021 conf->proxy_lengths = prev->proxy_lengths;
2022 conf->proxy_values = prev->proxy_values;
2023 }
2024
Igor Sysoev90f95522010-08-03 09:24:25 +00002025 if (conf->upstream.upstream || conf->proxy_lengths) {
2026 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2027 if (clcf->handler == NULL && clcf->lmt_excpt) {
2028 clcf->handler = ngx_http_proxy_handler;
2029 conf->location = prev->location;
2030 }
2031 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002032
2033 if (conf->body_source.data == NULL) {
2034 conf->body_source = prev->body_source;
2035 conf->body_set_len = prev->body_set_len;
2036 conf->body_set = prev->body_set;
2037 }
2038
Igor Sysoevb141f2b2005-11-15 14:49:57 +00002039 if (conf->body_source.data && conf->body_set_len == NULL) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002040
2041 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2042
2043 sc.cf = cf;
2044 sc.source = &conf->body_source;
2045 sc.flushes = &conf->flushes;
2046 sc.lengths = &conf->body_set_len;
2047 sc.values = &conf->body_set;
2048 sc.complete_lengths = 1;
2049 sc.complete_values = 1;
2050
2051 if (ngx_http_script_compile(&sc) != NGX_OK) {
2052 return NGX_CONF_ERROR;
2053 }
2054
2055 if (conf->headers_source == NULL) {
2056 conf->headers_source = ngx_array_create(cf->pool, 4,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002057 sizeof(ngx_keyval_t));
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002058 if (conf->headers_source == NULL) {
2059 return NGX_CONF_ERROR;
2060 }
2061 }
2062
2063 s = ngx_array_push(conf->headers_source);
2064 if (s == NULL) {
2065 return NGX_CONF_ERROR;
2066 }
2067
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00002068 ngx_str_set(&s->key, "Content-Length");
2069 ngx_str_set(&s->value, "$proxy_internal_body_length");
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002070 }
2071
Igor Sysoev52859f22009-03-23 13:14:51 +00002072 if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) {
2073 return NGX_CONF_ERROR;
2074 }
2075
2076 return NGX_CONF_OK;
2077}
2078
2079
2080static ngx_int_t
2081ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
2082 ngx_http_proxy_loc_conf_t *prev)
2083{
2084 u_char *p;
2085 size_t size;
2086 uintptr_t *code;
2087 ngx_uint_t i;
Igor Sysoev17483d52010-06-03 14:50:59 +00002088 ngx_array_t headers_names;
Igor Sysoev52859f22009-03-23 13:14:51 +00002089 ngx_keyval_t *src, *s, *h;
2090 ngx_hash_key_t *hk;
2091 ngx_hash_init_t hash;
2092 ngx_http_script_compile_t sc;
2093 ngx_http_script_copy_code_t *copy;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002094
Igor Sysoev899b44e2005-05-12 14:58:06 +00002095 if (conf->headers_source == NULL) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00002096 conf->flushes = prev->flushes;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002097 conf->headers_set_len = prev->headers_set_len;
2098 conf->headers_set = prev->headers_set;
2099 conf->headers_set_hash = prev->headers_set_hash;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002100 conf->headers_source = prev->headers_source;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002101 }
2102
Igor Sysoev83c93ba2009-06-08 12:33:11 +00002103 if (conf->headers_set_hash.buckets
Igor Sysoev07751822009-06-15 14:25:08 +00002104#if (NGX_HTTP_CACHE)
2105 && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
2106#endif
2107 )
Igor Sysoev83c93ba2009-06-08 12:33:11 +00002108 {
Igor Sysoev52859f22009-03-23 13:14:51 +00002109 return NGX_OK;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002110 }
2111
Igor Sysoev899b44e2005-05-12 14:58:06 +00002112
Igor Sysoev17483d52010-06-03 14:50:59 +00002113 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
2114 != NGX_OK)
2115 {
Igor Sysoev52859f22009-03-23 13:14:51 +00002116 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002117 }
2118
2119 if (conf->headers_source == NULL) {
2120 conf->headers_source = ngx_array_create(cf->pool, 4,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002121 sizeof(ngx_keyval_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00002122 if (conf->headers_source == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002123 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002124 }
2125 }
2126
2127 conf->headers_set_len = ngx_array_create(cf->pool, 64, 1);
2128 if (conf->headers_set_len == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002129 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002130 }
2131
2132 conf->headers_set = ngx_array_create(cf->pool, 512, 1);
2133 if (conf->headers_set == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002134 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002135 }
2136
2137
2138 src = conf->headers_source->elts;
2139
Igor Sysoev081662a2009-04-15 11:21:12 +00002140#if (NGX_HTTP_CACHE)
2141
2142 h = conf->upstream.cache ? ngx_http_proxy_cache_headers:
2143 ngx_http_proxy_headers;
2144#else
2145
2146 h = ngx_http_proxy_headers;
2147
2148#endif
2149
2150 while (h->key.len) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002151
2152 for (i = 0; i < conf->headers_source->nelts; i++) {
2153 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
2154 goto next;
2155 }
2156 }
2157
2158 s = ngx_array_push(conf->headers_source);
2159 if (s == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002160 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002161 }
2162
2163 *s = *h;
2164
Igor Sysoev4959ec42005-05-23 12:07:45 +00002165 src = conf->headers_source->elts;
2166
Igor Sysoev899b44e2005-05-12 14:58:06 +00002167 next:
2168
Igor Sysoev081662a2009-04-15 11:21:12 +00002169 h++;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002170 }
2171
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002172
2173 src = conf->headers_source->elts;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002174 for (i = 0; i < conf->headers_source->nelts; i++) {
2175
Igor Sysoev17483d52010-06-03 14:50:59 +00002176 hk = ngx_array_push(&headers_names);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002177 if (hk == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002178 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002179 }
2180
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002181 hk->key = src[i].key;
2182 hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
2183 hk->value = (void *) 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002184
Igor Sysoev403d2442005-05-26 18:12:40 +00002185 if (src[i].value.len == 0) {
2186 continue;
2187 }
2188
Igor Sysoev899b44e2005-05-12 14:58:06 +00002189 if (ngx_http_script_variables_count(&src[i].value) == 0) {
2190 copy = ngx_array_push_n(conf->headers_set_len,
2191 sizeof(ngx_http_script_copy_code_t));
2192 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002193 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002194 }
2195
2196 copy->code = (ngx_http_script_code_pt)
2197 ngx_http_script_copy_len_code;
2198 copy->len = src[i].key.len + sizeof(": ") - 1
2199 + src[i].value.len + sizeof(CRLF) - 1;
2200
2201
2202 size = (sizeof(ngx_http_script_copy_code_t)
2203 + src[i].key.len + sizeof(": ") - 1
2204 + src[i].value.len + sizeof(CRLF) - 1
2205 + sizeof(uintptr_t) - 1)
2206 & ~(sizeof(uintptr_t) - 1);
2207
2208 copy = ngx_array_push_n(conf->headers_set, size);
2209 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002210 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002211 }
2212
2213 copy->code = ngx_http_script_copy_code;
2214 copy->len = src[i].key.len + sizeof(": ") - 1
2215 + src[i].value.len + sizeof(CRLF) - 1;
2216
2217 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2218
2219 p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
2220 *p++ = ':'; *p++ = ' ';
2221 p = ngx_cpymem(p, src[i].value.data, src[i].value.len);
2222 *p++ = CR; *p = LF;
2223
2224 } else {
2225 copy = ngx_array_push_n(conf->headers_set_len,
2226 sizeof(ngx_http_script_copy_code_t));
2227 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002228 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002229 }
2230
2231 copy->code = (ngx_http_script_code_pt)
2232 ngx_http_script_copy_len_code;
2233 copy->len = src[i].key.len + sizeof(": ") - 1;
2234
2235
2236 size = (sizeof(ngx_http_script_copy_code_t)
2237 + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
2238 & ~(sizeof(uintptr_t) - 1);
2239
2240 copy = ngx_array_push_n(conf->headers_set, size);
2241 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002242 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002243 }
2244
2245 copy->code = ngx_http_script_copy_code;
2246 copy->len = src[i].key.len + sizeof(": ") - 1;
2247
2248 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2249 p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
2250 *p++ = ':'; *p = ' ';
2251
2252
2253 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2254
2255 sc.cf = cf;
2256 sc.source = &src[i].value;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002257 sc.flushes = &conf->flushes;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002258 sc.lengths = &conf->headers_set_len;
2259 sc.values = &conf->headers_set;
2260
2261 if (ngx_http_script_compile(&sc) != NGX_OK) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002262 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002263 }
2264
2265
2266 copy = ngx_array_push_n(conf->headers_set_len,
2267 sizeof(ngx_http_script_copy_code_t));
2268 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002269 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002270 }
2271
2272 copy->code = (ngx_http_script_code_pt)
2273 ngx_http_script_copy_len_code;
2274 copy->len = sizeof(CRLF) - 1;
2275
2276
2277 size = (sizeof(ngx_http_script_copy_code_t)
2278 + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
2279 & ~(sizeof(uintptr_t) - 1);
2280
2281 copy = ngx_array_push_n(conf->headers_set, size);
2282 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002283 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002284 }
2285
2286 copy->code = ngx_http_script_copy_code;
2287 copy->len = sizeof(CRLF) - 1;
2288
2289 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2290 *p++ = CR; *p = LF;
2291 }
2292
2293 code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
2294 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002295 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002296 }
2297
2298 *code = (uintptr_t) NULL;
2299
2300 code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t));
2301 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002302 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002303 }
2304
2305 *code = (uintptr_t) NULL;
2306 }
2307
2308 code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
2309 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002310 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002311 }
2312
2313 *code = (uintptr_t) NULL;
2314
2315
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002316 hash.hash = &conf->headers_set_hash;
2317 hash.key = ngx_hash_key_lc;
Igor Sysoev8a19bff2007-04-22 20:21:59 +00002318 hash.max_size = conf->headers_hash_max_size;
2319 hash.bucket_size = conf->headers_hash_bucket_size;
2320 hash.name = "proxy_headers_hash";
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002321 hash.pool = cf->pool;
2322 hash.temp_pool = NULL;
2323
Igor Sysoev17483d52010-06-03 14:50:59 +00002324 return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
Igor Sysoev02f742b2005-04-08 15:18:55 +00002325}
2326
2327
Igor Sysoev02f742b2005-04-08 15:18:55 +00002328static char *
2329ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2330{
Igor Sysoev899b44e2005-05-12 14:58:06 +00002331 ngx_http_proxy_loc_conf_t *plcf = conf;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002332
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002333 size_t add;
2334 u_short port;
2335 ngx_str_t *value, *url;
2336 ngx_url_t u;
2337 ngx_uint_t n;
2338 ngx_http_core_loc_conf_t *clcf;
2339 ngx_http_script_compile_t sc;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002340
Igor Sysoev73c31212008-12-10 14:44:48 +00002341 if (plcf->upstream.upstream || plcf->proxy_lengths) {
Igor Sysoeva2573672005-10-05 14:46:21 +00002342 return "is duplicate";
2343 }
2344
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002345 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2346
Igor Sysoev56392722009-07-20 11:44:38 +00002347 clcf->handler = ngx_http_proxy_handler;
2348
2349 if (clcf->name.data[clcf->name.len - 1] == '/') {
2350 clcf->auto_redirect = 1;
2351 }
2352
Igor Sysoev02f742b2005-04-08 15:18:55 +00002353 value = cf->args->elts;
2354
2355 url = &value[1];
2356
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002357 n = ngx_http_script_variables_count(url);
2358
2359 if (n) {
2360
2361 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2362
2363 sc.cf = cf;
2364 sc.source = url;
2365 sc.lengths = &plcf->proxy_lengths;
2366 sc.values = &plcf->proxy_values;
2367 sc.variables = n;
2368 sc.complete_lengths = 1;
2369 sc.complete_values = 1;
Igor Sysoevb4e5b4c2007-12-01 19:57:37 +00002370
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002371 if (ngx_http_script_compile(&sc) != NGX_OK) {
2372 return NGX_CONF_ERROR;
2373 }
2374
2375#if (NGX_HTTP_SSL)
2376 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
2377 return NGX_CONF_ERROR;
2378 }
2379#endif
2380
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002381 return NGX_CONF_OK;
2382 }
2383
Igor Sysoev722231f2007-02-14 18:51:19 +00002384 if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002385 add = 7;
Igor Sysoev43f279d2005-12-18 16:02:44 +00002386 port = 80;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002387
Igor Sysoev722231f2007-02-14 18:51:19 +00002388 } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002389
2390#if (NGX_HTTP_SSL)
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002391 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
2392 return NGX_CONF_ERROR;
2393 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002394
2395 add = 8;
Igor Sysoev43f279d2005-12-18 16:02:44 +00002396 port = 443;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002397#else
2398 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2399 "https protocol requires SSL support");
2400 return NGX_CONF_ERROR;
2401#endif
2402
2403 } else {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002404 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
2405 return NGX_CONF_ERROR;
2406 }
2407
Igor Sysoev6f134cc2006-05-23 14:54:58 +00002408 ngx_memzero(&u, sizeof(ngx_url_t));
Igor Sysoev02f742b2005-04-08 15:18:55 +00002409
Igor Sysoev6f134cc2006-05-23 14:54:58 +00002410 u.url.len = url->len - add;
2411 u.url.data = url->data + add;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00002412 u.default_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00002413 u.uri_part = 1;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00002414 u.no_resolve = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002415
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002416 plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
2417 if (plcf->upstream.upstream == NULL) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002418 return NGX_CONF_ERROR;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002419 }
2420
Igor Sysoev73c31212008-12-10 14:44:48 +00002421 plcf->vars.schema.len = add;
2422 plcf->vars.schema.data = url->data;
Igor Sysoev52859f22009-03-23 13:14:51 +00002423 plcf->vars.key_start = plcf->vars.schema;
2424
2425 ngx_http_proxy_set_vars(&u, &plcf->vars);
Igor Sysoev02f742b2005-04-08 15:18:55 +00002426
Igor Sysoev52859f22009-03-23 13:14:51 +00002427 plcf->location = clcf->name;
2428
Igor Sysoev8889b652007-07-29 18:11:39 +00002429 if (clcf->named
Igor Sysoeva2573672005-10-05 14:46:21 +00002430#if (NGX_PCRE)
Igor Sysoev8889b652007-07-29 18:11:39 +00002431 || clcf->regex
2432#endif
2433 || clcf->noname)
2434 {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002435 if (plcf->vars.uri.len) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00002436 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2437 "\"proxy_pass\" may not have URI part in "
Igor Sysoeve927b1e2006-11-14 12:43:14 +00002438 "location given by regular expression, "
Igor Sysoev8889b652007-07-29 18:11:39 +00002439 "or inside named location, "
Igor Sysoeve927b1e2006-11-14 12:43:14 +00002440 "or inside the \"if\" statement, "
2441 "or inside the \"limit_except\" block");
Igor Sysoev09c684b2005-11-09 17:25:55 +00002442 return NGX_CONF_ERROR;
2443 }
2444
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002445 plcf->location.len = 0;
Igor Sysoeva2573672005-10-05 14:46:21 +00002446 }
2447
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002448 plcf->url = *url;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002449
Igor Sysoev02f742b2005-04-08 15:18:55 +00002450 return NGX_CONF_OK;
2451}
2452
2453
2454static char *
Igor Sysoev899b44e2005-05-12 14:58:06 +00002455ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev02f742b2005-04-08 15:18:55 +00002456{
Igor Sysoev899b44e2005-05-12 14:58:06 +00002457 ngx_http_proxy_loc_conf_t *plcf = conf;
2458
2459 ngx_str_t *value;
2460 ngx_array_t *vars_lengths, *vars_values;
2461 ngx_http_script_compile_t sc;
2462 ngx_http_proxy_redirect_t *pr;
2463
2464 if (plcf->redirect == 0) {
2465 return NGX_CONF_OK;
2466 }
2467
2468 value = cf->args->elts;
2469
Igor Sysoev06d4aa12009-04-30 12:43:38 +00002470 if (cf->args->nelts == 2) {
2471 if (ngx_strcmp(value[1].data, "off") == 0) {
2472 plcf->redirect = 0;
2473 plcf->redirects = NULL;
2474 return NGX_CONF_OK;
2475 }
2476
2477 if (ngx_strcmp(value[1].data, "false") == 0) {
2478 ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
2479 "invalid parameter \"false\", use \"off\" instead");
2480 plcf->redirect = 0;
2481 plcf->redirects = NULL;
2482 return NGX_CONF_OK;
2483 }
2484
2485 if (ngx_strcmp(value[1].data, "default") != 0) {
2486 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2487 "invalid parameter \"%V\"", &value[1]);
2488 return NGX_CONF_ERROR;
2489 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00002490 }
2491
2492 if (plcf->redirects == NULL) {
2493 plcf->redirects = ngx_array_create(cf->pool, 1,
2494 sizeof(ngx_http_proxy_redirect_t));
2495 if (plcf->redirects == NULL) {
2496 return NGX_CONF_ERROR;
2497 }
2498 }
2499
2500 pr = ngx_array_push(plcf->redirects);
2501 if (pr == NULL) {
2502 return NGX_CONF_ERROR;
2503 }
2504
Igor Sysoev06d4aa12009-04-30 12:43:38 +00002505 if (ngx_strcmp(value[1].data, "default") == 0) {
Igor Sysoev7fa1c072010-03-10 14:41:49 +00002506 if (plcf->proxy_lengths) {
2507 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2508 "\"proxy_redirect default\" may not be used "
2509 "with \"proxy_pass\" directive with variables");
2510 return NGX_CONF_ERROR;
2511 }
2512
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002513 if (plcf->url.data == NULL) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002514 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev931d88c2010-03-10 14:37:18 +00002515 "\"proxy_redirect default\" must go "
Igor Sysoev899b44e2005-05-12 14:58:06 +00002516 "after the \"proxy_pass\" directive");
2517 return NGX_CONF_ERROR;
2518 }
2519
2520 pr->handler = ngx_http_proxy_rewrite_redirect_text;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002521 pr->redirect = plcf->url;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00002522
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002523 if (plcf->vars.uri.len) {
2524 pr->replacement.text = plcf->location;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00002525
2526 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00002527 ngx_str_null(&pr->replacement.text);
Igor Sysoevafd7ec52006-05-29 17:28:12 +00002528 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00002529
2530 return NGX_CONF_OK;
2531 }
2532
2533 if (ngx_http_script_variables_count(&value[2]) == 0) {
2534 pr->handler = ngx_http_proxy_rewrite_redirect_text;
2535 pr->redirect = value[1];
2536 pr->replacement.text = value[2];
2537
2538 return NGX_CONF_OK;
2539 }
2540
2541 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2542
2543 vars_lengths = NULL;
2544 vars_values = NULL;
2545
2546 sc.cf = cf;
2547 sc.source = &value[2];
2548 sc.lengths = &vars_lengths;
2549 sc.values = &vars_values;
2550 sc.complete_lengths = 1;
2551 sc.complete_values = 1;
2552
2553 if (ngx_http_script_compile(&sc) != NGX_OK) {
2554 return NGX_CONF_ERROR;
2555 }
2556
2557 pr->handler = ngx_http_proxy_rewrite_redirect_vars;
2558 pr->redirect = value[1];
2559 pr->replacement.vars.lengths = vars_lengths->elts;
2560 pr->replacement.vars.values = vars_values->elts;
2561
Igor Sysoev02f742b2005-04-08 15:18:55 +00002562 return NGX_CONF_OK;
2563}
2564
2565
2566static char *
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002567ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2568{
2569 ngx_http_proxy_loc_conf_t *plcf = conf;
2570
2571 ngx_str_t *value;
2572 ngx_http_script_compile_t sc;
2573
Igor Sysoevda28ef82009-05-28 13:31:43 +00002574 if (plcf->upstream.store != NGX_CONF_UNSET
2575 || plcf->upstream.store_lengths)
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002576 {
2577 return "is duplicate";
2578 }
2579
2580 value = cf->args->elts;
2581
Igor Sysoev98f692a2009-05-28 13:41:44 +00002582 if (ngx_strcmp(value[1].data, "off") == 0) {
2583 plcf->upstream.store = 0;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002584 return NGX_CONF_OK;
2585 }
2586
Igor Sysoev98f692a2009-05-28 13:41:44 +00002587#if (NGX_HTTP_CACHE)
2588
2589 if (plcf->upstream.cache != NGX_CONF_UNSET_PTR
2590 && plcf->upstream.cache != NULL)
2591 {
2592 return "is incompatible with \"proxy_cache\"";
2593 }
2594
2595#endif
2596
2597 if (ngx_strcmp(value[1].data, "on") == 0) {
2598 plcf->upstream.store = 1;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002599 return NGX_CONF_OK;
2600 }
2601
2602 /* include the terminating '\0' into script */
2603 value[1].len++;
2604
2605 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2606
2607 sc.cf = cf;
2608 sc.source = &value[1];
2609 sc.lengths = &plcf->upstream.store_lengths;
2610 sc.values = &plcf->upstream.store_values;
Igor Sysoevbfb23bf2007-10-09 20:11:03 +00002611 sc.variables = ngx_http_script_variables_count(&value[1]);
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002612 sc.complete_lengths = 1;
2613 sc.complete_values = 1;
2614
2615 if (ngx_http_script_compile(&sc) != NGX_OK) {
2616 return NGX_CONF_ERROR;
2617 }
2618
2619 return NGX_CONF_OK;
2620}
2621
2622
Igor Sysoev52859f22009-03-23 13:14:51 +00002623#if (NGX_HTTP_CACHE)
2624
2625static char *
2626ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2627{
2628 ngx_http_proxy_loc_conf_t *plcf = conf;
2629
2630 ngx_str_t *value;
2631
2632 value = cf->args->elts;
2633
2634 if (plcf->upstream.cache != NGX_CONF_UNSET_PTR) {
2635 return "is duplicate";
2636 }
2637
2638 if (ngx_strcmp(value[1].data, "off") == 0) {
2639 plcf->upstream.cache = NULL;
2640 return NGX_CONF_OK;
2641 }
2642
Igor Sysoev98f692a2009-05-28 13:41:44 +00002643 if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) {
2644 return "is incompatible with \"proxy_store\"";
2645 }
2646
Igor Sysoev52859f22009-03-23 13:14:51 +00002647 plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
2648 &ngx_http_proxy_module);
2649 if (plcf->upstream.cache == NULL) {
2650 return NGX_CONF_ERROR;
2651 }
2652
2653 return NGX_CONF_OK;
2654}
2655
Igor Sysoev44a69c82009-04-06 08:58:44 +00002656
2657static char *
2658ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2659{
2660 ngx_http_proxy_loc_conf_t *plcf = conf;
2661
2662 ngx_str_t *value;
2663 ngx_http_compile_complex_value_t ccv;
2664
2665 value = cf->args->elts;
2666
2667 if (plcf->cache_key.value.len) {
2668 return "is duplicate";
2669 }
2670
2671 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
2672
2673 ccv.cf = cf;
2674 ccv.value = &value[1];
2675 ccv.complex_value = &plcf->cache_key;
2676
2677 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
2678 return NGX_CONF_ERROR;
2679 }
2680
2681 return NGX_CONF_OK;
2682}
2683
Igor Sysoev52859f22009-03-23 13:14:51 +00002684#endif
2685
2686
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002687static char *
Igor Sysoev02f742b2005-04-08 15:18:55 +00002688ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
2689{
2690#if (NGX_FREEBSD)
2691 ssize_t *np = data;
2692
Igor Sysoev08e63d42006-08-14 15:09:38 +00002693 if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002694 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2695 "\"proxy_send_lowat\" must be less than %d "
2696 "(sysctl net.inet.tcp.sendspace)",
2697 ngx_freebsd_net_inet_tcp_sendspace);
2698
2699 return NGX_CONF_ERROR;
2700 }
2701
2702#elif !(NGX_HAVE_SO_SNDLOWAT)
2703 ssize_t *np = data;
2704
2705 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2706 "\"proxy_send_lowat\" is not supported, ignored");
2707
2708 *np = 0;
2709
2710#endif
2711
2712 return NGX_CONF_OK;
2713}
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002714
2715
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002716#if (NGX_HTTP_SSL)
2717
2718static ngx_int_t
2719ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
2720{
2721 ngx_pool_cleanup_t *cln;
2722
2723 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2724 if (plcf->upstream.ssl == NULL) {
2725 return NGX_ERROR;
2726 }
2727
2728 plcf->upstream.ssl->log = cf->log;
2729
2730 if (ngx_ssl_create(plcf->upstream.ssl,
2731 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
2732 != NGX_OK)
2733 {
2734 return NGX_ERROR;
2735 }
2736
2737 cln = ngx_pool_cleanup_add(cf->pool, 0);
2738 if (cln == NULL) {
2739 return NGX_ERROR;
2740 }
2741
2742 cln->handler = ngx_ssl_cleanup_ctx;
2743 cln->data = plcf->upstream.ssl;
2744
2745 return NGX_OK;
2746}
2747
2748#endif
2749
2750
Igor Sysoev52859f22009-03-23 13:14:51 +00002751static void
2752ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002753{
Igor Sysoevc9491d12008-08-26 14:24:14 +00002754 if (u->family != AF_UNIX) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002755
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002756 if (u->no_port || u->port == u->default_port) {
Igor Sysoev52859f22009-03-23 13:14:51 +00002757
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002758 v->host_header = u->host;
2759
2760 if (u->default_port == 80) {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00002761 ngx_str_set(&v->port, "80");
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002762
2763 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00002764 ngx_str_set(&v->port, "443");
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002765 }
2766
2767 } else {
Igor Sysoev00e03772007-11-28 19:55:31 +00002768 v->host_header.len = u->host.len + 1 + u->port_text.len;
2769 v->host_header.data = u->host.data;
2770 v->port = u->port_text;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002771 }
2772
Igor Sysoev52859f22009-03-23 13:14:51 +00002773 v->key_start.len += v->host_header.len;
2774
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002775 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00002776 ngx_str_set(&v->host_header, "localhost");
2777 ngx_str_null(&v->port);
Igor Sysoev52859f22009-03-23 13:14:51 +00002778 v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002779 }
2780
2781 v->uri = u->uri;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002782}