blob: c24ef170de5dd1e2843f30901492e1d2f82697f3 [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
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoev02f742b2005-04-08 15:18:55 +00005 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
Igor Sysoev02f742b2005-04-08 15:18:55 +000010#include <ngx_http.h>
11
12
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +030013typedef struct {
14 ngx_array_t caches; /* ngx_http_file_cache_t * */
15} ngx_http_proxy_main_conf_t;
16
17
Valentin Bartenev582dac12012-02-13 10:42:44 +000018typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
Igor Sysoev899b44e2005-05-12 14:58:06 +000019
Valentin Bartenev582dac12012-02-13 10:42:44 +000020typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
Valentin Bartenev7c611aa2012-02-13 10:56:09 +000021 ngx_table_elt_t *h, size_t prefix, size_t len,
22 ngx_http_proxy_rewrite_t *pr);
Igor Sysoev899b44e2005-05-12 14:58:06 +000023
Valentin Bartenev582dac12012-02-13 10:42:44 +000024struct ngx_http_proxy_rewrite_s {
25 ngx_http_proxy_rewrite_pt handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +000026
27 union {
Valentin Bartenev0be95542011-12-12 09:02:29 +000028 ngx_http_complex_value_t complex;
29#if (NGX_PCRE)
30 ngx_http_regex_t *regex;
31#endif
Valentin Bartenev582dac12012-02-13 10:42:44 +000032 } pattern;
Igor Sysoev899b44e2005-05-12 14:58:06 +000033
Valentin Bartenev0be95542011-12-12 09:02:29 +000034 ngx_http_complex_value_t replacement;
Igor Sysoev899b44e2005-05-12 14:58:06 +000035};
36
37
Igor Sysoev02f742b2005-04-08 15:18:55 +000038typedef struct {
Igor Sysoev52859f22009-03-23 13:14:51 +000039 ngx_str_t key_start;
Igor Sysoev73c31212008-12-10 14:44:48 +000040 ngx_str_t schema;
Igor Sysoev96dd8af2007-11-27 13:34:13 +000041 ngx_str_t host_header;
42 ngx_str_t port;
43 ngx_str_t uri;
44} ngx_http_proxy_vars_t;
45
46
47typedef struct {
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +030048 ngx_array_t *flushes;
49 ngx_array_t *lengths;
50 ngx_array_t *values;
51 ngx_hash_t hash;
52} ngx_http_proxy_headers_t;
53
54
55typedef struct {
Igor Sysoev6f134cc2006-05-23 14:54:58 +000056 ngx_http_upstream_conf_t upstream;
Igor Sysoev02f742b2005-04-08 15:18:55 +000057
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +030058 ngx_array_t *body_flushes;
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +030059 ngx_array_t *body_lengths;
60 ngx_array_t *body_values;
61 ngx_str_t body_source;
Igor Sysoev02f742b2005-04-08 15:18:55 +000062
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +030063 ngx_http_proxy_headers_t headers;
Roman Arutyunyan8898c972014-11-19 17:33:23 +030064#if (NGX_HTTP_CACHE)
65 ngx_http_proxy_headers_t headers_cache;
66#endif
Igor Sysoev6f134cc2006-05-23 14:54:58 +000067 ngx_array_t *headers_source;
Igor Sysoev02f742b2005-04-08 15:18:55 +000068
Igor Sysoev96dd8af2007-11-27 13:34:13 +000069 ngx_array_t *proxy_lengths;
70 ngx_array_t *proxy_values;
71
Igor Sysoev6f134cc2006-05-23 14:54:58 +000072 ngx_array_t *redirects;
Valentin Barteneve9df2d62012-02-13 11:04:45 +000073 ngx_array_t *cookie_domains;
Valentin Barteneva113cb32012-02-13 11:08:05 +000074 ngx_array_t *cookie_paths;
Igor Sysoev02f742b2005-04-08 15:18:55 +000075
Igor Sysoev6f134cc2006-05-23 14:54:58 +000076 ngx_str_t method;
Igor Sysoev96dd8af2007-11-27 13:34:13 +000077 ngx_str_t location;
78 ngx_str_t url;
79
Igor Sysoev44a69c82009-04-06 08:58:44 +000080#if (NGX_HTTP_CACHE)
81 ngx_http_complex_value_t cache_key;
82#endif
83
Igor Sysoev96dd8af2007-11-27 13:34:13 +000084 ngx_http_proxy_vars_t vars;
Igor Sysoev02f742b2005-04-08 15:18:55 +000085
Igor Sysoev6f134cc2006-05-23 14:54:58 +000086 ngx_flag_t redirect;
Igor Sysoev8a19bff2007-04-22 20:21:59 +000087
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +000088 ngx_uint_t http_version;
89
Igor Sysoev8a19bff2007-04-22 20:21:59 +000090 ngx_uint_t headers_hash_max_size;
91 ngx_uint_t headers_hash_bucket_size;
Andrei Belov003b2cd2013-09-19 18:30:33 +040092
93#if (NGX_HTTP_SSL)
94 ngx_uint_t ssl;
95 ngx_uint_t ssl_protocols;
Piotr Sikora43736b12013-09-23 15:58:28 -070096 ngx_str_t ssl_ciphers;
Maxim Dounin27475dd2014-04-18 20:13:30 +040097 ngx_uint_t ssl_verify_depth;
98 ngx_str_t ssl_trusted_certificate;
99 ngx_str_t ssl_crl;
Piotr Sikoraa9d9b092014-10-30 04:30:41 -0700100 ngx_str_t ssl_certificate;
101 ngx_str_t ssl_certificate_key;
102 ngx_array_t *ssl_passwords;
Andrei Belov003b2cd2013-09-19 18:30:33 +0400103#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +0000104} ngx_http_proxy_loc_conf_t;
105
106
107typedef struct {
Igor Sysoev54b35b02010-06-15 15:15:06 +0000108 ngx_http_status_t status;
Maxim Dounindf74d882012-11-21 00:59:16 +0000109 ngx_http_chunked_t chunked;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000110 ngx_http_proxy_vars_t vars;
Maxim Dounin9a483c82012-11-21 01:03:48 +0000111 off_t internal_body_length;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000112
Maxim Dounin55344dd2015-03-23 21:09:19 +0300113 ngx_chain_t *free;
114 ngx_chain_t *busy;
115
116 unsigned head:1;
117 unsigned internal_chunked:1;
118 unsigned header_sent:1;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000119} ngx_http_proxy_ctx_t;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000120
Igor Sysoev02f742b2005-04-08 15:18:55 +0000121
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000122static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
123 ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
Igor Sysoev52859f22009-03-23 13:14:51 +0000124#if (NGX_HTTP_CACHE)
125static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
126#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +0000127static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
128static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
Maxim Dounin55344dd2015-03-23 21:09:19 +0300129static ngx_int_t ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000130static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000131static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000132static ngx_int_t ngx_http_proxy_input_filter_init(void *data);
133static ngx_int_t ngx_http_proxy_copy_filter(ngx_event_pipe_t *p,
134 ngx_buf_t *buf);
135static ngx_int_t ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p,
136 ngx_buf_t *buf);
137static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
138 ssize_t bytes);
139static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
140 ssize_t bytes);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000141static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
142static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
143 ngx_int_t rc);
144
Igor Sysoev09c684b2005-11-09 17:25:55 +0000145static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
146 ngx_http_variable_value_t *v, uintptr_t data);
147static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
148 ngx_http_variable_value_t *v, uintptr_t data);
149static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +0000150 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
Igor Sysoev09c684b2005-11-09 17:25:55 +0000151 ngx_http_variable_value_t *v, uintptr_t data);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000152static ngx_int_t
153 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
154 ngx_http_variable_value_t *v, uintptr_t data);
Maxim Dounin55344dd2015-03-23 21:09:19 +0300155static ngx_int_t ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
156 ngx_http_variable_value_t *v, uintptr_t data);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000157static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
158 ngx_table_elt_t *h, size_t prefix);
Valentin Barteneve9df2d62012-02-13 11:04:45 +0000159static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
160 ngx_table_elt_t *h);
161static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
162 ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
Valentin Bartenev7c611aa2012-02-13 10:56:09 +0000163static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
164 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000165
Igor Sysoev899b44e2005-05-12 14:58:06 +0000166static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300167static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000168static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
169static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
170 void *parent, void *child);
Roman Arutyunyan62dfdf12014-11-19 17:33:21 +0300171static ngx_int_t ngx_http_proxy_init_headers(ngx_conf_t *cf,
Roman Arutyunyan8898c972014-11-19 17:33:23 +0300172 ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_headers_t *headers,
173 ngx_keyval_t *default_headers);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000174
175static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
176 void *conf);
Igor Sysoev899b44e2005-05-12 14:58:06 +0000177static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000178 void *conf);
Valentin Barteneve9df2d62012-02-13 11:04:45 +0000179static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
180 void *conf);
Valentin Barteneva113cb32012-02-13 11:08:05 +0000181static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
182 void *conf);
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000183static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
184 void *conf);
Igor Sysoev52859f22009-03-23 13:14:51 +0000185#if (NGX_HTTP_CACHE)
186static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
187 void *conf);
Igor Sysoev44a69c82009-04-06 08:58:44 +0000188static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
189 void *conf);
Igor Sysoev52859f22009-03-23 13:14:51 +0000190#endif
Piotr Sikoraa9d9b092014-10-30 04:30:41 -0700191#if (NGX_HTTP_SSL)
192static char *ngx_http_proxy_ssl_password_file(ngx_conf_t *cf,
193 ngx_command_t *cmd, void *conf);
194#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +0000195
Igor Sysoev02f742b2005-04-08 15:18:55 +0000196static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
197
Valentin Bartenev85551e52012-02-13 11:00:08 +0000198static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
199 ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
200
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000201#if (NGX_HTTP_SSL)
202static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
203 ngx_http_proxy_loc_conf_t *plcf);
204#endif
Igor Sysoev52859f22009-03-23 13:14:51 +0000205static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000206
Igor Sysoev899b44e2005-05-12 14:58:06 +0000207
Igor Sysoev02f742b2005-04-08 15:18:55 +0000208static ngx_conf_post_t ngx_http_proxy_lowat_post =
Igor Sysoev899b44e2005-05-12 14:58:06 +0000209 { ngx_http_proxy_lowat_check };
210
Igor Sysoev02f742b2005-04-08 15:18:55 +0000211
212static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
213 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
214 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
215 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
Maxim Dounin35062c62016-03-28 19:50:19 +0300216 { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000217 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
Igor Sysoev797c6ef2008-09-30 15:39:02 +0000218 { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
Igor Sysoev8fea8852006-03-15 09:53:04 +0000219 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
Igor Sysoev797c6ef2008-09-30 15:39:02 +0000220 { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
Maxim Dounin1a983a02013-05-27 16:54:09 +0400221 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000222 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
Igor Sysoev55192e72009-06-06 18:49:47 +0000223 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000224 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000225 { ngx_null_string, 0 }
226};
227
228
Andrei Belov003b2cd2013-09-19 18:30:33 +0400229#if (NGX_HTTP_SSL)
230
231static ngx_conf_bitmask_t ngx_http_proxy_ssl_protocols[] = {
232 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
233 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
234 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
235 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
236 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
237 { ngx_null_string, 0 }
238};
239
240#endif
241
242
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000243static ngx_conf_enum_t ngx_http_proxy_http_version[] = {
244 { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
245 { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
246 { ngx_null_string, 0 }
247};
248
249
Igor Sysoev52859f22009-03-23 13:14:51 +0000250ngx_module_t ngx_http_proxy_module;
251
252
Igor Sysoev02f742b2005-04-08 15:18:55 +0000253static ngx_command_t ngx_http_proxy_commands[] = {
254
255 { ngx_string("proxy_pass"),
Igor Sysoeve927b1e2006-11-14 12:43:14 +0000256 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000257 ngx_http_proxy_pass,
258 NGX_HTTP_LOC_CONF_OFFSET,
259 0,
260 NULL },
261
Igor Sysoev899b44e2005-05-12 14:58:06 +0000262 { ngx_string("proxy_redirect"),
263 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
264 ngx_http_proxy_redirect,
265 NGX_HTTP_LOC_CONF_OFFSET,
266 0,
267 NULL },
268
Valentin Barteneve9df2d62012-02-13 11:04:45 +0000269 { ngx_string("proxy_cookie_domain"),
270 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
271 ngx_http_proxy_cookie_domain,
272 NGX_HTTP_LOC_CONF_OFFSET,
273 0,
274 NULL },
275
Valentin Barteneva113cb32012-02-13 11:08:05 +0000276 { ngx_string("proxy_cookie_path"),
277 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
278 ngx_http_proxy_cookie_path,
279 NGX_HTTP_LOC_CONF_OFFSET,
280 0,
281 NULL },
282
Igor Sysoev58feb532007-07-12 11:19:05 +0000283 { ngx_string("proxy_store"),
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000284 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
285 ngx_http_proxy_store,
286 NGX_HTTP_LOC_CONF_OFFSET,
287 0,
288 NULL },
289
290 { ngx_string("proxy_store_access"),
Igor Sysoev58feb532007-07-12 11:19:05 +0000291 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
292 ngx_conf_set_access_slot,
293 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000294 offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access),
Igor Sysoev58feb532007-07-12 11:19:05 +0000295 NULL },
296
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000297 { ngx_string("proxy_buffering"),
298 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
299 ngx_conf_set_flag_slot,
300 NGX_HTTP_LOC_CONF_OFFSET,
301 offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
302 NULL },
303
Maxim Douninf568ff82015-03-23 21:09:19 +0300304 { ngx_string("proxy_request_buffering"),
305 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
306 ngx_conf_set_flag_slot,
307 NGX_HTTP_LOC_CONF_OFFSET,
308 offsetof(ngx_http_proxy_loc_conf_t, upstream.request_buffering),
309 NULL },
310
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000311 { ngx_string("proxy_ignore_client_abort"),
312 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
313 ngx_conf_set_flag_slot,
314 NGX_HTTP_LOC_CONF_OFFSET,
315 offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
316 NULL },
317
Igor Sysoev72e92872009-11-02 15:24:02 +0000318 { ngx_string("proxy_bind"),
319 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoevbd375b92009-12-23 14:22:17 +0000320 ngx_http_upstream_bind_set_slot,
Igor Sysoev72e92872009-11-02 15:24:02 +0000321 NGX_HTTP_LOC_CONF_OFFSET,
322 offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
323 NULL },
324
Igor Sysoev02f742b2005-04-08 15:18:55 +0000325 { ngx_string("proxy_connect_timeout"),
326 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
327 ngx_conf_set_msec_slot,
328 NGX_HTTP_LOC_CONF_OFFSET,
329 offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
330 NULL },
331
332 { ngx_string("proxy_send_timeout"),
333 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
334 ngx_conf_set_msec_slot,
335 NGX_HTTP_LOC_CONF_OFFSET,
336 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
337 NULL },
338
339 { ngx_string("proxy_send_lowat"),
340 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
341 ngx_conf_set_size_slot,
342 NGX_HTTP_LOC_CONF_OFFSET,
343 offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
344 &ngx_http_proxy_lowat_post },
345
Igor Sysoevef809b82006-06-28 16:00:26 +0000346 { ngx_string("proxy_intercept_errors"),
347 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
348 ngx_conf_set_flag_slot,
349 NGX_HTTP_LOC_CONF_OFFSET,
350 offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors),
351 NULL },
352
Igor Sysoev899b44e2005-05-12 14:58:06 +0000353 { ngx_string("proxy_set_header"),
354 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000355 ngx_conf_set_keyval_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000356 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000357 offsetof(ngx_http_proxy_loc_conf_t, headers_source),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000358 NULL },
359
Igor Sysoev8a19bff2007-04-22 20:21:59 +0000360 { ngx_string("proxy_headers_hash_max_size"),
361 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
362 ngx_conf_set_num_slot,
363 NGX_HTTP_LOC_CONF_OFFSET,
364 offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size),
365 NULL },
366
367 { ngx_string("proxy_headers_hash_bucket_size"),
368 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
369 ngx_conf_set_num_slot,
370 NGX_HTTP_LOC_CONF_OFFSET,
371 offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size),
372 NULL },
373
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000374 { ngx_string("proxy_set_body"),
375 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
376 ngx_conf_set_str_slot,
377 NGX_HTTP_LOC_CONF_OFFSET,
378 offsetof(ngx_http_proxy_loc_conf_t, body_source),
379 NULL },
380
Igor Sysoev899b44e2005-05-12 14:58:06 +0000381 { ngx_string("proxy_method"),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000382 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev78452232005-10-12 13:50:36 +0000383 ngx_conf_set_str_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000384 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev78452232005-10-12 13:50:36 +0000385 offsetof(ngx_http_proxy_loc_conf_t, method),
386 NULL },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000387
Igor Sysoev899b44e2005-05-12 14:58:06 +0000388 { ngx_string("proxy_pass_request_headers"),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000389 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
390 ngx_conf_set_flag_slot,
391 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000392 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
393 NULL },
394
395 { ngx_string("proxy_pass_request_body"),
396 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
397 ngx_conf_set_flag_slot,
398 NGX_HTTP_LOC_CONF_OFFSET,
399 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000400 NULL },
401
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000402 { ngx_string("proxy_buffer_size"),
403 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
404 ngx_conf_set_size_slot,
405 NGX_HTTP_LOC_CONF_OFFSET,
406 offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size),
407 NULL },
408
Igor Sysoev02f742b2005-04-08 15:18:55 +0000409 { ngx_string("proxy_read_timeout"),
410 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
411 ngx_conf_set_msec_slot,
412 NGX_HTTP_LOC_CONF_OFFSET,
413 offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
414 NULL },
415
416 { ngx_string("proxy_buffers"),
417 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
418 ngx_conf_set_bufs_slot,
419 NGX_HTTP_LOC_CONF_OFFSET,
420 offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
421 NULL },
422
423 { ngx_string("proxy_busy_buffers_size"),
424 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
425 ngx_conf_set_size_slot,
426 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000427 offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000428 NULL },
429
Roman Arutyunyan2244a5e2014-10-14 18:32:01 +0400430 { ngx_string("proxy_force_ranges"),
431 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
432 ngx_conf_set_flag_slot,
433 NGX_HTTP_LOC_CONF_OFFSET,
434 offsetof(ngx_http_proxy_loc_conf_t, upstream.force_ranges),
435 NULL },
436
Roman Arutyunyan18e4d042014-10-28 12:29:59 +0300437 { ngx_string("proxy_limit_rate"),
438 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
439 ngx_conf_set_size_slot,
440 NGX_HTTP_LOC_CONF_OFFSET,
441 offsetof(ngx_http_proxy_loc_conf_t, upstream.limit_rate),
442 NULL },
443
Igor Sysoev52859f22009-03-23 13:14:51 +0000444#if (NGX_HTTP_CACHE)
445
446 { ngx_string("proxy_cache"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000447 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev52859f22009-03-23 13:14:51 +0000448 ngx_http_proxy_cache,
Igor Sysoev0ded9db2009-03-23 16:40:11 +0000449 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev64416aa2009-03-23 15:57:57 +0000450 0,
Igor Sysoev52859f22009-03-23 13:14:51 +0000451 NULL },
452
Igor Sysoev44a69c82009-04-06 08:58:44 +0000453 { ngx_string("proxy_cache_key"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000454 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev44a69c82009-04-06 08:58:44 +0000455 ngx_http_proxy_cache_key,
456 NGX_HTTP_LOC_CONF_OFFSET,
457 0,
458 NULL },
459
Igor Sysoev52859f22009-03-23 13:14:51 +0000460 { ngx_string("proxy_cache_path"),
461 NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
462 ngx_http_file_cache_set_slot,
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300463 NGX_HTTP_MAIN_CONF_OFFSET,
464 offsetof(ngx_http_proxy_main_conf_t, caches),
Igor Sysoev52859f22009-03-23 13:14:51 +0000465 &ngx_http_proxy_module },
466
Igor Sysoevf7d659a2010-07-19 09:36:04 +0000467 { ngx_string("proxy_cache_bypass"),
468 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
469 ngx_http_set_predicate_slot,
470 NGX_HTTP_LOC_CONF_OFFSET,
471 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
472 NULL },
473
Igor Sysoev9b2763a2010-05-24 11:01:05 +0000474 { ngx_string("proxy_no_cache"),
475 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
Igor Sysoevf3870c62010-07-14 11:15:45 +0000476 ngx_http_set_predicate_slot,
Igor Sysoev9b2763a2010-05-24 11:01:05 +0000477 NGX_HTTP_LOC_CONF_OFFSET,
478 offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
479 NULL },
480
Igor Sysoev52859f22009-03-23 13:14:51 +0000481 { ngx_string("proxy_cache_valid"),
482 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
483 ngx_http_file_cache_valid_set_slot,
484 NGX_HTTP_LOC_CONF_OFFSET,
485 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
486 NULL },
487
488 { ngx_string("proxy_cache_min_uses"),
489 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
490 ngx_conf_set_num_slot,
491 NGX_HTTP_LOC_CONF_OFFSET,
492 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
493 NULL },
494
495 { ngx_string("proxy_cache_use_stale"),
496 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
497 ngx_conf_set_bitmask_slot,
498 NGX_HTTP_LOC_CONF_OFFSET,
499 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
500 &ngx_http_proxy_next_upstream_masks },
501
Igor Sysoev5ed36912009-05-19 13:27:27 +0000502 { ngx_string("proxy_cache_methods"),
503 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
504 ngx_conf_set_bitmask_slot,
505 NGX_HTTP_LOC_CONF_OFFSET,
506 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
507 &ngx_http_upstream_cache_method_mask },
508
Maxim Dounin822fe462011-12-26 11:15:23 +0000509 { ngx_string("proxy_cache_lock"),
510 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
511 ngx_conf_set_flag_slot,
512 NGX_HTTP_LOC_CONF_OFFSET,
513 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
514 NULL },
515
516 { ngx_string("proxy_cache_lock_timeout"),
517 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
518 ngx_conf_set_msec_slot,
519 NGX_HTTP_LOC_CONF_OFFSET,
520 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
521 NULL },
522
Roman Arutyunyan2628cc12014-11-18 20:41:12 +0300523 { ngx_string("proxy_cache_lock_age"),
524 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
525 ngx_conf_set_msec_slot,
526 NGX_HTTP_LOC_CONF_OFFSET,
527 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_age),
528 NULL },
529
Maxim Dounin1ac26932013-11-18 20:48:22 +0400530 { ngx_string("proxy_cache_revalidate"),
531 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
532 ngx_conf_set_flag_slot,
533 NGX_HTTP_LOC_CONF_OFFSET,
534 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_revalidate),
535 NULL },
536
Roman Arutyunyanf0ee4eb2015-11-11 15:47:30 +0300537 { ngx_string("proxy_cache_convert_head"),
538 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
539 ngx_conf_set_flag_slot,
540 NGX_HTTP_LOC_CONF_OFFSET,
541 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_convert_head),
542 NULL },
543
Igor Sysoev52859f22009-03-23 13:14:51 +0000544#endif
545
Igor Sysoev02f742b2005-04-08 15:18:55 +0000546 { ngx_string("proxy_temp_path"),
547 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
548 ngx_conf_set_path_slot,
549 NGX_HTTP_LOC_CONF_OFFSET,
550 offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
Igor Sysoev52859f22009-03-23 13:14:51 +0000551 NULL },
Igor Sysoev02f742b2005-04-08 15:18:55 +0000552
553 { ngx_string("proxy_max_temp_file_size"),
554 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
555 ngx_conf_set_size_slot,
556 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000557 offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000558 NULL },
559
560 { ngx_string("proxy_temp_file_write_size"),
561 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
562 ngx_conf_set_size_slot,
563 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev187b7d92005-07-14 12:51:53 +0000564 offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000565 NULL },
566
567 { ngx_string("proxy_next_upstream"),
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000568 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000569 ngx_conf_set_bitmask_slot,
570 NGX_HTTP_LOC_CONF_OFFSET,
571 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
572 &ngx_http_proxy_next_upstream_masks },
573
Roman Arutyunyan02ce6c42014-09-12 18:50:47 +0400574 { ngx_string("proxy_next_upstream_tries"),
575 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
576 ngx_conf_set_num_slot,
577 NGX_HTTP_LOC_CONF_OFFSET,
578 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_tries),
579 NULL },
580
581 { ngx_string("proxy_next_upstream_timeout"),
582 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
583 ngx_conf_set_msec_slot,
584 NGX_HTTP_LOC_CONF_OFFSET,
585 offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout),
586 NULL },
587
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000588 { ngx_string("proxy_pass_header"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000589 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000590 ngx_conf_set_str_array_slot,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000591 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000592 offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000593 NULL },
594
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000595 { ngx_string("proxy_hide_header"),
Igor Sysoev6d9d07b2010-08-02 12:47:52 +0000596 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000597 ngx_conf_set_str_array_slot,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000598 NGX_HTTP_LOC_CONF_OFFSET,
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000599 offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
Igor Sysoev02f742b2005-04-08 15:18:55 +0000600 NULL },
601
Igor Sysoevb01c9cc2009-04-30 16:15:07 +0000602 { ngx_string("proxy_ignore_headers"),
603 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
604 ngx_conf_set_bitmask_slot,
605 NGX_HTTP_LOC_CONF_OFFSET,
606 offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
Igor Sysoev7e14b502010-07-02 09:25:38 +0000607 &ngx_http_upstream_ignore_headers_masks },
Igor Sysoevb01c9cc2009-04-30 16:15:07 +0000608
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000609 { ngx_string("proxy_http_version"),
610 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
611 ngx_conf_set_enum_slot,
612 NGX_HTTP_LOC_CONF_OFFSET,
613 offsetof(ngx_http_proxy_loc_conf_t, http_version),
614 &ngx_http_proxy_http_version },
615
Igor Sysoev916ee8e2008-08-17 17:47:52 +0000616#if (NGX_HTTP_SSL)
617
618 { ngx_string("proxy_ssl_session_reuse"),
619 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
620 ngx_conf_set_flag_slot,
621 NGX_HTTP_LOC_CONF_OFFSET,
622 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
623 NULL },
624
Andrei Belov003b2cd2013-09-19 18:30:33 +0400625 { ngx_string("proxy_ssl_protocols"),
626 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
627 ngx_conf_set_bitmask_slot,
628 NGX_HTTP_LOC_CONF_OFFSET,
629 offsetof(ngx_http_proxy_loc_conf_t, ssl_protocols),
630 &ngx_http_proxy_ssl_protocols },
631
Piotr Sikora43736b12013-09-23 15:58:28 -0700632 { ngx_string("proxy_ssl_ciphers"),
633 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
634 ngx_conf_set_str_slot,
635 NGX_HTTP_LOC_CONF_OFFSET,
636 offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers),
637 NULL },
638
Maxim Dounin59ef4a32014-04-18 20:13:28 +0400639 { ngx_string("proxy_ssl_name"),
640 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
641 ngx_http_set_complex_value_slot,
642 NGX_HTTP_LOC_CONF_OFFSET,
643 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_name),
644 NULL },
645
646 { ngx_string("proxy_ssl_server_name"),
647 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
648 ngx_conf_set_flag_slot,
649 NGX_HTTP_LOC_CONF_OFFSET,
650 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_server_name),
651 NULL },
652
Maxim Dounin27475dd2014-04-18 20:13:30 +0400653 { ngx_string("proxy_ssl_verify"),
654 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
655 ngx_conf_set_flag_slot,
656 NGX_HTTP_LOC_CONF_OFFSET,
657 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify),
658 NULL },
659
660 { ngx_string("proxy_ssl_verify_depth"),
661 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
662 ngx_conf_set_num_slot,
663 NGX_HTTP_LOC_CONF_OFFSET,
664 offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth),
665 NULL },
666
667 { ngx_string("proxy_ssl_trusted_certificate"),
668 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
669 ngx_conf_set_str_slot,
670 NGX_HTTP_LOC_CONF_OFFSET,
671 offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate),
672 NULL },
673
674 { ngx_string("proxy_ssl_crl"),
675 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
676 ngx_conf_set_str_slot,
677 NGX_HTTP_LOC_CONF_OFFSET,
678 offsetof(ngx_http_proxy_loc_conf_t, ssl_crl),
679 NULL },
680
Piotr Sikoraa9d9b092014-10-30 04:30:41 -0700681 { ngx_string("proxy_ssl_certificate"),
682 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
683 ngx_conf_set_str_slot,
684 NGX_HTTP_LOC_CONF_OFFSET,
685 offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
686 NULL },
687
688 { ngx_string("proxy_ssl_certificate_key"),
689 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
690 ngx_conf_set_str_slot,
691 NGX_HTTP_LOC_CONF_OFFSET,
692 offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
693 NULL },
694
695 { ngx_string("proxy_ssl_password_file"),
696 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
697 ngx_http_proxy_ssl_password_file,
698 NGX_HTTP_LOC_CONF_OFFSET,
699 0,
700 NULL },
701
Igor Sysoev916ee8e2008-08-17 17:47:52 +0000702#endif
703
Igor Sysoev02f742b2005-04-08 15:18:55 +0000704 ngx_null_command
705};
706
707
Igor Sysoev8f125582006-07-28 15:16:17 +0000708static ngx_http_module_t ngx_http_proxy_module_ctx = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000709 ngx_http_proxy_add_variables, /* preconfiguration */
710 NULL, /* postconfiguration */
Igor Sysoev02f742b2005-04-08 15:18:55 +0000711
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300712 ngx_http_proxy_create_main_conf, /* create main configuration */
Igor Sysoev02f742b2005-04-08 15:18:55 +0000713 NULL, /* init main configuration */
714
715 NULL, /* create server configuration */
716 NULL, /* merge server configuration */
717
Ruslan Ermilovb74f8ff2012-02-28 11:31:05 +0000718 ngx_http_proxy_create_loc_conf, /* create location configuration */
719 ngx_http_proxy_merge_loc_conf /* merge location configuration */
Igor Sysoev02f742b2005-04-08 15:18:55 +0000720};
721
722
723ngx_module_t ngx_http_proxy_module = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000724 NGX_MODULE_V1,
Igor Sysoev02f742b2005-04-08 15:18:55 +0000725 &ngx_http_proxy_module_ctx, /* module context */
726 ngx_http_proxy_commands, /* module directives */
727 NGX_HTTP_MODULE, /* module type */
Igor Sysoeve5733802005-09-08 14:36:09 +0000728 NULL, /* init master */
Igor Sysoev899b44e2005-05-12 14:58:06 +0000729 NULL, /* init module */
Igor Sysoeve5733802005-09-08 14:36:09 +0000730 NULL, /* init process */
731 NULL, /* init thread */
732 NULL, /* exit thread */
733 NULL, /* exit process */
734 NULL, /* exit master */
735 NGX_MODULE_V1_PADDING
Igor Sysoev02f742b2005-04-08 15:18:55 +0000736};
737
738
Igor Sysoev02f742b2005-04-08 15:18:55 +0000739static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000740static char ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000741
Igor Sysoev899b44e2005-05-12 14:58:06 +0000742
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000743static ngx_keyval_t ngx_http_proxy_headers[] = {
744 { ngx_string("Host"), ngx_string("$proxy_host") },
745 { ngx_string("Connection"), ngx_string("close") },
Maxim Dounin9a483c82012-11-21 01:03:48 +0000746 { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
Maxim Dounin55344dd2015-03-23 21:09:19 +0300747 { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
Maxim Dounin4a32f812014-12-09 18:20:19 +0300748 { ngx_string("TE"), ngx_string("") },
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000749 { ngx_string("Keep-Alive"), ngx_string("") },
Igor Sysoev1e1f4c82008-06-26 13:00:39 +0000750 { ngx_string("Expect"), ngx_string("") },
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000751 { ngx_string("Upgrade"), ngx_string("") },
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000752 { ngx_null_string, ngx_null_string }
753};
754
755
Igor Sysoev2b89d202009-04-15 11:42:49 +0000756static ngx_str_t ngx_http_proxy_hide_headers[] = {
757 ngx_string("Date"),
758 ngx_string("Server"),
759 ngx_string("X-Pad"),
760 ngx_string("X-Accel-Expires"),
761 ngx_string("X-Accel-Redirect"),
762 ngx_string("X-Accel-Limit-Rate"),
763 ngx_string("X-Accel-Buffering"),
764 ngx_string("X-Accel-Charset"),
765 ngx_null_string
766};
767
768
Igor Sysoev081662a2009-04-15 11:21:12 +0000769#if (NGX_HTTP_CACHE)
770
771static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
772 { ngx_string("Host"), ngx_string("$proxy_host") },
773 { ngx_string("Connection"), ngx_string("close") },
Maxim Dounin9a483c82012-11-21 01:03:48 +0000774 { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
Maxim Dounin55344dd2015-03-23 21:09:19 +0300775 { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
Maxim Dounin4a32f812014-12-09 18:20:19 +0300776 { ngx_string("TE"), ngx_string("") },
Igor Sysoev081662a2009-04-15 11:21:12 +0000777 { ngx_string("Keep-Alive"), ngx_string("") },
778 { ngx_string("Expect"), ngx_string("") },
Maxim Dounin86a85192011-11-14 13:21:10 +0000779 { ngx_string("Upgrade"), ngx_string("") },
Maxim Dounin1ac26932013-11-18 20:48:22 +0400780 { ngx_string("If-Modified-Since"),
781 ngx_string("$upstream_cache_last_modified") },
Igor Sysoev081662a2009-04-15 11:21:12 +0000782 { ngx_string("If-Unmodified-Since"), ngx_string("") },
Maxim Dounin46ac5c72014-06-26 02:35:01 +0400783 { ngx_string("If-None-Match"), ngx_string("$upstream_cache_etag") },
Igor Sysoev081662a2009-04-15 11:21:12 +0000784 { ngx_string("If-Match"), ngx_string("") },
785 { ngx_string("Range"), ngx_string("") },
786 { ngx_string("If-Range"), ngx_string("") },
787 { ngx_null_string, ngx_null_string }
788};
789
Igor Sysoev2b89d202009-04-15 11:42:49 +0000790#endif
791
Igor Sysoev899b44e2005-05-12 14:58:06 +0000792
793static ngx_http_variable_t ngx_http_proxy_vars[] = {
794
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000795 { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
Igor Sysoev20612592008-03-11 14:10:11 +0000796 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000797
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000798 { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
Igor Sysoev20612592008-03-11 14:10:11 +0000799 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000800
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000801 { ngx_string("proxy_add_x_forwarded_for"), NULL,
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000802 ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000803
804#if 0
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000805 { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev899b44e2005-05-12 14:58:06 +0000806#endif
807
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000808 { ngx_string("proxy_internal_body_length"), NULL,
Maxim Dounina38455a2013-05-11 21:12:24 +0400809 ngx_http_proxy_internal_body_length_variable, 0,
810 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000811
Maxim Dounin55344dd2015-03-23 21:09:19 +0300812 { ngx_string("proxy_internal_chunked"), NULL,
813 ngx_http_proxy_internal_chunked_variable, 0,
814 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
815
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000816 { ngx_null_string, NULL, NULL, 0, 0, 0 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000817};
Igor Sysoev02f742b2005-04-08 15:18:55 +0000818
819
Igor Sysoev52859f22009-03-23 13:14:51 +0000820static ngx_path_init_t ngx_http_proxy_temp_path = {
821 ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
822};
823
824
Igor Sysoev02f742b2005-04-08 15:18:55 +0000825static ngx_int_t
826ngx_http_proxy_handler(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000827{
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300828 ngx_int_t rc;
829 ngx_http_upstream_t *u;
830 ngx_http_proxy_ctx_t *ctx;
831 ngx_http_proxy_loc_conf_t *plcf;
832#if (NGX_HTTP_CACHE)
833 ngx_http_proxy_main_conf_t *pmcf;
834#endif
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000835
Igor Sysoev15b74202009-07-27 13:25:29 +0000836 if (ngx_http_upstream_create(r) != NGX_OK) {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000837 return NGX_HTTP_INTERNAL_SERVER_ERROR;
838 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000839
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000840 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
841 if (ctx == NULL) {
Ruslan Ermilovc17b1632015-03-04 08:12:53 +0300842 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000843 }
844
845 ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
846
847 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
848
Igor Sysoev15b74202009-07-27 13:25:29 +0000849 u = r->upstream;
850
Igor Sysoeve4994fb2010-08-03 12:53:06 +0000851 if (plcf->proxy_lengths == NULL) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000852 ctx->vars = plcf->vars;
Igor Sysoev73c31212008-12-10 14:44:48 +0000853 u->schema = plcf->vars.schema;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000854#if (NGX_HTTP_SSL)
855 u->ssl = (plcf->upstream.ssl != NULL);
856#endif
857
858 } else {
859 if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
860 return NGX_HTTP_INTERNAL_SERVER_ERROR;
861 }
862 }
863
Igor Sysoev02f742b2005-04-08 15:18:55 +0000864 u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
865
866 u->conf = &plcf->upstream;
867
Igor Sysoev52859f22009-03-23 13:14:51 +0000868#if (NGX_HTTP_CACHE)
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300869 pmcf = ngx_http_get_module_main_conf(r, ngx_http_proxy_module);
870
871 u->caches = &pmcf->caches;
Igor Sysoev52859f22009-03-23 13:14:51 +0000872 u->create_key = ngx_http_proxy_create_key;
873#endif
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +0300874
Igor Sysoev02f742b2005-04-08 15:18:55 +0000875 u->create_request = ngx_http_proxy_create_request;
876 u->reinit_request = ngx_http_proxy_reinit_request;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000877 u->process_header = ngx_http_proxy_process_status_line;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000878 u->abort_request = ngx_http_proxy_abort_request;
879 u->finalize_request = ngx_http_proxy_finalize_request;
Igor Sysoevaed1ac12010-03-25 13:27:52 +0000880 r->state = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000881
Igor Sysoev899b44e2005-05-12 14:58:06 +0000882 if (plcf->redirects) {
883 u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
884 }
885
Valentin Barteneva113cb32012-02-13 11:08:05 +0000886 if (plcf->cookie_domains || plcf->cookie_paths) {
Valentin Barteneve9df2d62012-02-13 11:04:45 +0000887 u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
888 }
889
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000890 u->buffering = plcf->upstream.buffering;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000891
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000892 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
893 if (u->pipe == NULL) {
894 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000895 }
Igor Sysoev02f742b2005-04-08 15:18:55 +0000896
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +0000897 u->pipe->input_filter = ngx_http_proxy_copy_filter;
898 u->pipe->input_ctx = r;
899
900 u->input_filter_init = ngx_http_proxy_input_filter_init;
901 u->input_filter = ngx_http_proxy_non_buffered_copy_filter;
902 u->input_filter_ctx = r;
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000903
Igor Sysoev899b44e2005-05-12 14:58:06 +0000904 u->accel = 1;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000905
Maxim Douninf568ff82015-03-23 21:09:19 +0300906 if (!plcf->upstream.request_buffering
907 && plcf->body_values == NULL && plcf->upstream.pass_request_body
Maxim Dounin55344dd2015-03-23 21:09:19 +0300908 && (!r->headers_in.chunked
909 || plcf->http_version == NGX_HTTP_VERSION_11))
Maxim Douninf568ff82015-03-23 21:09:19 +0300910 {
Maxim Douninf568ff82015-03-23 21:09:19 +0300911 r->request_body_no_buffering = 1;
912 }
913
Igor Sysoev02f742b2005-04-08 15:18:55 +0000914 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
915
916 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
917 return rc;
918 }
919
920 return NGX_DONE;
921}
922
923
924static ngx_int_t
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000925ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
926 ngx_http_proxy_loc_conf_t *plcf)
927{
Igor Sysoev52859f22009-03-23 13:14:51 +0000928 u_char *p;
929 size_t add;
930 u_short port;
931 ngx_str_t proxy;
932 ngx_url_t url;
933 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000934
935 if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
936 plcf->proxy_values->elts)
937 == NULL)
938 {
939 return NGX_ERROR;
940 }
941
Igor Sysoevc9468022011-07-30 06:11:46 +0000942 if (proxy.len > 7
943 && ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0)
944 {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000945 add = 7;
946 port = 80;
947
948#if (NGX_HTTP_SSL)
949
Igor Sysoevc9468022011-07-30 06:11:46 +0000950 } else if (proxy.len > 8
951 && ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0)
952 {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000953 add = 8;
954 port = 443;
955 r->upstream->ssl = 1;
956
957#endif
958
959 } else {
960 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
961 "invalid URL prefix in \"%V\"", &proxy);
962 return NGX_ERROR;
963 }
964
Igor Sysoev52859f22009-03-23 13:14:51 +0000965 u = r->upstream;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000966
Igor Sysoev52859f22009-03-23 13:14:51 +0000967 u->schema.len = add;
968 u->schema.data = proxy.data;
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000969
Igor Sysoev52859f22009-03-23 13:14:51 +0000970 ngx_memzero(&url, sizeof(ngx_url_t));
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000971
Igor Sysoev52859f22009-03-23 13:14:51 +0000972 url.url.len = proxy.len - add;
973 url.url.data = proxy.data + add;
974 url.default_port = port;
975 url.uri_part = 1;
976 url.no_resolve = 1;
977
978 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
979 if (url.err) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000980 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev52859f22009-03-23 13:14:51 +0000981 "%s in upstream \"%V\"", url.err, &url.url);
Igor Sysoev96dd8af2007-11-27 13:34:13 +0000982 }
983
984 return NGX_ERROR;
985 }
986
Igor Sysoev6c71b882009-11-15 11:36:12 +0000987 if (url.uri.len) {
988 if (url.uri.data[0] == '?') {
989 p = ngx_pnalloc(r->pool, url.uri.len + 1);
990 if (p == NULL) {
991 return NGX_ERROR;
992 }
993
994 *p++ = '/';
995 ngx_memcpy(p, url.uri.data, url.uri.len);
996
997 url.uri.len++;
998 url.uri.data = p - 1;
Igor Sysoev164abfb2008-10-24 19:34:24 +0000999 }
Igor Sysoev164abfb2008-10-24 19:34:24 +00001000 }
1001
Igor Sysoev52859f22009-03-23 13:14:51 +00001002 ctx->vars.key_start = u->schema;
1003
1004 ngx_http_proxy_set_vars(&url, &ctx->vars);
1005
1006 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
1007 if (u->resolved == NULL) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001008 return NGX_ERROR;
1009 }
1010
Igor Sysoev52859f22009-03-23 13:14:51 +00001011 if (url.addrs && url.addrs[0].sockaddr) {
1012 u->resolved->sockaddr = url.addrs[0].sockaddr;
1013 u->resolved->socklen = url.addrs[0].socklen;
1014 u->resolved->naddrs = 1;
1015 u->resolved->host = url.addrs[0].name;
Igor Sysoev302cedc2008-12-23 19:35:12 +00001016
1017 } else {
Igor Sysoev52859f22009-03-23 13:14:51 +00001018 u->resolved->host = url.host;
Igor Sysoev302cedc2008-12-23 19:35:12 +00001019 }
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001020
Ruslan Ermilov4a3c4792015-11-21 10:44:07 +03001021 u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
1022 u->resolved->no_port = url.no_port;
1023
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001024 return NGX_OK;
1025}
1026
1027
Igor Sysoev52859f22009-03-23 13:14:51 +00001028#if (NGX_HTTP_CACHE)
1029
1030static ngx_int_t
1031ngx_http_proxy_create_key(ngx_http_request_t *r)
1032{
1033 size_t len, loc_len;
1034 u_char *p;
1035 uintptr_t escape;
1036 ngx_str_t *key;
1037 ngx_http_upstream_t *u;
1038 ngx_http_proxy_ctx_t *ctx;
1039 ngx_http_proxy_loc_conf_t *plcf;
1040
1041 u = r->upstream;
1042
1043 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1044
1045 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1046
1047 key = ngx_array_push(&r->cache->keys);
1048 if (key == NULL) {
1049 return NGX_ERROR;
1050 }
1051
Ruslan Ermilov73fb7e82012-12-06 23:03:53 +00001052 if (plcf->cache_key.value.data) {
Igor Sysoev44a69c82009-04-06 08:58:44 +00001053
1054 if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
1055 return NGX_ERROR;
1056 }
1057
1058 return NGX_OK;
1059 }
1060
Igor Sysoev52859f22009-03-23 13:14:51 +00001061 *key = ctx->vars.key_start;
1062
1063 key = ngx_array_push(&r->cache->keys);
1064 if (key == NULL) {
1065 return NGX_ERROR;
1066 }
1067
Maxim Douninaa449262011-12-23 16:04:09 +00001068 if (plcf->proxy_lengths && ctx->vars.uri.len) {
Igor Sysoev52859f22009-03-23 13:14:51 +00001069
1070 *key = ctx->vars.uri;
1071 u->uri = ctx->vars.uri;
1072
1073 return NGX_OK;
1074
1075 } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
1076 {
1077 *key = r->unparsed_uri;
1078 u->uri = r->unparsed_uri;
1079
1080 return NGX_OK;
1081 }
1082
1083 loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
1084
1085 if (r->quoted_uri || r->internal) {
1086 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
1087 r->uri.len - loc_len, NGX_ESCAPE_URI);
1088 } else {
1089 escape = 0;
1090 }
1091
1092 len = ctx->vars.uri.len + r->uri.len - loc_len + escape
1093 + sizeof("?") - 1 + r->args.len;
1094
1095 p = ngx_pnalloc(r->pool, len);
1096 if (p == NULL) {
1097 return NGX_ERROR;
1098 }
1099
1100 key->data = p;
1101
1102 if (r->valid_location) {
1103 p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
1104 }
1105
1106 if (escape) {
1107 ngx_escape_uri(p, r->uri.data + loc_len,
1108 r->uri.len - loc_len, NGX_ESCAPE_URI);
1109 p += r->uri.len - loc_len + escape;
1110
1111 } else {
1112 p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
1113 }
1114
1115 if (r->args.len > 0) {
1116 *p++ = '?';
1117 p = ngx_copy(p, r->args.data, r->args.len);
1118 }
1119
1120 key->len = p - key->data;
1121 u->uri = *key;
1122
1123 return NGX_OK;
1124}
1125
1126#endif
1127
1128
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001129static ngx_int_t
Igor Sysoev02f742b2005-04-08 15:18:55 +00001130ngx_http_proxy_create_request(ngx_http_request_t *r)
1131{
Igor Sysoev52859f22009-03-23 13:14:51 +00001132 size_t len, uri_len, loc_len, body_len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001133 uintptr_t escape;
1134 ngx_buf_t *b;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001135 ngx_str_t method;
1136 ngx_uint_t i, unparsed_uri;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001137 ngx_chain_t *cl, *body;
1138 ngx_list_part_t *part;
1139 ngx_table_elt_t *header;
1140 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001141 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001142 ngx_http_script_code_pt code;
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001143 ngx_http_proxy_headers_t *headers;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001144 ngx_http_script_engine_t e, le;
1145 ngx_http_proxy_loc_conf_t *plcf;
1146 ngx_http_script_len_code_pt lcode;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001147
1148 u = r->upstream;
1149
1150 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1151
Roman Arutyunyan8898c972014-11-19 17:33:23 +03001152#if (NGX_HTTP_CACHE)
1153 headers = u->cacheable ? &plcf->headers_cache : &plcf->headers;
1154#else
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001155 headers = &plcf->headers;
Roman Arutyunyan8898c972014-11-19 17:33:23 +03001156#endif
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001157
Igor Sysoev78452232005-10-12 13:50:36 +00001158 if (u->method.len) {
1159 /* HEAD was changed to GET to cache response */
1160 method = u->method;
Igor Sysoev78452232005-10-12 13:50:36 +00001161
1162 } else if (plcf->method.len) {
1163 method = plcf->method;
1164
Igor Sysoev02f742b2005-04-08 15:18:55 +00001165 } else {
Igor Sysoev78452232005-10-12 13:50:36 +00001166 method = r->method_name;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001167 }
1168
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001169 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1170
Ruslan Ermilov64f528a2015-11-06 15:21:51 +03001171 if (method.len == 4
1172 && ngx_strncasecmp(method.data, (u_char *) "HEAD", 4) == 0)
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001173 {
1174 ctx->head = 1;
1175 }
1176
Ruslan Ermilov64f528a2015-11-06 15:21:51 +03001177 len = method.len + 1 + sizeof(ngx_http_proxy_version) - 1
1178 + sizeof(CRLF) - 1;
Igor Sysoevfa626562007-11-28 15:06:05 +00001179
Igor Sysoev02f742b2005-04-08 15:18:55 +00001180 escape = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001181 loc_len = 0;
1182 unparsed_uri = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001183
Maxim Douninaa449262011-12-23 16:04:09 +00001184 if (plcf->proxy_lengths && ctx->vars.uri.len) {
Igor Sysoev52859f22009-03-23 13:14:51 +00001185 uri_len = ctx->vars.uri.len;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001186
1187 } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
1188 {
Igor Sysoev8290d282006-02-03 12:58:48 +00001189 unparsed_uri = 1;
Igor Sysoev52859f22009-03-23 13:14:51 +00001190 uri_len = r->unparsed_uri.len;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001191
1192 } else {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001193 loc_len = (r->valid_location && ctx->vars.uri.len) ?
1194 plcf->location.len : 0;
1195
Igor Sysoevda7b5e12010-06-15 09:31:19 +00001196 if (r->quoted_uri || r->space_in_uri || r->internal) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001197 escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
1198 r->uri.len - loc_len, NGX_ESCAPE_URI);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001199 }
1200
Igor Sysoev52859f22009-03-23 13:14:51 +00001201 uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
1202 + sizeof("?") - 1 + r->args.len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001203 }
1204
Igor Sysoev52859f22009-03-23 13:14:51 +00001205 if (uri_len == 0) {
1206 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1207 "zero length URI to proxy");
1208 return NGX_ERROR;
1209 }
1210
1211 len += uri_len;
1212
Maxim Dounin330ebdc2013-05-15 12:23:44 +04001213 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1214
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001215 ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
1216 ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
Igor Sysoev09c684b2005-11-09 17:25:55 +00001217
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03001218 if (plcf->body_lengths) {
1219 le.ip = plcf->body_lengths->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001220 le.request = r;
1221 le.flushed = 1;
1222 body_len = 0;
1223
1224 while (*(uintptr_t *) le.ip) {
1225 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1226 body_len += lcode(&le);
1227 }
1228
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001229 ctx->internal_body_length = body_len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001230 len += body_len;
Maxim Dounin9a483c82012-11-21 01:03:48 +00001231
Maxim Dounin55344dd2015-03-23 21:09:19 +03001232 } else if (r->headers_in.chunked && r->reading_body) {
1233 ctx->internal_body_length = -1;
1234 ctx->internal_chunked = 1;
1235
Maxim Dounin9a483c82012-11-21 01:03:48 +00001236 } else {
1237 ctx->internal_body_length = r->headers_in.content_length_n;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001238 }
1239
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001240 le.ip = headers->lengths->elts;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001241 le.request = r;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001242 le.flushed = 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001243
1244 while (*(uintptr_t *) le.ip) {
1245 while (*(uintptr_t *) le.ip) {
1246 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1247 len += lcode(&le);
1248 }
1249 le.ip += sizeof(uintptr_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001250 }
1251
1252
Igor Sysoev899b44e2005-05-12 14:58:06 +00001253 if (plcf->upstream.pass_request_headers) {
1254 part = &r->headers_in.headers.part;
1255 header = part->elts;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001256
Igor Sysoev899b44e2005-05-12 14:58:06 +00001257 for (i = 0; /* void */; i++) {
1258
1259 if (i >= part->nelts) {
1260 if (part->next == NULL) {
1261 break;
1262 }
1263
1264 part = part->next;
1265 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001266 i = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001267 }
1268
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001269 if (ngx_hash_find(&headers->hash, header[i].hash,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001270 header[i].lowcase_key, header[i].key.len))
Igor Sysoev899b44e2005-05-12 14:58:06 +00001271 {
1272 continue;
1273 }
1274
1275 len += header[i].key.len + sizeof(": ") - 1
1276 + header[i].value.len + sizeof(CRLF) - 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001277 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001278 }
1279
Igor Sysoev899b44e2005-05-12 14:58:06 +00001280
Igor Sysoev02f742b2005-04-08 15:18:55 +00001281 b = ngx_create_temp_buf(r->pool, len);
1282 if (b == NULL) {
1283 return NGX_ERROR;
1284 }
1285
1286 cl = ngx_alloc_chain_link(r->pool);
1287 if (cl == NULL) {
1288 return NGX_ERROR;
1289 }
1290
1291 cl->buf = b;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001292
1293
1294 /* the request line */
1295
Igor Sysoev09c684b2005-11-09 17:25:55 +00001296 b->last = ngx_copy(b->last, method.data, method.len);
Ruslan Ermilov64f528a2015-11-06 15:21:51 +03001297 *b->last++ = ' ';
Igor Sysoev02f742b2005-04-08 15:18:55 +00001298
Igor Sysoeva2573672005-10-05 14:46:21 +00001299 u->uri.data = b->last;
1300
Maxim Douninaa449262011-12-23 16:04:09 +00001301 if (plcf->proxy_lengths && ctx->vars.uri.len) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001302 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
1303
1304 } else if (unparsed_uri) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00001305 b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
1306
Igor Sysoev02f742b2005-04-08 15:18:55 +00001307 } else {
Igor Sysoeva2573672005-10-05 14:46:21 +00001308 if (r->valid_location) {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001309 b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
Igor Sysoeva2573672005-10-05 14:46:21 +00001310 }
Igor Sysoev82dc95e2005-10-03 12:53:14 +00001311
Igor Sysoev02f742b2005-04-08 15:18:55 +00001312 if (escape) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001313 ngx_escape_uri(b->last, r->uri.data + loc_len,
1314 r->uri.len - loc_len, NGX_ESCAPE_URI);
1315 b->last += r->uri.len - loc_len + escape;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001316
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001317 } else {
Igor Sysoev09c684b2005-11-09 17:25:55 +00001318 b->last = ngx_copy(b->last, r->uri.data + loc_len,
1319 r->uri.len - loc_len);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001320 }
1321
1322 if (r->args.len > 0) {
1323 *b->last++ = '?';
Igor Sysoev09c684b2005-11-09 17:25:55 +00001324 b->last = ngx_copy(b->last, r->args.data, r->args.len);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001325 }
1326 }
1327
Igor Sysoeva2573672005-10-05 14:46:21 +00001328 u->uri.len = b->last - u->uri.data;
1329
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001330 if (plcf->http_version == NGX_HTTP_VERSION_11) {
1331 b->last = ngx_cpymem(b->last, ngx_http_proxy_version_11,
1332 sizeof(ngx_http_proxy_version_11) - 1);
1333
1334 } else {
1335 b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
1336 sizeof(ngx_http_proxy_version) - 1);
1337 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001338
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001339 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
Igor Sysoev02f742b2005-04-08 15:18:55 +00001340
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001341 e.ip = headers->values->elts;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001342 e.pos = b->last;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001343 e.request = r;
Igor Sysoev09c684b2005-11-09 17:25:55 +00001344 e.flushed = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001345
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001346 le.ip = headers->lengths->elts;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001347
1348 while (*(uintptr_t *) le.ip) {
1349 lcode = *(ngx_http_script_len_code_pt *) le.ip;
Igor Sysoeve31e90b2005-05-19 13:25:22 +00001350
1351 /* skip the header line name length */
1352 (void) lcode(&le);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001353
1354 if (*(ngx_http_script_len_code_pt *) le.ip) {
1355
1356 for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
1357 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1358 }
1359
1360 e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0;
1361
1362 } else {
1363 e.skip = 0;
1364 }
1365
1366 le.ip += sizeof(uintptr_t);
1367
1368 while (*(uintptr_t *) e.ip) {
1369 code = *(ngx_http_script_code_pt *) e.ip;
1370 code((ngx_http_script_engine_t *) &e);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001371 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001372 e.ip += sizeof(uintptr_t);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001373 }
1374
1375 b->last = e.pos;
1376
1377
Igor Sysoev899b44e2005-05-12 14:58:06 +00001378 if (plcf->upstream.pass_request_headers) {
1379 part = &r->headers_in.headers.part;
1380 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001381
Igor Sysoev899b44e2005-05-12 14:58:06 +00001382 for (i = 0; /* void */; i++) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00001383
Igor Sysoev899b44e2005-05-12 14:58:06 +00001384 if (i >= part->nelts) {
1385 if (part->next == NULL) {
1386 break;
1387 }
1388
1389 part = part->next;
1390 header = part->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001391 i = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001392 }
1393
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03001394 if (ngx_hash_find(&headers->hash, header[i].hash,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001395 header[i].lowcase_key, header[i].key.len))
Igor Sysoev899b44e2005-05-12 14:58:06 +00001396 {
1397 continue;
1398 }
1399
Igor Sysoev09c684b2005-11-09 17:25:55 +00001400 b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001401
1402 *b->last++ = ':'; *b->last++ = ' ';
1403
Igor Sysoev09c684b2005-11-09 17:25:55 +00001404 b->last = ngx_copy(b->last, header[i].value.data,
1405 header[i].value.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001406
1407 *b->last++ = CR; *b->last++ = LF;
1408
1409 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1410 "http proxy header: \"%V: %V\"",
1411 &header[i].key, &header[i].value);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001412 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001413 }
1414
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001415
Igor Sysoev02f742b2005-04-08 15:18:55 +00001416 /* add "\r\n" at the header end */
1417 *b->last++ = CR; *b->last++ = LF;
1418
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03001419 if (plcf->body_values) {
1420 e.ip = plcf->body_values->elts;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001421 e.pos = b->last;
Maxim Douninabf40d02015-03-23 19:28:54 +03001422 e.skip = 0;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001423
1424 while (*(uintptr_t *) e.ip) {
1425 code = *(ngx_http_script_code_pt *) e.ip;
1426 code((ngx_http_script_engine_t *) &e);
1427 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001428
Igor Sysoevb141f2b2005-11-15 14:49:57 +00001429 b->last = e.pos;
1430 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001431
Igor Sysoevd02661a2007-12-24 17:05:31 +00001432 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Ruslan Ermilov5a3d4412014-05-14 22:26:30 +04001433 "http proxy header:%N\"%*s\"",
Igor Sysoevd02661a2007-12-24 17:05:31 +00001434 (size_t) (b->last - b->pos), b->pos);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001435
Maxim Douninf568ff82015-03-23 21:09:19 +03001436 if (r->request_body_no_buffering) {
1437
1438 u->request_bufs = cl;
1439
Maxim Dounin55344dd2015-03-23 21:09:19 +03001440 if (ctx->internal_chunked) {
1441 u->output.output_filter = ngx_http_proxy_body_output_filter;
1442 u->output.filter_ctx = r;
1443 }
1444
Maxim Douninf568ff82015-03-23 21:09:19 +03001445 } else if (plcf->body_values == NULL && plcf->upstream.pass_request_body) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001446
1447 body = u->request_bufs;
1448 u->request_bufs = cl;
1449
1450 while (body) {
1451 b = ngx_alloc_buf(r->pool);
1452 if (b == NULL) {
1453 return NGX_ERROR;
1454 }
1455
1456 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
1457
1458 cl->next = ngx_alloc_chain_link(r->pool);
1459 if (cl->next == NULL) {
1460 return NGX_ERROR;
1461 }
1462
1463 cl = cl->next;
1464 cl->buf = b;
1465
1466 body = body->next;
1467 }
1468
1469 } else {
1470 u->request_bufs = cl;
1471 }
1472
Maxim Dounin9bc8fc42011-08-18 16:34:24 +00001473 b->flush = 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001474 cl->next = NULL;
1475
Igor Sysoev02f742b2005-04-08 15:18:55 +00001476 return NGX_OK;
1477}
1478
1479
1480static ngx_int_t
1481ngx_http_proxy_reinit_request(ngx_http_request_t *r)
1482{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001483 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001484
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001485 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001486
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001487 if (ctx == NULL) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001488 return NGX_OK;
1489 }
1490
Igor Sysoev54b35b02010-06-15 15:15:06 +00001491 ctx->status.code = 0;
1492 ctx->status.count = 0;
1493 ctx->status.start = NULL;
1494 ctx->status.end = NULL;
Maxim Dounindf74d882012-11-21 00:59:16 +00001495 ctx->chunked.state = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001496
1497 r->upstream->process_header = ngx_http_proxy_process_status_line;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001498 r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
1499 r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter;
Igor Sysoevaed1ac12010-03-25 13:27:52 +00001500 r->state = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001501
1502 return NGX_OK;
1503}
1504
1505
1506static ngx_int_t
Maxim Dounin55344dd2015-03-23 21:09:19 +03001507ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in)
1508{
1509 ngx_http_request_t *r = data;
1510
1511 off_t size;
1512 u_char *chunk;
1513 ngx_int_t rc;
1514 ngx_buf_t *b;
Maxim Douninb89196a2015-03-26 02:31:30 +03001515 ngx_chain_t *out, *cl, *tl, **ll, **fl;
Maxim Dounin55344dd2015-03-23 21:09:19 +03001516 ngx_http_proxy_ctx_t *ctx;
1517
1518 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1519 "proxy output filter");
1520
1521 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1522
1523 if (in == NULL) {
1524 out = in;
1525 goto out;
1526 }
1527
1528 out = NULL;
1529 ll = &out;
1530
1531 if (!ctx->header_sent) {
1532 /* first buffer contains headers, pass it unmodified */
1533
1534 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1535 "proxy output header");
1536
1537 ctx->header_sent = 1;
1538
1539 tl = ngx_alloc_chain_link(r->pool);
1540 if (tl == NULL) {
1541 return NGX_ERROR;
1542 }
1543
1544 tl->buf = in->buf;
1545 *ll = tl;
1546 ll = &tl->next;
1547
1548 in = in->next;
1549
1550 if (in == NULL) {
1551 tl->next = NULL;
1552 goto out;
1553 }
1554 }
1555
1556 size = 0;
1557 cl = in;
Maxim Douninb89196a2015-03-26 02:31:30 +03001558 fl = ll;
Maxim Dounin55344dd2015-03-23 21:09:19 +03001559
1560 for ( ;; ) {
1561 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Sergey Kandaurovb7687bb2016-03-31 02:33:57 +03001562 "proxy output chunk: %O", ngx_buf_size(cl->buf));
Maxim Dounin55344dd2015-03-23 21:09:19 +03001563
1564 size += ngx_buf_size(cl->buf);
1565
1566 if (cl->buf->flush
1567 || cl->buf->sync
1568 || ngx_buf_in_memory(cl->buf)
1569 || cl->buf->in_file)
1570 {
1571 tl = ngx_alloc_chain_link(r->pool);
1572 if (tl == NULL) {
1573 return NGX_ERROR;
1574 }
1575
1576 tl->buf = cl->buf;
1577 *ll = tl;
1578 ll = &tl->next;
1579 }
1580
1581 if (cl->next == NULL) {
1582 break;
1583 }
1584
1585 cl = cl->next;
1586 }
1587
1588 if (size) {
1589 tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1590 if (tl == NULL) {
1591 return NGX_ERROR;
1592 }
1593
1594 b = tl->buf;
1595 chunk = b->start;
1596
1597 if (chunk == NULL) {
1598 /* the "0000000000000000" is 64-bit hexadecimal string */
1599
1600 chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
1601 if (chunk == NULL) {
1602 return NGX_ERROR;
1603 }
1604
1605 b->start = chunk;
1606 b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
1607 }
1608
1609 b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1610 b->memory = 0;
1611 b->temporary = 1;
1612 b->pos = chunk;
1613 b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
1614
Maxim Douninb89196a2015-03-26 02:31:30 +03001615 tl->next = *fl;
1616 *fl = tl;
Maxim Dounin55344dd2015-03-23 21:09:19 +03001617 }
1618
1619 if (cl->buf->last_buf) {
1620 tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1621 if (tl == NULL) {
1622 return NGX_ERROR;
1623 }
1624
1625 b = tl->buf;
1626
1627 b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1628 b->temporary = 0;
1629 b->memory = 1;
1630 b->last_buf = 1;
1631 b->pos = (u_char *) CRLF "0" CRLF CRLF;
1632 b->last = b->pos + 7;
1633
1634 cl->buf->last_buf = 0;
1635
1636 *ll = tl;
1637
1638 if (size == 0) {
1639 b->pos += 2;
1640 }
1641
1642 } else if (size > 0) {
1643 tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1644 if (tl == NULL) {
1645 return NGX_ERROR;
1646 }
1647
1648 b = tl->buf;
1649
1650 b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1651 b->temporary = 0;
1652 b->memory = 1;
1653 b->pos = (u_char *) CRLF;
1654 b->last = b->pos + 2;
1655
1656 *ll = tl;
1657
1658 } else {
1659 *ll = NULL;
1660 }
1661
1662out:
1663
1664 rc = ngx_chain_writer(&r->upstream->writer, out);
1665
1666 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
1667 (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter);
1668
1669 return rc;
1670}
1671
1672
1673static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001674ngx_http_proxy_process_status_line(ngx_http_request_t *r)
1675{
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001676 size_t len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001677 ngx_int_t rc;
1678 ngx_http_upstream_t *u;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001679 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001680
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001681 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001682
Igor Sysoev96dd8af2007-11-27 13:34:13 +00001683 if (ctx == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001684 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001685 }
1686
Igor Sysoev54b35b02010-06-15 15:15:06 +00001687 u = r->upstream;
1688
1689 rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001690
1691 if (rc == NGX_AGAIN) {
1692 return rc;
1693 }
1694
Igor Sysoev54b35b02010-06-15 15:15:06 +00001695 if (rc == NGX_ERROR) {
Igor Sysoev52859f22009-03-23 13:14:51 +00001696
1697#if (NGX_HTTP_CACHE)
1698
1699 if (r->cache) {
1700 r->http_version = NGX_HTTP_VERSION_9;
Igor Sysoev52859f22009-03-23 13:14:51 +00001701 return NGX_OK;
1702 }
1703
1704#endif
1705
Igor Sysoev899b44e2005-05-12 14:58:06 +00001706 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001707 "upstream sent no valid HTTP/1.0 header");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001708
Igor Sysoev13c68742006-03-10 12:51:52 +00001709#if 0
Igor Sysoev899b44e2005-05-12 14:58:06 +00001710 if (u->accel) {
1711 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1712 }
Igor Sysoev13c68742006-03-10 12:51:52 +00001713#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +00001714
1715 r->http_version = NGX_HTTP_VERSION_9;
Igor Sysoevd7cf1a62007-11-06 15:01:13 +00001716 u->state->status = NGX_HTTP_OK;
Maxim Douninf2fcf112011-09-15 19:22:35 +00001717 u->headers_in.connection_close = 1;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001718
Igor Sysoev899b44e2005-05-12 14:58:06 +00001719 return NGX_OK;
1720 }
1721
Piotr Sikora60d508c2014-02-11 21:54:42 -08001722 if (u->state && u->state->status == 0) {
Igor Sysoev54b35b02010-06-15 15:15:06 +00001723 u->state->status = ctx->status.code;
Igor Sysoev52859f22009-03-23 13:14:51 +00001724 }
1725
Igor Sysoev54b35b02010-06-15 15:15:06 +00001726 u->headers_in.status_n = ctx->status.code;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001727
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001728 len = ctx->status.end - ctx->status.start;
1729 u->headers_in.status_line.len = len;
1730
1731 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
Igor Sysoev187b7d92005-07-14 12:51:53 +00001732 if (u->headers_in.status_line.data == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001733 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001734 }
Igor Sysoev09c684b2005-11-09 17:25:55 +00001735
Igor Sysoev1cc1b312010-06-15 15:21:37 +00001736 ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001737
1738 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1739 "http proxy status %ui \"%V\"",
Igor Sysoev4e08b9c2006-12-20 19:38:06 +00001740 u->headers_in.status_n, &u->headers_in.status_line);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001741
Maxim Douninf2fcf112011-09-15 19:22:35 +00001742 if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
1743 u->headers_in.connection_close = 1;
1744 }
1745
Igor Sysoev899b44e2005-05-12 14:58:06 +00001746 u->process_header = ngx_http_proxy_process_header;
1747
1748 return ngx_http_proxy_process_header(r);
1749}
1750
1751
1752static ngx_int_t
Igor Sysoev02f742b2005-04-08 15:18:55 +00001753ngx_http_proxy_process_header(ngx_http_request_t *r)
1754{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001755 ngx_int_t rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001756 ngx_table_elt_t *h;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001757 ngx_http_upstream_t *u;
1758 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001759 ngx_http_upstream_header_t *hh;
1760 ngx_http_upstream_main_conf_t *umcf;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001761
Igor Sysoev899b44e2005-05-12 14:58:06 +00001762 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +00001763
Igor Sysoev3b304762008-05-22 12:09:41 +00001764 for ( ;; ) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001765
Igor Sysoev753792e2008-09-24 14:02:50 +00001766 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001767
1768 if (rc == NGX_OK) {
1769
1770 /* a header line has been parsed successfully */
1771
1772 h = ngx_list_push(&r->upstream->headers_in.headers);
1773 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001774 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001775 }
1776
1777 h->hash = r->header_hash;
1778
1779 h->key.len = r->header_name_end - r->header_name_start;
1780 h->value.len = r->header_end - r->header_start;
1781
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001782 h->key.data = ngx_pnalloc(r->pool,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001783 h->key.len + 1 + h->value.len + 1 + h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001784 if (h->key.data == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001785 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001786 }
1787
1788 h->value.data = h->key.data + h->key.len + 1;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001789 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001790
Maxim Dounineb526b72012-03-15 11:27:12 +00001791 ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
1792 h->key.data[h->key.len] = '\0';
1793 ngx_memcpy(h->value.data, r->header_start, h->value.len);
1794 h->value.data[h->value.len] = '\0';
Igor Sysoev899b44e2005-05-12 14:58:06 +00001795
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001796 if (h->key.len == r->lowcase_index) {
1797 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001798
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001799 } else {
Igor Sysoev777b0192008-08-04 10:07:00 +00001800 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001801 }
1802
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001803 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
1804 h->lowcase_key, h->key.len);
1805
1806 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001807 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001808 }
1809
Igor Sysoev899b44e2005-05-12 14:58:06 +00001810 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1811 "http proxy header: \"%V: %V\"",
1812 &h->key, &h->value);
1813
1814 continue;
1815 }
1816
1817 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1818
1819 /* a whole header has been parsed successfully */
1820
1821 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1822 "http proxy header done");
1823
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001824 /*
1825 * if no "Server" and "Date" in header line,
1826 * then add the special empty headers
1827 */
1828
1829 if (r->upstream->headers_in.server == NULL) {
1830 h = ngx_list_push(&r->upstream->headers_in.headers);
1831 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001832 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001833 }
1834
1835 h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
1836 ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
1837
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001838 ngx_str_set(&h->key, "Server");
1839 ngx_str_null(&h->value);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001840 h->lowcase_key = (u_char *) "server";
1841 }
1842
1843 if (r->upstream->headers_in.date == NULL) {
1844 h = ngx_list_push(&r->upstream->headers_in.headers);
1845 if (h == NULL) {
Igor Sysoev5a55d712007-12-09 08:22:35 +00001846 return NGX_ERROR;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001847 }
1848
1849 h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
1850
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00001851 ngx_str_set(&h->key, "Date");
1852 ngx_str_null(&h->value);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001853 h->lowcase_key = (u_char *) "date";
1854 }
1855
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001856 /* clear content length if response is chunked */
1857
1858 u = r->upstream;
1859
1860 if (u->headers_in.chunked) {
1861 u->headers_in.content_length_n = -1;
1862 }
1863
1864 /*
1865 * set u->keepalive if response has no body; this allows to keep
1866 * connections alive in case of r->header_only or X-Accel-Redirect
1867 */
1868
1869 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1870
1871 if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1872 || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1873 || ctx->head
1874 || (!u->headers_in.chunked
1875 && u->headers_in.content_length_n == 0))
1876 {
1877 u->keepalive = !u->headers_in.connection_close;
1878 }
1879
Maxim Dounin08a73b42013-02-18 13:50:52 +00001880 if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS) {
1881 u->keepalive = 0;
1882
1883 if (r->headers_in.upgrade) {
1884 u->upgrade = 1;
1885 }
1886 }
1887
Igor Sysoev899b44e2005-05-12 14:58:06 +00001888 return NGX_OK;
1889 }
1890
Igor Sysoev7b190b42005-06-07 15:56:31 +00001891 if (rc == NGX_AGAIN) {
1892 return NGX_AGAIN;
1893 }
1894
Igor Sysoev899b44e2005-05-12 14:58:06 +00001895 /* there was error while a header line parsing */
1896
1897 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev13c68742006-03-10 12:51:52 +00001898 "upstream sent invalid header");
Igor Sysoev899b44e2005-05-12 14:58:06 +00001899
1900 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1901 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00001902}
1903
1904
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001905static ngx_int_t
1906ngx_http_proxy_input_filter_init(void *data)
1907{
1908 ngx_http_request_t *r = data;
1909 ngx_http_upstream_t *u;
1910 ngx_http_proxy_ctx_t *ctx;
1911
1912 u = r->upstream;
1913 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1914
Maxim Douninc7bb1622012-04-23 10:40:01 +00001915 if (ctx == NULL) {
1916 return NGX_ERROR;
1917 }
1918
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001919 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Sergey Kandaurovb7687bb2016-03-31 02:33:57 +03001920 "http proxy filter init s:%ui h:%d c:%d l:%O",
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001921 u->headers_in.status_n, ctx->head, u->headers_in.chunked,
1922 u->headers_in.content_length_n);
1923
1924 /* as per RFC2616, 4.4 Message Length */
1925
1926 if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1927 || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1928 || ctx->head)
1929 {
1930 /* 1xx, 204, and 304 and replies to HEAD requests */
1931 /* no 1xx since we don't send Expect and Upgrade */
1932
1933 u->pipe->length = 0;
1934 u->length = 0;
1935 u->keepalive = !u->headers_in.connection_close;
1936
1937 } else if (u->headers_in.chunked) {
1938 /* chunked */
1939
1940 u->pipe->input_filter = ngx_http_proxy_chunked_filter;
1941 u->pipe->length = 3; /* "0" LF LF */
1942
1943 u->input_filter = ngx_http_proxy_non_buffered_chunked_filter;
Maxim Dounin960d0bf2013-07-25 15:00:12 +04001944 u->length = 1;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001945
1946 } else if (u->headers_in.content_length_n == 0) {
1947 /* empty body: special case as filter won't be called */
1948
1949 u->pipe->length = 0;
1950 u->length = 0;
1951 u->keepalive = !u->headers_in.connection_close;
1952
1953 } else {
1954 /* content length or connection close */
1955
1956 u->pipe->length = u->headers_in.content_length_n;
1957 u->length = u->headers_in.content_length_n;
1958 }
1959
1960 return NGX_OK;
1961}
1962
1963
1964static ngx_int_t
1965ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1966{
1967 ngx_buf_t *b;
1968 ngx_chain_t *cl;
1969 ngx_http_request_t *r;
1970
1971 if (buf->pos == buf->last) {
1972 return NGX_OK;
1973 }
1974
Valentin Bartenev25765302013-12-11 21:30:38 +04001975 cl = ngx_chain_get_free_buf(p->pool, &p->free);
1976 if (cl == NULL) {
1977 return NGX_ERROR;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001978 }
1979
Valentin Bartenev25765302013-12-11 21:30:38 +04001980 b = cl->buf;
1981
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001982 ngx_memcpy(b, buf, sizeof(ngx_buf_t));
1983 b->shadow = buf;
1984 b->tag = p->tag;
1985 b->last_shadow = 1;
1986 b->recycled = 1;
1987 buf->shadow = b;
1988
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00001989 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
1990
1991 if (p->in) {
1992 *p->last_in = cl;
1993 } else {
1994 p->in = cl;
1995 }
1996 p->last_in = &cl->next;
1997
1998 if (p->length == -1) {
1999 return NGX_OK;
2000 }
2001
2002 p->length -= b->last - b->pos;
2003
2004 if (p->length == 0) {
2005 r = p->input_ctx;
2006 p->upstream_done = 1;
2007 r->upstream->keepalive = !r->upstream->headers_in.connection_close;
2008
2009 } else if (p->length < 0) {
2010 r = p->input_ctx;
2011 p->upstream_done = 1;
2012
Maxim Dounin5c56f202011-09-25 20:04:20 +00002013 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
Maxim Douninb3430992012-12-13 13:45:39 +00002014 "upstream sent more data than specified in "
2015 "\"Content-Length\" header");
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002016 }
2017
2018 return NGX_OK;
2019}
2020
2021
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002022static ngx_int_t
2023ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
2024{
2025 ngx_int_t rc;
2026 ngx_buf_t *b, **prev;
2027 ngx_chain_t *cl;
2028 ngx_http_request_t *r;
2029 ngx_http_proxy_ctx_t *ctx;
2030
2031 if (buf->pos == buf->last) {
2032 return NGX_OK;
2033 }
2034
2035 r = p->input_ctx;
2036 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2037
Maxim Douninc7bb1622012-04-23 10:40:01 +00002038 if (ctx == NULL) {
2039 return NGX_ERROR;
2040 }
2041
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002042 b = NULL;
2043 prev = &buf->shadow;
2044
2045 for ( ;; ) {
2046
Maxim Dounindf74d882012-11-21 00:59:16 +00002047 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002048
2049 if (rc == NGX_OK) {
2050
2051 /* a chunk has been parsed successfully */
2052
Valentin Bartenev25765302013-12-11 21:30:38 +04002053 cl = ngx_chain_get_free_buf(p->pool, &p->free);
2054 if (cl == NULL) {
2055 return NGX_ERROR;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002056 }
2057
Valentin Bartenev25765302013-12-11 21:30:38 +04002058 b = cl->buf;
2059
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002060 ngx_memzero(b, sizeof(ngx_buf_t));
2061
2062 b->pos = buf->pos;
2063 b->start = buf->start;
2064 b->end = buf->end;
2065 b->tag = p->tag;
2066 b->temporary = 1;
2067 b->recycled = 1;
2068
2069 *prev = b;
2070 prev = &b->shadow;
2071
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002072 if (p->in) {
2073 *p->last_in = cl;
2074 } else {
2075 p->in = cl;
2076 }
2077 p->last_in = &cl->next;
2078
2079 /* STUB */ b->num = buf->num;
2080
2081 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
2082 "input buf #%d %p", b->num, b->pos);
2083
Maxim Dounindf74d882012-11-21 00:59:16 +00002084 if (buf->last - buf->pos >= ctx->chunked.size) {
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002085
Maxim Dounin74b7a912013-09-04 20:48:23 +04002086 buf->pos += (size_t) ctx->chunked.size;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002087 b->last = buf->pos;
Maxim Dounindf74d882012-11-21 00:59:16 +00002088 ctx->chunked.size = 0;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002089
2090 continue;
2091 }
2092
Maxim Dounindf74d882012-11-21 00:59:16 +00002093 ctx->chunked.size -= buf->last - buf->pos;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002094 buf->pos = buf->last;
2095 b->last = buf->last;
2096
2097 continue;
2098 }
2099
2100 if (rc == NGX_DONE) {
2101
2102 /* a whole response has been parsed successfully */
2103
2104 p->upstream_done = 1;
2105 r->upstream->keepalive = !r->upstream->headers_in.connection_close;
2106
2107 break;
2108 }
2109
2110 if (rc == NGX_AGAIN) {
2111
2112 /* set p->length, minimal amount of data we want to see */
2113
Maxim Dounindf74d882012-11-21 00:59:16 +00002114 p->length = ctx->chunked.length;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002115
2116 break;
2117 }
2118
2119 /* invalid response */
2120
Maxim Dounin5c56f202011-09-25 20:04:20 +00002121 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002122 "upstream sent invalid chunked response");
2123
2124 return NGX_ERROR;
2125 }
2126
2127 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Sergey Kandaurovb7687bb2016-03-31 02:33:57 +03002128 "http proxy chunked state %ui, length %O",
Maxim Dounindf74d882012-11-21 00:59:16 +00002129 ctx->chunked.state, p->length);
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002130
2131 if (b) {
2132 b->shadow = buf;
2133 b->last_shadow = 1;
2134
2135 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
2136 "input buf %p %z", b->pos, b->last - b->pos);
2137
2138 return NGX_OK;
2139 }
2140
2141 /* there is no data record in the buf, add it to free chain */
2142
2143 if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
2144 return NGX_ERROR;
2145 }
2146
2147 return NGX_OK;
2148}
2149
2150
2151static ngx_int_t
2152ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
2153{
2154 ngx_http_request_t *r = data;
2155
2156 ngx_buf_t *b;
2157 ngx_chain_t *cl, **ll;
2158 ngx_http_upstream_t *u;
2159
2160 u = r->upstream;
2161
2162 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2163 ll = &cl->next;
2164 }
2165
2166 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2167 if (cl == NULL) {
2168 return NGX_ERROR;
2169 }
2170
2171 *ll = cl;
2172
2173 cl->buf->flush = 1;
2174 cl->buf->memory = 1;
2175
2176 b = &u->buffer;
2177
2178 cl->buf->pos = b->last;
2179 b->last += bytes;
2180 cl->buf->last = b->last;
2181 cl->buf->tag = u->output.tag;
2182
2183 if (u->length == -1) {
2184 return NGX_OK;
2185 }
2186
2187 u->length -= bytes;
2188
2189 if (u->length == 0) {
2190 u->keepalive = !u->headers_in.connection_close;
2191 }
2192
2193 return NGX_OK;
2194}
2195
2196
2197static ngx_int_t
2198ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
2199{
2200 ngx_http_request_t *r = data;
2201
2202 ngx_int_t rc;
2203 ngx_buf_t *b, *buf;
2204 ngx_chain_t *cl, **ll;
2205 ngx_http_upstream_t *u;
2206 ngx_http_proxy_ctx_t *ctx;
2207
2208 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Maxim Douninc7bb1622012-04-23 10:40:01 +00002209
2210 if (ctx == NULL) {
2211 return NGX_ERROR;
2212 }
2213
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002214 u = r->upstream;
2215 buf = &u->buffer;
2216
2217 buf->pos = buf->last;
2218 buf->last += bytes;
2219
2220 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2221 ll = &cl->next;
2222 }
2223
2224 for ( ;; ) {
2225
Maxim Dounindf74d882012-11-21 00:59:16 +00002226 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002227
2228 if (rc == NGX_OK) {
2229
2230 /* a chunk has been parsed successfully */
2231
2232 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2233 if (cl == NULL) {
2234 return NGX_ERROR;
2235 }
2236
2237 *ll = cl;
2238 ll = &cl->next;
2239
2240 b = cl->buf;
2241
2242 b->flush = 1;
2243 b->memory = 1;
2244
2245 b->pos = buf->pos;
2246 b->tag = u->output.tag;
2247
Maxim Dounindf74d882012-11-21 00:59:16 +00002248 if (buf->last - buf->pos >= ctx->chunked.size) {
Maxim Dounin74b7a912013-09-04 20:48:23 +04002249 buf->pos += (size_t) ctx->chunked.size;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002250 b->last = buf->pos;
Maxim Dounindf74d882012-11-21 00:59:16 +00002251 ctx->chunked.size = 0;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002252
2253 } else {
Maxim Dounindf74d882012-11-21 00:59:16 +00002254 ctx->chunked.size -= buf->last - buf->pos;
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002255 buf->pos = buf->last;
2256 b->last = buf->last;
2257 }
2258
2259 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2260 "http proxy out buf %p %z",
2261 b->pos, b->last - b->pos);
2262
2263 continue;
2264 }
2265
2266 if (rc == NGX_DONE) {
2267
2268 /* a whole response has been parsed successfully */
2269
2270 u->keepalive = !u->headers_in.connection_close;
2271 u->length = 0;
2272
2273 break;
2274 }
2275
2276 if (rc == NGX_AGAIN) {
2277 break;
2278 }
2279
2280 /* invalid response */
2281
Maxim Dounin5c56f202011-09-25 20:04:20 +00002282 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002283 "upstream sent invalid chunked response");
2284
2285 return NGX_ERROR;
2286 }
2287
2288 /* provide continuous buffer for subrequests in memory */
2289
2290 if (r->subrequest_in_memory) {
2291
2292 cl = u->out_bufs;
2293
2294 if (cl) {
2295 buf->pos = cl->buf->pos;
2296 }
2297
2298 buf->last = buf->pos;
2299
2300 for (cl = u->out_bufs; cl; cl = cl->next) {
2301 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Sergey Kandaurovb7687bb2016-03-31 02:33:57 +03002302 "http proxy in memory %p-%p %O",
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002303 cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf));
2304
2305 if (buf->last == cl->buf->pos) {
2306 buf->last = cl->buf->last;
2307 continue;
2308 }
2309
2310 buf->last = ngx_movemem(buf->last, cl->buf->pos,
2311 cl->buf->last - cl->buf->pos);
2312
2313 cl->buf->pos = buf->last - (cl->buf->last - cl->buf->pos);
2314 cl->buf->last = buf->last;
2315 }
2316 }
2317
2318 return NGX_OK;
2319}
2320
2321
Igor Sysoev02f742b2005-04-08 15:18:55 +00002322static void
2323ngx_http_proxy_abort_request(ngx_http_request_t *r)
2324{
2325 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2326 "abort http proxy request");
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002327
Igor Sysoev02f742b2005-04-08 15:18:55 +00002328 return;
2329}
2330
2331
2332static void
2333ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002334{
Igor Sysoev02f742b2005-04-08 15:18:55 +00002335 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2336 "finalize http proxy request");
2337
2338 return;
2339}
2340
2341
Igor Sysoev09c684b2005-11-09 17:25:55 +00002342static ngx_int_t
2343ngx_http_proxy_host_variable(ngx_http_request_t *r,
2344 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev02f742b2005-04-08 15:18:55 +00002345{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002346 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002347
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002348 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +00002349
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002350 if (ctx == NULL) {
2351 v->not_found = 1;
2352 return NGX_OK;
2353 }
2354
2355 v->len = ctx->vars.host_header.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002356 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00002357 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002358 v->not_found = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002359 v->data = ctx->vars.host_header.data;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002360
Igor Sysoev09c684b2005-11-09 17:25:55 +00002361 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002362}
2363
2364
Igor Sysoev09c684b2005-11-09 17:25:55 +00002365static ngx_int_t
2366ngx_http_proxy_port_variable(ngx_http_request_t *r,
2367 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002368{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002369 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002370
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002371 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002372
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002373 if (ctx == NULL) {
2374 v->not_found = 1;
2375 return NGX_OK;
2376 }
2377
2378 v->len = ctx->vars.port.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002379 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00002380 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002381 v->not_found = 0;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002382 v->data = ctx->vars.port.data;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002383
Igor Sysoev09c684b2005-11-09 17:25:55 +00002384 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002385}
2386
2387
Igor Sysoev09c684b2005-11-09 17:25:55 +00002388static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00002389ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
Igor Sysoev09c684b2005-11-09 17:25:55 +00002390 ngx_http_variable_value_t *v, uintptr_t data)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002391{
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002392 size_t len;
2393 u_char *p;
2394 ngx_uint_t i, n;
2395 ngx_table_elt_t **h;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002396
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002397 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00002398 v->no_cacheable = 0;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002399 v->not_found = 0;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002400
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002401 n = r->headers_in.x_forwarded_for.nelts;
2402 h = r->headers_in.x_forwarded_for.elts;
2403
2404 len = 0;
2405
2406 for (i = 0; i < n; i++) {
2407 len += h[i]->value.len + sizeof(", ") - 1;
2408 }
2409
2410 if (len == 0) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00002411 v->len = r->connection->addr_text.len;
2412 v->data = r->connection->addr_text.data;
2413 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002414 }
2415
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002416 len += r->connection->addr_text.len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002417
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002418 p = ngx_pnalloc(r->pool, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002419 if (p == NULL) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00002420 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002421 }
2422
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002423 v->len = len;
Igor Sysoev09c684b2005-11-09 17:25:55 +00002424 v->data = p;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002425
Ruslan Ermilov67a68722013-02-27 13:29:50 +00002426 for (i = 0; i < n; i++) {
2427 p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
2428 *p++ = ','; *p++ = ' ';
2429 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00002430
2431 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
2432
Igor Sysoev09c684b2005-11-09 17:25:55 +00002433 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002434}
2435
2436
2437static ngx_int_t
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002438ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
2439 ngx_http_variable_value_t *v, uintptr_t data)
2440{
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002441 ngx_http_proxy_ctx_t *ctx;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002442
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002443 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002444
Maxim Dounin9a483c82012-11-21 01:03:48 +00002445 if (ctx == NULL || ctx->internal_body_length < 0) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002446 v->not_found = 1;
2447 return NGX_OK;
2448 }
2449
2450 v->valid = 1;
Igor Sysoev2d3f3f62007-10-14 18:56:15 +00002451 v->no_cacheable = 0;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002452 v->not_found = 0;
2453
Ruslan Ermilov9014efd2013-04-29 18:58:58 +04002454 v->data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002455
2456 if (v->data == NULL) {
2457 return NGX_ERROR;
2458 }
2459
Maxim Dounin9a483c82012-11-21 01:03:48 +00002460 v->len = ngx_sprintf(v->data, "%O", ctx->internal_body_length) - v->data;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002461
2462 return NGX_OK;
2463}
2464
2465
2466static ngx_int_t
Maxim Dounin55344dd2015-03-23 21:09:19 +03002467ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
2468 ngx_http_variable_value_t *v, uintptr_t data)
2469{
2470 ngx_http_proxy_ctx_t *ctx;
2471
2472 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2473
2474 if (ctx == NULL || !ctx->internal_chunked) {
2475 v->not_found = 1;
2476 return NGX_OK;
2477 }
2478
2479 v->valid = 1;
2480 v->no_cacheable = 0;
2481 v->not_found = 0;
2482
2483 v->data = (u_char *) "chunked";
2484 v->len = sizeof("chunked") - 1;
2485
2486 return NGX_OK;
2487}
2488
2489
2490static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00002491ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
2492 size_t prefix)
2493{
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002494 size_t len;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002495 ngx_int_t rc;
2496 ngx_uint_t i;
Valentin Bartenev582dac12012-02-13 10:42:44 +00002497 ngx_http_proxy_rewrite_t *pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002498 ngx_http_proxy_loc_conf_t *plcf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002499
2500 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2501
2502 pr = plcf->redirects->elts;
2503
2504 if (pr == NULL) {
2505 return NGX_DECLINED;
2506 }
2507
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002508 len = h->value.len - prefix;
2509
Igor Sysoev899b44e2005-05-12 14:58:06 +00002510 for (i = 0; i < plcf->redirects->nelts; i++) {
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002511 rc = pr[i].handler(r, h, prefix, len, &pr[i]);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002512
2513 if (rc != NGX_DECLINED) {
2514 return rc;
2515 }
2516 }
2517
2518 return NGX_DECLINED;
2519}
2520
2521
2522static ngx_int_t
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002523ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
2524{
2525 size_t prefix;
2526 u_char *p;
Valentin Barteneva113cb32012-02-13 11:08:05 +00002527 ngx_int_t rc, rv;
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002528 ngx_http_proxy_loc_conf_t *plcf;
2529
2530 p = (u_char *) ngx_strchr(h->value.data, ';');
2531 if (p == NULL) {
2532 return NGX_DECLINED;
2533 }
2534
2535 prefix = p + 1 - h->value.data;
2536
Valentin Barteneva113cb32012-02-13 11:08:05 +00002537 rv = NGX_DECLINED;
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002538
2539 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2540
2541 if (plcf->cookie_domains) {
2542 p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
2543
2544 if (p) {
2545 rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
2546 plcf->cookie_domains);
Valentin Barteneva113cb32012-02-13 11:08:05 +00002547 if (rc == NGX_ERROR) {
2548 return NGX_ERROR;
2549 }
2550
2551 if (rc != NGX_DECLINED) {
2552 rv = rc;
2553 }
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002554 }
2555 }
2556
Valentin Barteneva113cb32012-02-13 11:08:05 +00002557 if (plcf->cookie_paths) {
2558 p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
2559
2560 if (p) {
2561 rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
2562 plcf->cookie_paths);
2563 if (rc == NGX_ERROR) {
2564 return NGX_ERROR;
2565 }
2566
2567 if (rc != NGX_DECLINED) {
2568 rv = rc;
2569 }
2570 }
2571 }
2572
2573 return rv;
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002574}
2575
2576
2577static ngx_int_t
2578ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
2579 u_char *value, ngx_array_t *rewrites)
2580{
2581 size_t len, prefix;
2582 u_char *p;
2583 ngx_int_t rc;
2584 ngx_uint_t i;
2585 ngx_http_proxy_rewrite_t *pr;
2586
2587 prefix = value - h->value.data;
2588
2589 p = (u_char *) ngx_strchr(value, ';');
2590
2591 len = p ? (size_t) (p - value) : (h->value.len - prefix);
2592
2593 pr = rewrites->elts;
2594
2595 for (i = 0; i < rewrites->nelts; i++) {
2596 rc = pr[i].handler(r, h, prefix, len, &pr[i]);
2597
2598 if (rc != NGX_DECLINED) {
2599 return rc;
2600 }
2601 }
2602
2603 return NGX_DECLINED;
2604}
2605
2606
2607static ngx_int_t
Valentin Bartenev582dac12012-02-13 10:42:44 +00002608ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002609 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002610{
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002611 ngx_str_t pattern, replacement;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002612
Valentin Bartenev582dac12012-02-13 10:42:44 +00002613 if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
Valentin Bartenev0be95542011-12-12 09:02:29 +00002614 return NGX_ERROR;
2615 }
2616
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002617 if (pattern.len > len
Valentin Bartenev582dac12012-02-13 10:42:44 +00002618 || ngx_rstrncmp(h->value.data + prefix, pattern.data,
2619 pattern.len) != 0)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002620 {
2621 return NGX_DECLINED;
2622 }
2623
Valentin Bartenev0be95542011-12-12 09:02:29 +00002624 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2625 return NGX_ERROR;
2626 }
2627
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002628 return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002629}
2630
2631
Valentin Bartenev0be95542011-12-12 09:02:29 +00002632#if (NGX_PCRE)
2633
Igor Sysoev899b44e2005-05-12 14:58:06 +00002634static ngx_int_t
Valentin Bartenev582dac12012-02-13 10:42:44 +00002635ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002636 size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002637{
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002638 ngx_str_t pattern, replacement;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002639
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002640 pattern.len = len;
Valentin Bartenev582dac12012-02-13 10:42:44 +00002641 pattern.data = h->value.data + prefix;
Valentin Bartenev0be95542011-12-12 09:02:29 +00002642
Valentin Bartenev582dac12012-02-13 10:42:44 +00002643 if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002644 return NGX_DECLINED;
2645 }
2646
Valentin Bartenev0be95542011-12-12 09:02:29 +00002647 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002648 return NGX_ERROR;
2649 }
2650
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002651 if (prefix == 0 && h->value.len == len) {
Valentin Bartenevb8ef9d92012-01-10 15:09:45 +00002652 h->value = replacement;
2653 return NGX_OK;
2654 }
2655
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002656 return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002657}
2658
Valentin Bartenev0be95542011-12-12 09:02:29 +00002659#endif
2660
Igor Sysoev899b44e2005-05-12 14:58:06 +00002661
2662static ngx_int_t
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002663ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
2664 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2665{
2666 u_char *p;
2667 ngx_str_t pattern, replacement;
2668
2669 if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
2670 return NGX_ERROR;
2671 }
2672
2673 p = h->value.data + prefix;
2674
2675 if (p[0] == '.') {
2676 p++;
2677 prefix++;
2678 len--;
2679 }
2680
2681 if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) {
2682 return NGX_DECLINED;
2683 }
2684
2685 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2686 return NGX_ERROR;
2687 }
2688
2689 return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
2690}
2691
2692
2693static ngx_int_t
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002694ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
2695 size_t len, ngx_str_t *replacement)
2696{
2697 u_char *p, *data;
2698 size_t new_len;
2699
2700 new_len = replacement->len + h->value.len - len;
2701
2702 if (replacement->len > len) {
2703
Valentin Bartenevb5330682013-11-18 03:06:45 +04002704 data = ngx_pnalloc(r->pool, new_len + 1);
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002705 if (data == NULL) {
2706 return NGX_ERROR;
2707 }
2708
2709 p = ngx_copy(data, h->value.data, prefix);
2710 p = ngx_copy(p, replacement->data, replacement->len);
2711
2712 ngx_memcpy(p, h->value.data + prefix + len,
Valentin Bartenevb5330682013-11-18 03:06:45 +04002713 h->value.len - len - prefix + 1);
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002714
2715 h->value.data = data;
2716
2717 } else {
2718 p = ngx_copy(h->value.data + prefix, replacement->data,
2719 replacement->len);
2720
2721 ngx_memmove(p, h->value.data + prefix + len,
Valentin Bartenevb5330682013-11-18 03:06:45 +04002722 h->value.len - len - prefix + 1);
Valentin Bartenev7c611aa2012-02-13 10:56:09 +00002723 }
2724
2725 h->value.len = new_len;
2726
2727 return NGX_OK;
2728}
2729
2730
2731static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00002732ngx_http_proxy_add_variables(ngx_conf_t *cf)
2733{
2734 ngx_http_variable_t *var, *v;
2735
2736 for (v = ngx_http_proxy_vars; v->name.len; v++) {
2737 var = ngx_http_add_variable(cf, &v->name, v->flags);
2738 if (var == NULL) {
2739 return NGX_ERROR;
2740 }
2741
Igor Sysoev7bdb7202006-04-19 15:30:56 +00002742 var->get_handler = v->get_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002743 var->data = v->data;
2744 }
2745
2746 return NGX_OK;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002747}
2748
2749
2750static void *
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +03002751ngx_http_proxy_create_main_conf(ngx_conf_t *cf)
2752{
2753 ngx_http_proxy_main_conf_t *conf;
2754
2755 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_main_conf_t));
2756 if (conf == NULL) {
2757 return NULL;
2758 }
2759
2760#if (NGX_HTTP_CACHE)
2761 if (ngx_array_init(&conf->caches, cf->pool, 4,
2762 sizeof(ngx_http_file_cache_t *))
2763 != NGX_OK)
2764 {
2765 return NULL;
2766 }
2767#endif
2768
2769 return conf;
2770}
2771
2772
2773static void *
Igor Sysoev02f742b2005-04-08 15:18:55 +00002774ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
2775{
2776 ngx_http_proxy_loc_conf_t *conf;
2777
2778 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
2779 if (conf == NULL) {
Igor Sysoev260c4322009-06-02 16:09:44 +00002780 return NULL;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002781 }
2782
2783 /*
2784 * set by ngx_pcalloc():
2785 *
2786 * conf->upstream.bufs.num = 0;
Igor Sysoevb01c9cc2009-04-30 16:15:07 +00002787 * conf->upstream.ignore_headers = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002788 * conf->upstream.next_upstream = 0;
Valentin Bartenev5de66622014-12-22 12:59:02 +03002789 * conf->upstream.cache_zone = NULL;
Igor Sysoev5ed36912009-05-19 13:27:27 +00002790 * conf->upstream.cache_use_stale = 0;
2791 * conf->upstream.cache_methods = 0;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002792 * conf->upstream.temp_path = NULL;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002793 * conf->upstream.hide_headers_hash = { NULL, 0 };
Igor Sysoev899b44e2005-05-12 14:58:06 +00002794 * conf->upstream.uri = { 0, NULL };
2795 * conf->upstream.location = NULL;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002796 * conf->upstream.store_lengths = NULL;
2797 * conf->upstream.store_values = NULL;
Maxim Dounin59ef4a32014-04-18 20:13:28 +04002798 * conf->upstream.ssl_name = NULL;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002799 *
Maxim Douninaa0b86f2013-01-22 12:36:00 +00002800 * conf->method = { 0, NULL };
Igor Sysoev899b44e2005-05-12 14:58:06 +00002801 * conf->headers_source = NULL;
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03002802 * conf->headers.lengths = NULL;
2803 * conf->headers.values = NULL;
2804 * conf->headers.hash = { NULL, 0 };
Roman Arutyunyan8898c972014-11-19 17:33:23 +03002805 * conf->headers_cache.lengths = NULL;
2806 * conf->headers_cache.values = NULL;
2807 * conf->headers_cache.hash = { NULL, 0 };
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03002808 * conf->body_lengths = NULL;
2809 * conf->body_values = NULL;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002810 * conf->body_source = { 0, NULL };
Igor Sysoev931d88c2010-03-10 14:37:18 +00002811 * conf->redirects = NULL;
Andrei Belov003b2cd2013-09-19 18:30:33 +04002812 * conf->ssl = 0;
2813 * conf->ssl_protocols = 0;
Piotr Sikora43736b12013-09-23 15:58:28 -07002814 * conf->ssl_ciphers = { 0, NULL };
Maxim Dounin27475dd2014-04-18 20:13:30 +04002815 * conf->ssl_trusted_certificate = { 0, NULL };
2816 * conf->ssl_crl = { 0, NULL };
Piotr Sikoraa9d9b092014-10-30 04:30:41 -07002817 * conf->ssl_certificate = { 0, NULL };
2818 * conf->ssl_certificate_key = { 0, NULL };
Igor Sysoev02f742b2005-04-08 15:18:55 +00002819 */
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002820
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002821 conf->upstream.store = NGX_CONF_UNSET;
2822 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
Roman Arutyunyan02ce6c42014-09-12 18:50:47 +04002823 conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002824 conf->upstream.buffering = NGX_CONF_UNSET;
Maxim Douninf568ff82015-03-23 21:09:19 +03002825 conf->upstream.request_buffering = NGX_CONF_UNSET;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002826 conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
Roman Arutyunyan2244a5e2014-10-14 18:32:01 +04002827 conf->upstream.force_ranges = NGX_CONF_UNSET;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002828
Ruslan Ermilov5d143ca2013-01-16 09:42:57 +00002829 conf->upstream.local = NGX_CONF_UNSET_PTR;
2830
Igor Sysoev02f742b2005-04-08 15:18:55 +00002831 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
2832 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
2833 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
Roman Arutyunyan02ce6c42014-09-12 18:50:47 +04002834 conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002835
2836 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002837 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
Roman Arutyunyan18e4d042014-10-28 12:29:59 +03002838 conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
Igor Sysoev187b7d92005-07-14 12:51:53 +00002839
2840 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002841 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev187b7d92005-07-14 12:51:53 +00002842 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002843
Igor Sysoev899b44e2005-05-12 14:58:06 +00002844 conf->upstream.pass_request_headers = NGX_CONF_UNSET;
2845 conf->upstream.pass_request_body = NGX_CONF_UNSET;
Igor Sysoev78452232005-10-12 13:50:36 +00002846
Igor Sysoev52859f22009-03-23 13:14:51 +00002847#if (NGX_HTTP_CACHE)
Valentin Bartenev5de66622014-12-22 12:59:02 +03002848 conf->upstream.cache = NGX_CONF_UNSET;
Igor Sysoev52859f22009-03-23 13:14:51 +00002849 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
Igor Sysoevf7d659a2010-07-19 09:36:04 +00002850 conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
Igor Sysoev9b2763a2010-05-24 11:01:05 +00002851 conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
Igor Sysoev52859f22009-03-23 13:14:51 +00002852 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
Maxim Dounin822fe462011-12-26 11:15:23 +00002853 conf->upstream.cache_lock = NGX_CONF_UNSET;
2854 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
Roman Arutyunyan2628cc12014-11-18 20:41:12 +03002855 conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
Maxim Dounin1ac26932013-11-18 20:48:22 +04002856 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
Roman Arutyunyanf0ee4eb2015-11-11 15:47:30 +03002857 conf->upstream.cache_convert_head = NGX_CONF_UNSET;
Igor Sysoev52859f22009-03-23 13:14:51 +00002858#endif
2859
Igor Sysoevcb540612007-12-09 18:03:20 +00002860 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
2861 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
2862
Igor Sysoevef809b82006-06-28 16:00:26 +00002863 conf->upstream.intercept_errors = NGX_CONF_UNSET;
Maxim Dounin59ef4a32014-04-18 20:13:28 +04002864
Igor Sysoev916ee8e2008-08-17 17:47:52 +00002865#if (NGX_HTTP_SSL)
2866 conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
Maxim Dounin59ef4a32014-04-18 20:13:28 +04002867 conf->upstream.ssl_server_name = NGX_CONF_UNSET;
Maxim Dounin27475dd2014-04-18 20:13:30 +04002868 conf->upstream.ssl_verify = NGX_CONF_UNSET;
2869 conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
Piotr Sikoraa9d9b092014-10-30 04:30:41 -07002870 conf->ssl_passwords = NGX_CONF_UNSET_PTR;
Igor Sysoev916ee8e2008-08-17 17:47:52 +00002871#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +00002872
2873 /* "proxy_cyclic_temp_file" is disabled */
2874 conf->upstream.cyclic_temp_file = 0;
2875
Igor Sysoev899b44e2005-05-12 14:58:06 +00002876 conf->redirect = NGX_CONF_UNSET;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00002877 conf->upstream.change_buffering = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00002878
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002879 conf->cookie_domains = NGX_CONF_UNSET_PTR;
Valentin Barteneva113cb32012-02-13 11:08:05 +00002880 conf->cookie_paths = NGX_CONF_UNSET_PTR;
Valentin Barteneve9df2d62012-02-13 11:04:45 +00002881
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00002882 conf->http_version = NGX_CONF_UNSET_UINT;
2883
Igor Sysoev8a19bff2007-04-22 20:21:59 +00002884 conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
2885 conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
2886
Igor Sysoevc2f852c2011-07-29 15:33:03 +00002887 ngx_str_set(&conf->upstream.module, "proxy");
2888
Igor Sysoev02f742b2005-04-08 15:18:55 +00002889 return conf;
2890}
2891
2892
2893static char *
2894ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2895{
2896 ngx_http_proxy_loc_conf_t *prev = parent;
2897 ngx_http_proxy_loc_conf_t *conf = child;
2898
Igor Sysoevb2492252011-02-17 11:54:35 +00002899 u_char *p;
Igor Sysoev52859f22009-03-23 13:14:51 +00002900 size_t size;
Roman Arutyunyan8898c972014-11-19 17:33:23 +03002901 ngx_int_t rc;
Igor Sysoev52859f22009-03-23 13:14:51 +00002902 ngx_hash_init_t hash;
Igor Sysoev90f95522010-08-03 09:24:25 +00002903 ngx_http_core_loc_conf_t *clcf;
Valentin Bartenev582dac12012-02-13 10:42:44 +00002904 ngx_http_proxy_rewrite_t *pr;
Igor Sysoev52859f22009-03-23 13:14:51 +00002905 ngx_http_script_compile_t sc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002906
Valentin Barteneve764ffb2014-12-22 12:58:59 +03002907#if (NGX_HTTP_CACHE)
2908
2909 if (conf->upstream.store > 0) {
Valentin Bartenev5de66622014-12-22 12:59:02 +03002910 conf->upstream.cache = 0;
Valentin Barteneve764ffb2014-12-22 12:58:59 +03002911 }
2912
Valentin Bartenev5de66622014-12-22 12:59:02 +03002913 if (conf->upstream.cache > 0) {
Valentin Barteneve764ffb2014-12-22 12:58:59 +03002914 conf->upstream.store = 0;
2915 }
2916
2917#endif
2918
Valentin Bartenevc562b742014-10-09 20:30:11 +04002919 if (conf->upstream.store == NGX_CONF_UNSET) {
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002920 ngx_conf_merge_value(conf->upstream.store,
Igor Sysoevda28ef82009-05-28 13:31:43 +00002921 prev->upstream.store, 0);
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002922
Valentin Barteneva4b7b102014-12-22 12:58:56 +03002923 conf->upstream.store_lengths = prev->upstream.store_lengths;
2924 conf->upstream.store_values = prev->upstream.store_values;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00002925 }
2926
2927 ngx_conf_merge_uint_value(conf->upstream.store_access,
2928 prev->upstream.store_access, 0600);
Igor Sysoev58feb532007-07-12 11:19:05 +00002929
Roman Arutyunyan02ce6c42014-09-12 18:50:47 +04002930 ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
2931 prev->upstream.next_upstream_tries, 0);
2932
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002933 ngx_conf_merge_value(conf->upstream.buffering,
2934 prev->upstream.buffering, 1);
2935
Maxim Douninf568ff82015-03-23 21:09:19 +03002936 ngx_conf_merge_value(conf->upstream.request_buffering,
2937 prev->upstream.request_buffering, 1);
2938
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002939 ngx_conf_merge_value(conf->upstream.ignore_client_abort,
2940 prev->upstream.ignore_client_abort, 0);
2941
Roman Arutyunyan2244a5e2014-10-14 18:32:01 +04002942 ngx_conf_merge_value(conf->upstream.force_ranges,
2943 prev->upstream.force_ranges, 0);
2944
Ruslan Ermilov5d143ca2013-01-16 09:42:57 +00002945 ngx_conf_merge_ptr_value(conf->upstream.local,
2946 prev->upstream.local, NULL);
2947
Igor Sysoev02f742b2005-04-08 15:18:55 +00002948 ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
2949 prev->upstream.connect_timeout, 60000);
2950
2951 ngx_conf_merge_msec_value(conf->upstream.send_timeout,
2952 prev->upstream.send_timeout, 60000);
2953
2954 ngx_conf_merge_msec_value(conf->upstream.read_timeout,
2955 prev->upstream.read_timeout, 60000);
2956
Roman Arutyunyan02ce6c42014-09-12 18:50:47 +04002957 ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
2958 prev->upstream.next_upstream_timeout, 0);
2959
Igor Sysoev02f742b2005-04-08 15:18:55 +00002960 ngx_conf_merge_size_value(conf->upstream.send_lowat,
2961 prev->upstream.send_lowat, 0);
2962
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002963 ngx_conf_merge_size_value(conf->upstream.buffer_size,
2964 prev->upstream.buffer_size,
Igor Sysoev02f742b2005-04-08 15:18:55 +00002965 (size_t) ngx_pagesize);
2966
Roman Arutyunyan18e4d042014-10-28 12:29:59 +03002967 ngx_conf_merge_size_value(conf->upstream.limit_rate,
2968 prev->upstream.limit_rate, 0);
2969
Igor Sysoev02f742b2005-04-08 15:18:55 +00002970 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
2971 8, ngx_pagesize);
2972
2973 if (conf->upstream.bufs.num < 2) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002974 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev02f742b2005-04-08 15:18:55 +00002975 "there must be at least 2 \"proxy_buffers\"");
2976 return NGX_CONF_ERROR;
2977 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002978
Igor Sysoev02f742b2005-04-08 15:18:55 +00002979
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002980 size = conf->upstream.buffer_size;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002981 if (size < conf->upstream.bufs.size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002982 size = conf->upstream.bufs.size;
2983 }
2984
2985
Igor Sysoev187b7d92005-07-14 12:51:53 +00002986 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
2987 prev->upstream.busy_buffers_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00002988 NGX_CONF_UNSET_SIZE);
2989
Igor Sysoev187b7d92005-07-14 12:51:53 +00002990 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002991 conf->upstream.busy_buffers_size = 2 * size;
Igor Sysoev187b7d92005-07-14 12:51:53 +00002992 } else {
2993 conf->upstream.busy_buffers_size =
2994 conf->upstream.busy_buffers_size_conf;
2995 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002996
Igor Sysoev187b7d92005-07-14 12:51:53 +00002997 if (conf->upstream.busy_buffers_size < size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00002998 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00002999 "\"proxy_busy_buffers_size\" must be equal to or greater than "
3000 "the maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev02f742b2005-04-08 15:18:55 +00003001 "one of the \"proxy_buffers\"");
3002
3003 return NGX_CONF_ERROR;
Igor Sysoev187b7d92005-07-14 12:51:53 +00003004 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00003005
Igor Sysoev187b7d92005-07-14 12:51:53 +00003006 if (conf->upstream.busy_buffers_size
3007 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
Igor Sysoev02f742b2005-04-08 15:18:55 +00003008 {
3009 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3010 "\"proxy_busy_buffers_size\" must be less than "
3011 "the size of all \"proxy_buffers\" minus one buffer");
3012
3013 return NGX_CONF_ERROR;
3014 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00003015
Igor Sysoev187b7d92005-07-14 12:51:53 +00003016
3017 ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
3018 prev->upstream.temp_file_write_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00003019 NGX_CONF_UNSET_SIZE);
3020
Igor Sysoev187b7d92005-07-14 12:51:53 +00003021 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00003022 conf->upstream.temp_file_write_size = 2 * size;
Igor Sysoev187b7d92005-07-14 12:51:53 +00003023 } else {
3024 conf->upstream.temp_file_write_size =
3025 conf->upstream.temp_file_write_size_conf;
3026 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003027
Igor Sysoev187b7d92005-07-14 12:51:53 +00003028 if (conf->upstream.temp_file_write_size < size) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00003029 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003030 "\"proxy_temp_file_write_size\" must be equal to or greater "
3031 "than the maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev02f742b2005-04-08 15:18:55 +00003032 "one of the \"proxy_buffers\"");
3033
3034 return NGX_CONF_ERROR;
3035 }
3036
Igor Sysoev187b7d92005-07-14 12:51:53 +00003037 ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
3038 prev->upstream.max_temp_file_size_conf,
Igor Sysoev02f742b2005-04-08 15:18:55 +00003039 NGX_CONF_UNSET_SIZE);
3040
Igor Sysoev187b7d92005-07-14 12:51:53 +00003041 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00003042 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
Igor Sysoev187b7d92005-07-14 12:51:53 +00003043 } else {
3044 conf->upstream.max_temp_file_size =
3045 conf->upstream.max_temp_file_size_conf;
3046 }
Igor Sysoev02f742b2005-04-08 15:18:55 +00003047
Igor Sysoev187b7d92005-07-14 12:51:53 +00003048 if (conf->upstream.max_temp_file_size != 0
3049 && conf->upstream.max_temp_file_size < size)
Igor Sysoev02f742b2005-04-08 15:18:55 +00003050 {
3051 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev78452232005-10-12 13:50:36 +00003052 "\"proxy_max_temp_file_size\" must be equal to zero to disable "
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003053 "temporary files usage or must be equal to or greater than "
3054 "the maximum of the value of \"proxy_buffer_size\" and "
Igor Sysoev78452232005-10-12 13:50:36 +00003055 "one of the \"proxy_buffers\"");
Igor Sysoev02f742b2005-04-08 15:18:55 +00003056
3057 return NGX_CONF_ERROR;
3058 }
3059
Igor Sysoev187b7d92005-07-14 12:51:53 +00003060
Igor Sysoevb01c9cc2009-04-30 16:15:07 +00003061 ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
3062 prev->upstream.ignore_headers,
3063 NGX_CONF_BITMASK_SET);
3064
3065
Igor Sysoev02f742b2005-04-08 15:18:55 +00003066 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
3067 prev->upstream.next_upstream,
3068 (NGX_CONF_BITMASK_SET
3069 |NGX_HTTP_UPSTREAM_FT_ERROR
3070 |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
3071
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00003072 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
3073 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
3074 |NGX_HTTP_UPSTREAM_FT_OFF;
3075 }
3076
Igor Sysoev52859f22009-03-23 13:14:51 +00003077 if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
Igor Sysoev899b44e2005-05-12 14:58:06 +00003078 prev->upstream.temp_path,
Igor Sysoev52859f22009-03-23 13:14:51 +00003079 &ngx_http_proxy_temp_path)
3080 != NGX_OK)
3081 {
3082 return NGX_CONF_ERROR;
3083 }
3084
3085
3086#if (NGX_HTTP_CACHE)
3087
Valentin Bartenev5de66622014-12-22 12:59:02 +03003088 if (conf->upstream.cache == NGX_CONF_UNSET) {
3089 ngx_conf_merge_value(conf->upstream.cache,
3090 prev->upstream.cache, 0);
Igor Sysoev52859f22009-03-23 13:14:51 +00003091
Valentin Bartenev5de66622014-12-22 12:59:02 +03003092 conf->upstream.cache_zone = prev->upstream.cache_zone;
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +03003093 conf->upstream.cache_value = prev->upstream.cache_value;
Valentin Bartenev5de66622014-12-22 12:59:02 +03003094 }
3095
3096 if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003097 ngx_shm_zone_t *shm_zone;
3098
Valentin Bartenev5de66622014-12-22 12:59:02 +03003099 shm_zone = conf->upstream.cache_zone;
Igor Sysoev52859f22009-03-23 13:14:51 +00003100
3101 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3102 "\"proxy_cache\" zone \"%V\" is unknown",
Igor Sysoevc7f876b2009-04-16 19:25:09 +00003103 &shm_zone->shm.name);
Igor Sysoev52859f22009-03-23 13:14:51 +00003104
3105 return NGX_CONF_ERROR;
3106 }
3107
3108 ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
3109 prev->upstream.cache_min_uses, 1);
3110
3111 ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
3112 prev->upstream.cache_use_stale,
3113 (NGX_CONF_BITMASK_SET
3114 |NGX_HTTP_UPSTREAM_FT_OFF));
3115
Maxim Dounin2c559142012-01-16 11:01:52 +00003116 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
3117 conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
3118 |NGX_HTTP_UPSTREAM_FT_OFF;
3119 }
3120
3121 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
3122 conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
3123 }
3124
Igor Sysoev5ed36912009-05-19 13:27:27 +00003125 if (conf->upstream.cache_methods == 0) {
3126 conf->upstream.cache_methods = prev->upstream.cache_methods;
3127 }
3128
3129 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
3130
Igor Sysoevf7d659a2010-07-19 09:36:04 +00003131 ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
3132 prev->upstream.cache_bypass, NULL);
3133
Igor Sysoev9b2763a2010-05-24 11:01:05 +00003134 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
3135 prev->upstream.no_cache, NULL);
3136
Igor Sysoev52859f22009-03-23 13:14:51 +00003137 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
3138 prev->upstream.cache_valid, NULL);
3139
Igor Sysoev44a69c82009-04-06 08:58:44 +00003140 if (conf->cache_key.value.data == NULL) {
3141 conf->cache_key = prev->cache_key;
3142 }
3143
Maxim Dounin822fe462011-12-26 11:15:23 +00003144 ngx_conf_merge_value(conf->upstream.cache_lock,
3145 prev->upstream.cache_lock, 0);
3146
3147 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
3148 prev->upstream.cache_lock_timeout, 5000);
3149
Roman Arutyunyan2628cc12014-11-18 20:41:12 +03003150 ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
3151 prev->upstream.cache_lock_age, 5000);
3152
Maxim Dounin1ac26932013-11-18 20:48:22 +04003153 ngx_conf_merge_value(conf->upstream.cache_revalidate,
3154 prev->upstream.cache_revalidate, 0);
3155
Roman Arutyunyanf0ee4eb2015-11-11 15:47:30 +03003156 ngx_conf_merge_value(conf->upstream.cache_convert_head,
3157 prev->upstream.cache_convert_head, 1);
3158
Igor Sysoev52859f22009-03-23 13:14:51 +00003159#endif
Igor Sysoev02f742b2005-04-08 15:18:55 +00003160
Maxim Douninaa0b86f2013-01-22 12:36:00 +00003161 ngx_conf_merge_str_value(conf->method, prev->method, "");
Igor Sysoev78452232005-10-12 13:50:36 +00003162
Igor Sysoev899b44e2005-05-12 14:58:06 +00003163 ngx_conf_merge_value(conf->upstream.pass_request_headers,
3164 prev->upstream.pass_request_headers, 1);
3165 ngx_conf_merge_value(conf->upstream.pass_request_body,
3166 prev->upstream.pass_request_body, 1);
3167
Igor Sysoevef809b82006-06-28 16:00:26 +00003168 ngx_conf_merge_value(conf->upstream.intercept_errors,
3169 prev->upstream.intercept_errors, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00003170
Igor Sysoev916ee8e2008-08-17 17:47:52 +00003171#if (NGX_HTTP_SSL)
Maxim Dounin59ef4a32014-04-18 20:13:28 +04003172
Igor Sysoev916ee8e2008-08-17 17:47:52 +00003173 ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
3174 prev->upstream.ssl_session_reuse, 1);
Andrei Belov003b2cd2013-09-19 18:30:33 +04003175
3176 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
Maxim Douninae0d1e52015-05-25 17:58:20 +03003177 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
3178 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
Andrei Belov003b2cd2013-09-19 18:30:33 +04003179
Piotr Sikora43736b12013-09-23 15:58:28 -07003180 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
3181 "DEFAULT");
3182
Maxim Dounin59ef4a32014-04-18 20:13:28 +04003183 if (conf->upstream.ssl_name == NULL) {
3184 conf->upstream.ssl_name = prev->upstream.ssl_name;
3185 }
3186
3187 ngx_conf_merge_value(conf->upstream.ssl_server_name,
3188 prev->upstream.ssl_server_name, 0);
Maxim Dounin27475dd2014-04-18 20:13:30 +04003189 ngx_conf_merge_value(conf->upstream.ssl_verify,
3190 prev->upstream.ssl_verify, 0);
3191 ngx_conf_merge_uint_value(conf->ssl_verify_depth,
3192 prev->ssl_verify_depth, 1);
3193 ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
3194 prev->ssl_trusted_certificate, "");
3195 ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
Maxim Dounin59ef4a32014-04-18 20:13:28 +04003196
Piotr Sikoraa9d9b092014-10-30 04:30:41 -07003197 ngx_conf_merge_str_value(conf->ssl_certificate,
3198 prev->ssl_certificate, "");
3199 ngx_conf_merge_str_value(conf->ssl_certificate_key,
3200 prev->ssl_certificate_key, "");
3201 ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
3202
Andrei Belov003b2cd2013-09-19 18:30:33 +04003203 if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
3204 return NGX_CONF_ERROR;
3205 }
Maxim Dounin59ef4a32014-04-18 20:13:28 +04003206
Igor Sysoev916ee8e2008-08-17 17:47:52 +00003207#endif
3208
Igor Sysoev899b44e2005-05-12 14:58:06 +00003209 ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
3210
3211 if (conf->redirect) {
3212
3213 if (conf->redirects == NULL) {
3214 conf->redirects = prev->redirects;
3215 }
3216
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003217 if (conf->redirects == NULL && conf->url.data) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003218
3219 conf->redirects = ngx_array_create(cf->pool, 1,
Valentin Bartenev582dac12012-02-13 10:42:44 +00003220 sizeof(ngx_http_proxy_rewrite_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003221 if (conf->redirects == NULL) {
3222 return NGX_CONF_ERROR;
3223 }
3224
3225 pr = ngx_array_push(conf->redirects);
3226 if (pr == NULL) {
3227 return NGX_CONF_ERROR;
3228 }
3229
Valentin Bartenev582dac12012-02-13 10:42:44 +00003230 ngx_memzero(&pr->pattern.complex,
Valentin Bartenev0be95542011-12-12 09:02:29 +00003231 sizeof(ngx_http_complex_value_t));
3232
3233 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
3234
Valentin Bartenev582dac12012-02-13 10:42:44 +00003235 pr->handler = ngx_http_proxy_rewrite_complex_handler;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003236
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003237 if (conf->vars.uri.len) {
Valentin Bartenev582dac12012-02-13 10:42:44 +00003238 pr->pattern.complex.value = conf->url;
Valentin Bartenev0be95542011-12-12 09:02:29 +00003239 pr->replacement.value = conf->location;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003240
3241 } else {
Valentin Bartenev582dac12012-02-13 10:42:44 +00003242 pr->pattern.complex.value.len = conf->url.len
3243 + sizeof("/") - 1;
Igor Sysoevb2492252011-02-17 11:54:35 +00003244
Valentin Bartenev582dac12012-02-13 10:42:44 +00003245 p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
Igor Sysoevb2492252011-02-17 11:54:35 +00003246 if (p == NULL) {
3247 return NGX_CONF_ERROR;
3248 }
3249
Valentin Bartenev582dac12012-02-13 10:42:44 +00003250 pr->pattern.complex.value.data = p;
Igor Sysoevb2492252011-02-17 11:54:35 +00003251
3252 p = ngx_cpymem(p, conf->url.data, conf->url.len);
3253 *p = '/';
3254
Valentin Bartenev0be95542011-12-12 09:02:29 +00003255 ngx_str_set(&pr->replacement.value, "/");
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003256 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00003257 }
3258 }
3259
Valentin Barteneve9df2d62012-02-13 11:04:45 +00003260 ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL);
3261
Valentin Barteneva113cb32012-02-13 11:08:05 +00003262 ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
3263
Maxim Dounin2fe0a7a2011-09-15 19:23:20 +00003264 ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
3265 NGX_HTTP_VERSION_10);
3266
Igor Sysoev8a19bff2007-04-22 20:21:59 +00003267 ngx_conf_merge_uint_value(conf->headers_hash_max_size,
3268 prev->headers_hash_max_size, 512);
3269
3270 ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
3271 prev->headers_hash_bucket_size, 64);
3272
3273 conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
3274 ngx_cacheline_size);
3275
Igor Sysoevcb540612007-12-09 18:03:20 +00003276 hash.max_size = conf->headers_hash_max_size;
3277 hash.bucket_size = conf->headers_hash_bucket_size;
3278 hash.name = "proxy_headers_hash";
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003279
Igor Sysoevcb540612007-12-09 18:03:20 +00003280 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
Igor Sysoev0cb0c672010-07-02 10:05:40 +00003281 &prev->upstream, ngx_http_proxy_hide_headers, &hash)
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003282 != NGX_OK)
3283 {
3284 return NGX_CONF_ERROR;
3285 }
3286
Maxim Dounindbf41762014-12-09 18:22:31 +03003287 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
3288
3289 if (clcf->noname
3290 && conf->upstream.upstream == NULL && conf->proxy_lengths == NULL)
3291 {
Igor Sysoev3d2fd182006-12-04 16:46:13 +00003292 conf->upstream.upstream = prev->upstream.upstream;
Maxim Douninf3075292014-12-09 18:22:39 +03003293 conf->location = prev->location;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003294 conf->vars = prev->vars;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003295
Igor Sysoev81cd5e42010-08-03 12:59:14 +00003296 conf->proxy_lengths = prev->proxy_lengths;
3297 conf->proxy_values = prev->proxy_values;
Maxim Dounin18f34cf2014-12-09 18:21:55 +03003298
3299#if (NGX_HTTP_SSL)
3300 conf->upstream.ssl = prev->upstream.ssl;
3301#endif
Igor Sysoev81cd5e42010-08-03 12:59:14 +00003302 }
3303
Maxim Dounindbf41762014-12-09 18:22:31 +03003304 if (clcf->lmt_excpt && clcf->handler == NULL
3305 && (conf->upstream.upstream || conf->proxy_lengths))
3306 {
3307 clcf->handler = ngx_http_proxy_handler;
Igor Sysoev90f95522010-08-03 09:24:25 +00003308 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003309
3310 if (conf->body_source.data == NULL) {
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003311 conf->body_flushes = prev->body_flushes;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003312 conf->body_source = prev->body_source;
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03003313 conf->body_lengths = prev->body_lengths;
3314 conf->body_values = prev->body_values;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003315 }
3316
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03003317 if (conf->body_source.data && conf->body_lengths == NULL) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003318
3319 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3320
3321 sc.cf = cf;
3322 sc.source = &conf->body_source;
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003323 sc.flushes = &conf->body_flushes;
Roman Arutyunyan1b79cb22014-11-19 17:33:24 +03003324 sc.lengths = &conf->body_lengths;
3325 sc.values = &conf->body_values;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003326 sc.complete_lengths = 1;
3327 sc.complete_values = 1;
3328
3329 if (ngx_http_script_compile(&sc) != NGX_OK) {
3330 return NGX_CONF_ERROR;
3331 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003332 }
3333
Roman Arutyunyan62dfdf12014-11-19 17:33:21 +03003334 if (conf->headers_source == NULL) {
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003335 conf->headers = prev->headers;
Roman Arutyunyan8898c972014-11-19 17:33:23 +03003336#if (NGX_HTTP_CACHE)
3337 conf->headers_cache = prev->headers_cache;
3338#endif
Roman Arutyunyan62dfdf12014-11-19 17:33:21 +03003339 conf->headers_source = prev->headers_source;
3340 }
3341
Roman Arutyunyan8898c972014-11-19 17:33:23 +03003342 rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers,
3343 ngx_http_proxy_headers);
3344 if (rc != NGX_OK) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003345 return NGX_CONF_ERROR;
3346 }
3347
Roman Arutyunyan8898c972014-11-19 17:33:23 +03003348#if (NGX_HTTP_CACHE)
3349
3350 if (conf->upstream.cache) {
3351 rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers_cache,
3352 ngx_http_proxy_cache_headers);
3353 if (rc != NGX_OK) {
3354 return NGX_CONF_ERROR;
3355 }
3356 }
3357
3358#endif
3359
Igor Sysoev52859f22009-03-23 13:14:51 +00003360 return NGX_CONF_OK;
3361}
3362
3363
3364static ngx_int_t
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003365ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
Roman Arutyunyan8898c972014-11-19 17:33:23 +03003366 ngx_http_proxy_headers_t *headers, ngx_keyval_t *default_headers)
Igor Sysoev52859f22009-03-23 13:14:51 +00003367{
3368 u_char *p;
3369 size_t size;
3370 uintptr_t *code;
3371 ngx_uint_t i;
Maxim Douninb5984de2011-11-14 13:18:15 +00003372 ngx_array_t headers_names, headers_merged;
Igor Sysoev52859f22009-03-23 13:14:51 +00003373 ngx_keyval_t *src, *s, *h;
3374 ngx_hash_key_t *hk;
3375 ngx_hash_init_t hash;
3376 ngx_http_script_compile_t sc;
3377 ngx_http_script_copy_code_t *copy;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003378
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003379 if (headers->hash.buckets) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003380 return NGX_OK;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003381 }
3382
Igor Sysoev17483d52010-06-03 14:50:59 +00003383 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
3384 != NGX_OK)
3385 {
Igor Sysoev52859f22009-03-23 13:14:51 +00003386 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003387 }
3388
Maxim Douninb5984de2011-11-14 13:18:15 +00003389 if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
3390 != NGX_OK)
3391 {
3392 return NGX_ERROR;
3393 }
3394
Igor Sysoev899b44e2005-05-12 14:58:06 +00003395 if (conf->headers_source == NULL) {
3396 conf->headers_source = ngx_array_create(cf->pool, 4,
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003397 sizeof(ngx_keyval_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003398 if (conf->headers_source == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003399 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003400 }
3401 }
3402
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003403 headers->lengths = ngx_array_create(cf->pool, 64, 1);
3404 if (headers->lengths == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003405 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003406 }
3407
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003408 headers->values = ngx_array_create(cf->pool, 512, 1);
3409 if (headers->values == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003410 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003411 }
3412
Maxim Douninb5984de2011-11-14 13:18:15 +00003413 src = conf->headers_source->elts;
3414 for (i = 0; i < conf->headers_source->nelts; i++) {
3415
3416 s = ngx_array_push(&headers_merged);
3417 if (s == NULL) {
3418 return NGX_ERROR;
3419 }
3420
3421 *s = src[i];
3422 }
3423
Roman Arutyunyan8898c972014-11-19 17:33:23 +03003424 h = default_headers;
3425
Igor Sysoev081662a2009-04-15 11:21:12 +00003426 while (h->key.len) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003427
Maxim Douninb5984de2011-11-14 13:18:15 +00003428 src = headers_merged.elts;
3429 for (i = 0; i < headers_merged.nelts; i++) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003430 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
3431 goto next;
3432 }
3433 }
3434
Maxim Douninb5984de2011-11-14 13:18:15 +00003435 s = ngx_array_push(&headers_merged);
Igor Sysoev899b44e2005-05-12 14:58:06 +00003436 if (s == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003437 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003438 }
3439
3440 *s = *h;
3441
3442 next:
3443
Igor Sysoev081662a2009-04-15 11:21:12 +00003444 h++;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003445 }
3446
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003447
Maxim Douninb5984de2011-11-14 13:18:15 +00003448 src = headers_merged.elts;
3449 for (i = 0; i < headers_merged.nelts; i++) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003450
Igor Sysoev17483d52010-06-03 14:50:59 +00003451 hk = ngx_array_push(&headers_names);
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003452 if (hk == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003453 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003454 }
3455
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003456 hk->key = src[i].key;
3457 hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
3458 hk->value = (void *) 1;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003459
Igor Sysoev403d2442005-05-26 18:12:40 +00003460 if (src[i].value.len == 0) {
3461 continue;
3462 }
3463
Igor Sysoev899b44e2005-05-12 14:58:06 +00003464 if (ngx_http_script_variables_count(&src[i].value) == 0) {
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003465 copy = ngx_array_push_n(headers->lengths,
Igor Sysoev899b44e2005-05-12 14:58:06 +00003466 sizeof(ngx_http_script_copy_code_t));
3467 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003468 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003469 }
3470
3471 copy->code = (ngx_http_script_code_pt)
3472 ngx_http_script_copy_len_code;
3473 copy->len = src[i].key.len + sizeof(": ") - 1
3474 + src[i].value.len + sizeof(CRLF) - 1;
3475
3476
3477 size = (sizeof(ngx_http_script_copy_code_t)
3478 + src[i].key.len + sizeof(": ") - 1
3479 + src[i].value.len + sizeof(CRLF) - 1
3480 + sizeof(uintptr_t) - 1)
3481 & ~(sizeof(uintptr_t) - 1);
3482
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003483 copy = ngx_array_push_n(headers->values, size);
Igor Sysoev899b44e2005-05-12 14:58:06 +00003484 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003485 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003486 }
3487
3488 copy->code = ngx_http_script_copy_code;
3489 copy->len = src[i].key.len + sizeof(": ") - 1
3490 + src[i].value.len + sizeof(CRLF) - 1;
3491
3492 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
3493
3494 p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
3495 *p++ = ':'; *p++ = ' ';
3496 p = ngx_cpymem(p, src[i].value.data, src[i].value.len);
3497 *p++ = CR; *p = LF;
3498
3499 } else {
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003500 copy = ngx_array_push_n(headers->lengths,
Igor Sysoev899b44e2005-05-12 14:58:06 +00003501 sizeof(ngx_http_script_copy_code_t));
3502 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003503 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003504 }
3505
3506 copy->code = (ngx_http_script_code_pt)
3507 ngx_http_script_copy_len_code;
3508 copy->len = src[i].key.len + sizeof(": ") - 1;
3509
3510
3511 size = (sizeof(ngx_http_script_copy_code_t)
3512 + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
3513 & ~(sizeof(uintptr_t) - 1);
3514
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003515 copy = ngx_array_push_n(headers->values, size);
Igor Sysoev899b44e2005-05-12 14:58:06 +00003516 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003517 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003518 }
3519
3520 copy->code = ngx_http_script_copy_code;
3521 copy->len = src[i].key.len + sizeof(": ") - 1;
3522
3523 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
3524 p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
3525 *p++ = ':'; *p = ' ';
3526
3527
3528 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3529
3530 sc.cf = cf;
3531 sc.source = &src[i].value;
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003532 sc.flushes = &headers->flushes;
3533 sc.lengths = &headers->lengths;
3534 sc.values = &headers->values;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003535
3536 if (ngx_http_script_compile(&sc) != NGX_OK) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003537 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003538 }
3539
3540
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003541 copy = ngx_array_push_n(headers->lengths,
Igor Sysoev899b44e2005-05-12 14:58:06 +00003542 sizeof(ngx_http_script_copy_code_t));
3543 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003544 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003545 }
3546
3547 copy->code = (ngx_http_script_code_pt)
3548 ngx_http_script_copy_len_code;
3549 copy->len = sizeof(CRLF) - 1;
3550
3551
3552 size = (sizeof(ngx_http_script_copy_code_t)
3553 + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
3554 & ~(sizeof(uintptr_t) - 1);
3555
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003556 copy = ngx_array_push_n(headers->values, size);
Igor Sysoev899b44e2005-05-12 14:58:06 +00003557 if (copy == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003558 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003559 }
3560
3561 copy->code = ngx_http_script_copy_code;
3562 copy->len = sizeof(CRLF) - 1;
3563
3564 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
3565 *p++ = CR; *p = LF;
3566 }
3567
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003568 code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003569 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003570 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003571 }
3572
3573 *code = (uintptr_t) NULL;
3574
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003575 code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003576 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003577 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003578 }
3579
3580 *code = (uintptr_t) NULL;
3581 }
3582
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003583 code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003584 if (code == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00003585 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003586 }
3587
3588 *code = (uintptr_t) NULL;
3589
3590
Roman Arutyunyanbcf6b112014-11-19 17:33:22 +03003591 hash.hash = &headers->hash;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003592 hash.key = ngx_hash_key_lc;
Igor Sysoev8a19bff2007-04-22 20:21:59 +00003593 hash.max_size = conf->headers_hash_max_size;
3594 hash.bucket_size = conf->headers_hash_bucket_size;
3595 hash.name = "proxy_headers_hash";
Igor Sysoev3338cfd2006-05-11 14:43:47 +00003596 hash.pool = cf->pool;
3597 hash.temp_pool = NULL;
3598
Igor Sysoev17483d52010-06-03 14:50:59 +00003599 return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
Igor Sysoev02f742b2005-04-08 15:18:55 +00003600}
3601
3602
Igor Sysoev02f742b2005-04-08 15:18:55 +00003603static char *
3604ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3605{
Igor Sysoev899b44e2005-05-12 14:58:06 +00003606 ngx_http_proxy_loc_conf_t *plcf = conf;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003607
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003608 size_t add;
3609 u_short port;
3610 ngx_str_t *value, *url;
3611 ngx_url_t u;
3612 ngx_uint_t n;
3613 ngx_http_core_loc_conf_t *clcf;
3614 ngx_http_script_compile_t sc;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003615
Igor Sysoev73c31212008-12-10 14:44:48 +00003616 if (plcf->upstream.upstream || plcf->proxy_lengths) {
Igor Sysoeva2573672005-10-05 14:46:21 +00003617 return "is duplicate";
3618 }
3619
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003620 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
3621
Igor Sysoev56392722009-07-20 11:44:38 +00003622 clcf->handler = ngx_http_proxy_handler;
3623
3624 if (clcf->name.data[clcf->name.len - 1] == '/') {
3625 clcf->auto_redirect = 1;
3626 }
3627
Igor Sysoev02f742b2005-04-08 15:18:55 +00003628 value = cf->args->elts;
3629
3630 url = &value[1];
3631
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003632 n = ngx_http_script_variables_count(url);
3633
3634 if (n) {
3635
3636 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3637
3638 sc.cf = cf;
3639 sc.source = url;
3640 sc.lengths = &plcf->proxy_lengths;
3641 sc.values = &plcf->proxy_values;
3642 sc.variables = n;
3643 sc.complete_lengths = 1;
3644 sc.complete_values = 1;
Igor Sysoevb4e5b4c2007-12-01 19:57:37 +00003645
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003646 if (ngx_http_script_compile(&sc) != NGX_OK) {
3647 return NGX_CONF_ERROR;
3648 }
3649
3650#if (NGX_HTTP_SSL)
Andrei Belov003b2cd2013-09-19 18:30:33 +04003651 plcf->ssl = 1;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003652#endif
3653
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003654 return NGX_CONF_OK;
3655 }
3656
Igor Sysoev722231f2007-02-14 18:51:19 +00003657 if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003658 add = 7;
Igor Sysoev43f279d2005-12-18 16:02:44 +00003659 port = 80;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003660
Igor Sysoev722231f2007-02-14 18:51:19 +00003661 } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003662
3663#if (NGX_HTTP_SSL)
Andrei Belov003b2cd2013-09-19 18:30:33 +04003664 plcf->ssl = 1;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003665
3666 add = 8;
Igor Sysoev43f279d2005-12-18 16:02:44 +00003667 port = 443;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00003668#else
3669 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3670 "https protocol requires SSL support");
3671 return NGX_CONF_ERROR;
3672#endif
3673
3674 } else {
Igor Sysoev02f742b2005-04-08 15:18:55 +00003675 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
3676 return NGX_CONF_ERROR;
3677 }
3678
Igor Sysoev6f134cc2006-05-23 14:54:58 +00003679 ngx_memzero(&u, sizeof(ngx_url_t));
Igor Sysoev02f742b2005-04-08 15:18:55 +00003680
Igor Sysoev6f134cc2006-05-23 14:54:58 +00003681 u.url.len = url->len - add;
3682 u.url.data = url->data + add;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00003683 u.default_port = port;
Igor Sysoev6f134cc2006-05-23 14:54:58 +00003684 u.uri_part = 1;
Igor Sysoevbf3aaac2006-12-12 16:46:16 +00003685 u.no_resolve = 1;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003686
Igor Sysoev3d2fd182006-12-04 16:46:13 +00003687 plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
3688 if (plcf->upstream.upstream == NULL) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00003689 return NGX_CONF_ERROR;
Igor Sysoev02f742b2005-04-08 15:18:55 +00003690 }
3691
Igor Sysoev73c31212008-12-10 14:44:48 +00003692 plcf->vars.schema.len = add;
3693 plcf->vars.schema.data = url->data;
Igor Sysoev52859f22009-03-23 13:14:51 +00003694 plcf->vars.key_start = plcf->vars.schema;
3695
3696 ngx_http_proxy_set_vars(&u, &plcf->vars);
Igor Sysoev02f742b2005-04-08 15:18:55 +00003697
Igor Sysoev52859f22009-03-23 13:14:51 +00003698 plcf->location = clcf->name;
3699
Igor Sysoev8889b652007-07-29 18:11:39 +00003700 if (clcf->named
Igor Sysoeva2573672005-10-05 14:46:21 +00003701#if (NGX_PCRE)
Igor Sysoev8889b652007-07-29 18:11:39 +00003702 || clcf->regex
3703#endif
3704 || clcf->noname)
3705 {
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003706 if (plcf->vars.uri.len) {
Igor Sysoev09c684b2005-11-09 17:25:55 +00003707 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003708 "\"proxy_pass\" cannot have URI part in "
Igor Sysoeve927b1e2006-11-14 12:43:14 +00003709 "location given by regular expression, "
Igor Sysoev8889b652007-07-29 18:11:39 +00003710 "or inside named location, "
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003711 "or inside \"if\" statement, "
3712 "or inside \"limit_except\" block");
Igor Sysoev09c684b2005-11-09 17:25:55 +00003713 return NGX_CONF_ERROR;
3714 }
3715
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003716 plcf->location.len = 0;
Igor Sysoeva2573672005-10-05 14:46:21 +00003717 }
3718
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003719 plcf->url = *url;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003720
Igor Sysoev02f742b2005-04-08 15:18:55 +00003721 return NGX_CONF_OK;
3722}
3723
3724
3725static char *
Igor Sysoev899b44e2005-05-12 14:58:06 +00003726ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev02f742b2005-04-08 15:18:55 +00003727{
Igor Sysoev899b44e2005-05-12 14:58:06 +00003728 ngx_http_proxy_loc_conf_t *plcf = conf;
3729
Valentin Bartenev0be95542011-12-12 09:02:29 +00003730 u_char *p;
3731 ngx_str_t *value;
Valentin Bartenev582dac12012-02-13 10:42:44 +00003732 ngx_http_proxy_rewrite_t *pr;
Valentin Bartenev0be95542011-12-12 09:02:29 +00003733 ngx_http_compile_complex_value_t ccv;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003734
3735 if (plcf->redirect == 0) {
3736 return NGX_CONF_OK;
3737 }
3738
Valentin Bartenev3feafa72012-01-30 11:22:56 +00003739 plcf->redirect = 1;
3740
Igor Sysoev899b44e2005-05-12 14:58:06 +00003741 value = cf->args->elts;
3742
Igor Sysoev06d4aa12009-04-30 12:43:38 +00003743 if (cf->args->nelts == 2) {
3744 if (ngx_strcmp(value[1].data, "off") == 0) {
3745 plcf->redirect = 0;
3746 plcf->redirects = NULL;
3747 return NGX_CONF_OK;
3748 }
3749
3750 if (ngx_strcmp(value[1].data, "false") == 0) {
3751 ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
3752 "invalid parameter \"false\", use \"off\" instead");
3753 plcf->redirect = 0;
3754 plcf->redirects = NULL;
3755 return NGX_CONF_OK;
3756 }
3757
3758 if (ngx_strcmp(value[1].data, "default") != 0) {
3759 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3760 "invalid parameter \"%V\"", &value[1]);
3761 return NGX_CONF_ERROR;
3762 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00003763 }
3764
3765 if (plcf->redirects == NULL) {
3766 plcf->redirects = ngx_array_create(cf->pool, 1,
Valentin Bartenev582dac12012-02-13 10:42:44 +00003767 sizeof(ngx_http_proxy_rewrite_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003768 if (plcf->redirects == NULL) {
3769 return NGX_CONF_ERROR;
3770 }
3771 }
3772
3773 pr = ngx_array_push(plcf->redirects);
3774 if (pr == NULL) {
3775 return NGX_CONF_ERROR;
3776 }
3777
Igor Sysoev06d4aa12009-04-30 12:43:38 +00003778 if (ngx_strcmp(value[1].data, "default") == 0) {
Igor Sysoev7fa1c072010-03-10 14:41:49 +00003779 if (plcf->proxy_lengths) {
3780 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003781 "\"proxy_redirect default\" cannot be used "
Igor Sysoev7fa1c072010-03-10 14:41:49 +00003782 "with \"proxy_pass\" directive with variables");
3783 return NGX_CONF_ERROR;
3784 }
3785
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003786 if (plcf->url.data == NULL) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003787 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilov43d2b1c2012-04-12 19:35:41 +00003788 "\"proxy_redirect default\" should be placed "
Igor Sysoev899b44e2005-05-12 14:58:06 +00003789 "after the \"proxy_pass\" directive");
3790 return NGX_CONF_ERROR;
3791 }
3792
Valentin Bartenev582dac12012-02-13 10:42:44 +00003793 pr->handler = ngx_http_proxy_rewrite_complex_handler;
Valentin Bartenev0be95542011-12-12 09:02:29 +00003794
Valentin Bartenev582dac12012-02-13 10:42:44 +00003795 ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t));
Valentin Bartenev0be95542011-12-12 09:02:29 +00003796
3797 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003798
Igor Sysoev96dd8af2007-11-27 13:34:13 +00003799 if (plcf->vars.uri.len) {
Valentin Bartenev582dac12012-02-13 10:42:44 +00003800 pr->pattern.complex.value = plcf->url;
Valentin Bartenev0be95542011-12-12 09:02:29 +00003801 pr->replacement.value = plcf->location;
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003802
3803 } else {
Valentin Bartenev582dac12012-02-13 10:42:44 +00003804 pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
Igor Sysoevb2492252011-02-17 11:54:35 +00003805
Valentin Bartenev582dac12012-02-13 10:42:44 +00003806 p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
Igor Sysoevb2492252011-02-17 11:54:35 +00003807 if (p == NULL) {
3808 return NGX_CONF_ERROR;
3809 }
3810
Valentin Bartenev582dac12012-02-13 10:42:44 +00003811 pr->pattern.complex.value.data = p;
Igor Sysoevb2492252011-02-17 11:54:35 +00003812
3813 p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
3814 *p = '/';
3815
Valentin Bartenev0be95542011-12-12 09:02:29 +00003816 ngx_str_set(&pr->replacement.value, "/");
Igor Sysoevafd7ec52006-05-29 17:28:12 +00003817 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00003818
3819 return NGX_CONF_OK;
3820 }
3821
Igor Sysoev899b44e2005-05-12 14:58:06 +00003822
Valentin Bartenev0be95542011-12-12 09:02:29 +00003823 if (value[1].data[0] == '~') {
Valentin Bartenev0be95542011-12-12 09:02:29 +00003824 value[1].len--;
3825 value[1].data++;
3826
Valentin Bartenev0be95542011-12-12 09:02:29 +00003827 if (value[1].data[0] == '*') {
3828 value[1].len--;
3829 value[1].data++;
Valentin Bartenev85551e52012-02-13 11:00:08 +00003830
3831 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3832 return NGX_CONF_ERROR;
3833 }
3834
3835 } else {
3836 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
3837 return NGX_CONF_ERROR;
3838 }
Valentin Bartenev0be95542011-12-12 09:02:29 +00003839 }
3840
Valentin Bartenev0be95542011-12-12 09:02:29 +00003841 } else {
3842
3843 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3844
3845 ccv.cf = cf;
3846 ccv.value = &value[1];
Valentin Bartenev582dac12012-02-13 10:42:44 +00003847 ccv.complex_value = &pr->pattern.complex;
Valentin Bartenev0be95542011-12-12 09:02:29 +00003848
3849 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3850 return NGX_CONF_ERROR;
3851 }
3852
Valentin Bartenev582dac12012-02-13 10:42:44 +00003853 pr->handler = ngx_http_proxy_rewrite_complex_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003854 }
3855
Igor Sysoev899b44e2005-05-12 14:58:06 +00003856
Valentin Bartenev0be95542011-12-12 09:02:29 +00003857 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
Igor Sysoev899b44e2005-05-12 14:58:06 +00003858
Valentin Bartenev0be95542011-12-12 09:02:29 +00003859 ccv.cf = cf;
3860 ccv.value = &value[2];
3861 ccv.complex_value = &pr->replacement;
Igor Sysoev899b44e2005-05-12 14:58:06 +00003862
Valentin Bartenev0be95542011-12-12 09:02:29 +00003863 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00003864 return NGX_CONF_ERROR;
3865 }
3866
Igor Sysoev02f742b2005-04-08 15:18:55 +00003867 return NGX_CONF_OK;
3868}
3869
3870
Valentin Barteneve9df2d62012-02-13 11:04:45 +00003871static char *
3872ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3873{
3874 ngx_http_proxy_loc_conf_t *plcf = conf;
3875
3876 ngx_str_t *value;
3877 ngx_http_proxy_rewrite_t *pr;
3878 ngx_http_compile_complex_value_t ccv;
3879
3880 if (plcf->cookie_domains == NULL) {
3881 return NGX_CONF_OK;
3882 }
3883
3884 value = cf->args->elts;
3885
3886 if (cf->args->nelts == 2) {
3887
3888 if (ngx_strcmp(value[1].data, "off") == 0) {
3889 plcf->cookie_domains = NULL;
3890 return NGX_CONF_OK;
3891 }
3892
3893 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3894 "invalid parameter \"%V\"", &value[1]);
3895 return NGX_CONF_ERROR;
3896 }
3897
3898 if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) {
3899 plcf->cookie_domains = ngx_array_create(cf->pool, 1,
3900 sizeof(ngx_http_proxy_rewrite_t));
3901 if (plcf->cookie_domains == NULL) {
3902 return NGX_CONF_ERROR;
3903 }
3904 }
3905
3906 pr = ngx_array_push(plcf->cookie_domains);
3907 if (pr == NULL) {
3908 return NGX_CONF_ERROR;
3909 }
3910
3911 if (value[1].data[0] == '~') {
3912 value[1].len--;
3913 value[1].data++;
3914
3915 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3916 return NGX_CONF_ERROR;
3917 }
3918
3919 } else {
3920
3921 if (value[1].data[0] == '.') {
3922 value[1].len--;
3923 value[1].data++;
3924 }
3925
3926 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3927
3928 ccv.cf = cf;
3929 ccv.value = &value[1];
3930 ccv.complex_value = &pr->pattern.complex;
3931
3932 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3933 return NGX_CONF_ERROR;
3934 }
3935
3936 pr->handler = ngx_http_proxy_rewrite_domain_handler;
3937
3938 if (value[2].data[0] == '.') {
3939 value[2].len--;
3940 value[2].data++;
3941 }
3942 }
3943
3944 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3945
3946 ccv.cf = cf;
3947 ccv.value = &value[2];
3948 ccv.complex_value = &pr->replacement;
3949
3950 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3951 return NGX_CONF_ERROR;
3952 }
3953
3954 return NGX_CONF_OK;
3955}
3956
3957
Valentin Barteneva113cb32012-02-13 11:08:05 +00003958static char *
3959ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3960{
3961 ngx_http_proxy_loc_conf_t *plcf = conf;
3962
3963 ngx_str_t *value;
3964 ngx_http_proxy_rewrite_t *pr;
3965 ngx_http_compile_complex_value_t ccv;
3966
3967 if (plcf->cookie_paths == NULL) {
3968 return NGX_CONF_OK;
3969 }
3970
3971 value = cf->args->elts;
3972
3973 if (cf->args->nelts == 2) {
3974
3975 if (ngx_strcmp(value[1].data, "off") == 0) {
3976 plcf->cookie_paths = NULL;
3977 return NGX_CONF_OK;
3978 }
3979
3980 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3981 "invalid parameter \"%V\"", &value[1]);
3982 return NGX_CONF_ERROR;
3983 }
3984
3985 if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) {
3986 plcf->cookie_paths = ngx_array_create(cf->pool, 1,
3987 sizeof(ngx_http_proxy_rewrite_t));
3988 if (plcf->cookie_paths == NULL) {
3989 return NGX_CONF_ERROR;
3990 }
3991 }
3992
3993 pr = ngx_array_push(plcf->cookie_paths);
3994 if (pr == NULL) {
3995 return NGX_CONF_ERROR;
3996 }
3997
3998 if (value[1].data[0] == '~') {
3999 value[1].len--;
4000 value[1].data++;
4001
4002 if (value[1].data[0] == '*') {
4003 value[1].len--;
4004 value[1].data++;
4005
4006 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
4007 return NGX_CONF_ERROR;
4008 }
4009
4010 } else {
4011 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
4012 return NGX_CONF_ERROR;
4013 }
4014 }
4015
4016 } else {
4017
4018 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4019
4020 ccv.cf = cf;
4021 ccv.value = &value[1];
4022 ccv.complex_value = &pr->pattern.complex;
4023
4024 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4025 return NGX_CONF_ERROR;
4026 }
4027
4028 pr->handler = ngx_http_proxy_rewrite_complex_handler;
4029 }
4030
4031 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4032
4033 ccv.cf = cf;
4034 ccv.value = &value[2];
4035 ccv.complex_value = &pr->replacement;
4036
4037 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4038 return NGX_CONF_ERROR;
4039 }
4040
4041 return NGX_CONF_OK;
4042}
4043
4044
Valentin Bartenev85551e52012-02-13 11:00:08 +00004045static ngx_int_t
4046ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
4047 ngx_str_t *regex, ngx_uint_t caseless)
4048{
4049#if (NGX_PCRE)
4050 u_char errstr[NGX_MAX_CONF_ERRSTR];
4051 ngx_regex_compile_t rc;
4052
4053 ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
4054
4055 rc.pattern = *regex;
4056 rc.err.len = NGX_MAX_CONF_ERRSTR;
4057 rc.err.data = errstr;
4058
4059 if (caseless) {
4060 rc.options = NGX_REGEX_CASELESS;
4061 }
4062
4063 pr->pattern.regex = ngx_http_regex_compile(cf, &rc);
4064 if (pr->pattern.regex == NULL) {
4065 return NGX_ERROR;
4066 }
4067
4068 pr->handler = ngx_http_proxy_rewrite_regex_handler;
4069
4070 return NGX_OK;
4071
4072#else
4073
4074 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4075 "using regex \"%V\" requires PCRE library", regex);
4076 return NGX_ERROR;
4077
4078#endif
4079}
4080
4081
Igor Sysoev02f742b2005-04-08 15:18:55 +00004082static char *
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004083ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4084{
4085 ngx_http_proxy_loc_conf_t *plcf = conf;
4086
4087 ngx_str_t *value;
4088 ngx_http_script_compile_t sc;
4089
Valentin Barteneva4b7b102014-12-22 12:58:56 +03004090 if (plcf->upstream.store != NGX_CONF_UNSET) {
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004091 return "is duplicate";
4092 }
4093
4094 value = cf->args->elts;
4095
Igor Sysoev98f692a2009-05-28 13:41:44 +00004096 if (ngx_strcmp(value[1].data, "off") == 0) {
4097 plcf->upstream.store = 0;
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004098 return NGX_CONF_OK;
4099 }
4100
Igor Sysoev98f692a2009-05-28 13:41:44 +00004101#if (NGX_HTTP_CACHE)
Valentin Bartenev5de66622014-12-22 12:59:02 +03004102 if (plcf->upstream.cache > 0) {
Igor Sysoev98f692a2009-05-28 13:41:44 +00004103 return "is incompatible with \"proxy_cache\"";
4104 }
Igor Sysoev98f692a2009-05-28 13:41:44 +00004105#endif
4106
Valentin Barteneva4b7b102014-12-22 12:58:56 +03004107 plcf->upstream.store = 1;
4108
Igor Sysoev98f692a2009-05-28 13:41:44 +00004109 if (ngx_strcmp(value[1].data, "on") == 0) {
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004110 return NGX_CONF_OK;
4111 }
4112
4113 /* include the terminating '\0' into script */
4114 value[1].len++;
4115
4116 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
4117
4118 sc.cf = cf;
4119 sc.source = &value[1];
4120 sc.lengths = &plcf->upstream.store_lengths;
4121 sc.values = &plcf->upstream.store_values;
Igor Sysoevbfb23bf2007-10-09 20:11:03 +00004122 sc.variables = ngx_http_script_variables_count(&value[1]);
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004123 sc.complete_lengths = 1;
4124 sc.complete_values = 1;
4125
4126 if (ngx_http_script_compile(&sc) != NGX_OK) {
4127 return NGX_CONF_ERROR;
4128 }
4129
4130 return NGX_CONF_OK;
4131}
4132
4133
Igor Sysoev52859f22009-03-23 13:14:51 +00004134#if (NGX_HTTP_CACHE)
4135
4136static char *
4137ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4138{
4139 ngx_http_proxy_loc_conf_t *plcf = conf;
4140
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +03004141 ngx_str_t *value;
4142 ngx_http_complex_value_t cv;
4143 ngx_http_compile_complex_value_t ccv;
Igor Sysoev52859f22009-03-23 13:14:51 +00004144
4145 value = cf->args->elts;
4146
Valentin Bartenev5de66622014-12-22 12:59:02 +03004147 if (plcf->upstream.cache != NGX_CONF_UNSET) {
Igor Sysoev52859f22009-03-23 13:14:51 +00004148 return "is duplicate";
4149 }
4150
4151 if (ngx_strcmp(value[1].data, "off") == 0) {
Valentin Bartenev5de66622014-12-22 12:59:02 +03004152 plcf->upstream.cache = 0;
Igor Sysoev52859f22009-03-23 13:14:51 +00004153 return NGX_CONF_OK;
4154 }
4155
Valentin Barteneva4b7b102014-12-22 12:58:56 +03004156 if (plcf->upstream.store > 0) {
Igor Sysoev98f692a2009-05-28 13:41:44 +00004157 return "is incompatible with \"proxy_store\"";
4158 }
4159
Valentin Bartenev5de66622014-12-22 12:59:02 +03004160 plcf->upstream.cache = 1;
4161
Valentin Bartenev9a0eb4f2014-12-22 12:59:09 +03004162 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4163
4164 ccv.cf = cf;
4165 ccv.value = &value[1];
4166 ccv.complex_value = &cv;
4167
4168 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4169 return NGX_CONF_ERROR;
4170 }
4171
4172 if (cv.lengths != NULL) {
4173
4174 plcf->upstream.cache_value = ngx_palloc(cf->pool,
4175 sizeof(ngx_http_complex_value_t));
4176 if (plcf->upstream.cache_value == NULL) {
4177 return NGX_CONF_ERROR;
4178 }
4179
4180 *plcf->upstream.cache_value = cv;
4181
4182 return NGX_CONF_OK;
4183 }
4184
Valentin Bartenev5de66622014-12-22 12:59:02 +03004185 plcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
4186 &ngx_http_proxy_module);
4187 if (plcf->upstream.cache_zone == NULL) {
Igor Sysoev52859f22009-03-23 13:14:51 +00004188 return NGX_CONF_ERROR;
4189 }
4190
4191 return NGX_CONF_OK;
4192}
4193
Igor Sysoev44a69c82009-04-06 08:58:44 +00004194
4195static char *
4196ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4197{
4198 ngx_http_proxy_loc_conf_t *plcf = conf;
4199
4200 ngx_str_t *value;
4201 ngx_http_compile_complex_value_t ccv;
4202
4203 value = cf->args->elts;
4204
Ruslan Ermilov73fb7e82012-12-06 23:03:53 +00004205 if (plcf->cache_key.value.data) {
Igor Sysoev44a69c82009-04-06 08:58:44 +00004206 return "is duplicate";
4207 }
4208
4209 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4210
4211 ccv.cf = cf;
4212 ccv.value = &value[1];
4213 ccv.complex_value = &plcf->cache_key;
4214
4215 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4216 return NGX_CONF_ERROR;
4217 }
4218
4219 return NGX_CONF_OK;
4220}
4221
Igor Sysoev52859f22009-03-23 13:14:51 +00004222#endif
4223
4224
Piotr Sikoraa9d9b092014-10-30 04:30:41 -07004225#if (NGX_HTTP_SSL)
4226
4227static char *
4228ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4229{
4230 ngx_http_proxy_loc_conf_t *plcf = conf;
4231
4232 ngx_str_t *value;
4233
4234 if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
4235 return "is duplicate";
4236 }
4237
4238 value = cf->args->elts;
4239
4240 plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
4241
4242 if (plcf->ssl_passwords == NULL) {
4243 return NGX_CONF_ERROR;
4244 }
4245
4246 return NGX_CONF_OK;
4247}
4248
4249#endif
4250
4251
Igor Sysoevfbd9b432007-07-13 08:30:34 +00004252static char *
Igor Sysoev02f742b2005-04-08 15:18:55 +00004253ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
4254{
4255#if (NGX_FREEBSD)
4256 ssize_t *np = data;
4257
Igor Sysoev08e63d42006-08-14 15:09:38 +00004258 if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
Igor Sysoev02f742b2005-04-08 15:18:55 +00004259 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4260 "\"proxy_send_lowat\" must be less than %d "
4261 "(sysctl net.inet.tcp.sendspace)",
4262 ngx_freebsd_net_inet_tcp_sendspace);
4263
4264 return NGX_CONF_ERROR;
4265 }
4266
4267#elif !(NGX_HAVE_SO_SNDLOWAT)
4268 ssize_t *np = data;
4269
4270 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4271 "\"proxy_send_lowat\" is not supported, ignored");
4272
4273 *np = 0;
4274
4275#endif
4276
4277 return NGX_CONF_OK;
4278}
Igor Sysoev3d2fd182006-12-04 16:46:13 +00004279
4280
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004281#if (NGX_HTTP_SSL)
4282
4283static ngx_int_t
4284ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
4285{
4286 ngx_pool_cleanup_t *cln;
4287
4288 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
4289 if (plcf->upstream.ssl == NULL) {
4290 return NGX_ERROR;
4291 }
4292
4293 plcf->upstream.ssl->log = cf->log;
4294
Andrei Belov003b2cd2013-09-19 18:30:33 +04004295 if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004296 != NGX_OK)
4297 {
4298 return NGX_ERROR;
4299 }
4300
Maxim Dounin93eb94d2014-04-18 20:13:24 +04004301 cln = ngx_pool_cleanup_add(cf->pool, 0);
4302 if (cln == NULL) {
4303 return NGX_ERROR;
4304 }
4305
4306 cln->handler = ngx_ssl_cleanup_ctx;
4307 cln->data = plcf->upstream.ssl;
4308
Piotr Sikoraa9d9b092014-10-30 04:30:41 -07004309 if (plcf->ssl_certificate.len) {
4310
4311 if (plcf->ssl_certificate_key.len == 0) {
4312 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
4313 "no \"proxy_ssl_certificate_key\" is defined "
4314 "for certificate \"%V\"", &plcf->ssl_certificate);
4315 return NGX_ERROR;
4316 }
4317
4318 if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate,
4319 &plcf->ssl_certificate_key, plcf->ssl_passwords)
4320 != NGX_OK)
4321 {
4322 return NGX_ERROR;
4323 }
4324 }
4325
Piotr Sikora43736b12013-09-23 15:58:28 -07004326 if (SSL_CTX_set_cipher_list(plcf->upstream.ssl->ctx,
4327 (const char *) plcf->ssl_ciphers.data)
4328 == 0)
4329 {
4330 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
4331 "SSL_CTX_set_cipher_list(\"%V\") failed",
4332 &plcf->ssl_ciphers);
4333 return NGX_ERROR;
4334 }
4335
Maxim Dounin27475dd2014-04-18 20:13:30 +04004336 if (plcf->upstream.ssl_verify) {
4337 if (plcf->ssl_trusted_certificate.len == 0) {
4338 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
4339 "no proxy_ssl_trusted_certificate for proxy_ssl_verify");
4340 return NGX_ERROR;
4341 }
4342
4343 if (ngx_ssl_trusted_certificate(cf, plcf->upstream.ssl,
4344 &plcf->ssl_trusted_certificate,
4345 plcf->ssl_verify_depth)
4346 != NGX_OK)
4347 {
4348 return NGX_ERROR;
4349 }
4350
4351 if (ngx_ssl_crl(cf, plcf->upstream.ssl, &plcf->ssl_crl) != NGX_OK) {
4352 return NGX_ERROR;
4353 }
4354 }
4355
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004356 return NGX_OK;
4357}
4358
4359#endif
4360
4361
Igor Sysoev52859f22009-03-23 13:14:51 +00004362static void
4363ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004364{
Igor Sysoevc9491d12008-08-26 14:24:14 +00004365 if (u->family != AF_UNIX) {
Igor Sysoev52859f22009-03-23 13:14:51 +00004366
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004367 if (u->no_port || u->port == u->default_port) {
Igor Sysoev52859f22009-03-23 13:14:51 +00004368
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004369 v->host_header = u->host;
4370
4371 if (u->default_port == 80) {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00004372 ngx_str_set(&v->port, "80");
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004373
4374 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00004375 ngx_str_set(&v->port, "443");
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004376 }
4377
4378 } else {
Igor Sysoev00e03772007-11-28 19:55:31 +00004379 v->host_header.len = u->host.len + 1 + u->port_text.len;
4380 v->host_header.data = u->host.data;
4381 v->port = u->port_text;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004382 }
4383
Igor Sysoev52859f22009-03-23 13:14:51 +00004384 v->key_start.len += v->host_header.len;
4385
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004386 } else {
Igor Sysoev05b1a8f2010-05-14 09:56:37 +00004387 ngx_str_set(&v->host_header, "localhost");
4388 ngx_str_null(&v->port);
Igor Sysoev52859f22009-03-23 13:14:51 +00004389 v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004390 }
4391
4392 v->uri = u->uri;
Igor Sysoev96dd8af2007-11-27 13:34:13 +00004393}