3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
13 typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t
;
15 typedef ngx_int_t (*ngx_http_proxy_redirect_pt
)(ngx_http_request_t
*r
,
16 ngx_table_elt_t
*h
, size_t prefix
, ngx_http_proxy_redirect_t
*pr
);
18 struct ngx_http_proxy_redirect_s
{
19 ngx_http_proxy_redirect_pt handler
;
36 ngx_str_t host_header
;
39 } ngx_http_proxy_vars_t
;
43 ngx_http_upstream_conf_t upstream
;
46 ngx_array_t
*body_set_len
;
47 ngx_array_t
*body_set
;
48 ngx_array_t
*headers_set_len
;
49 ngx_array_t
*headers_set
;
50 ngx_hash_t headers_set_hash
;
52 ngx_array_t
*headers_source
;
53 ngx_array_t
*headers_names
;
55 ngx_array_t
*proxy_lengths
;
56 ngx_array_t
*proxy_values
;
58 ngx_array_t
*redirects
;
60 ngx_str_t body_source
;
66 ngx_http_proxy_vars_t vars
;
70 ngx_uint_t headers_hash_max_size
;
71 ngx_uint_t headers_hash_bucket_size
;
72 } ngx_http_proxy_loc_conf_t
;
77 ngx_uint_t status_count
;
81 ngx_http_proxy_vars_t vars
;
83 size_t internal_body_length
;
84 } ngx_http_proxy_ctx_t
;
87 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
90 static ngx_int_t
ngx_http_proxy_eval(ngx_http_request_t
*r
,
91 ngx_http_proxy_ctx_t
*ctx
, ngx_http_proxy_loc_conf_t
*plcf
);
92 static ngx_int_t
ngx_http_proxy_create_request(ngx_http_request_t
*r
);
93 static ngx_int_t
ngx_http_proxy_reinit_request(ngx_http_request_t
*r
);
94 static ngx_int_t
ngx_http_proxy_process_status_line(ngx_http_request_t
*r
);
95 static ngx_int_t
ngx_http_proxy_parse_status_line(ngx_http_request_t
*r
,
96 ngx_http_proxy_ctx_t
*ctx
);
97 static ngx_int_t
ngx_http_proxy_process_header(ngx_http_request_t
*r
);
98 static void ngx_http_proxy_abort_request(ngx_http_request_t
*r
);
99 static void ngx_http_proxy_finalize_request(ngx_http_request_t
*r
,
102 static ngx_int_t
ngx_http_proxy_host_variable(ngx_http_request_t
*r
,
103 ngx_http_variable_value_t
*v
, uintptr_t data
);
104 static ngx_int_t
ngx_http_proxy_port_variable(ngx_http_request_t
*r
,
105 ngx_http_variable_value_t
*v
, uintptr_t data
);
107 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t
*r
,
108 ngx_http_variable_value_t
*v
, uintptr_t data
);
110 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t
*r
,
111 ngx_http_variable_value_t
*v
, uintptr_t data
);
112 static ngx_int_t
ngx_http_proxy_rewrite_redirect(ngx_http_request_t
*r
,
113 ngx_table_elt_t
*h
, size_t prefix
);
115 static ngx_int_t
ngx_http_proxy_add_variables(ngx_conf_t
*cf
);
116 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t
*cf
);
117 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t
*cf
,
118 void *parent
, void *child
);
120 static char *ngx_http_proxy_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
122 static char *ngx_http_proxy_redirect(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
124 static char *ngx_http_proxy_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
127 static char *ngx_http_proxy_lowat_check(ngx_conf_t
*cf
, void *post
, void *data
);
129 static char *ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t
*cf
,
130 ngx_command_t
*cmd
, void *conf
);
131 static char *ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t
*cf
,
132 ngx_command_t
*cmd
, void *conf
);
135 static ngx_int_t
ngx_http_proxy_set_ssl(ngx_conf_t
*cf
,
136 ngx_http_proxy_loc_conf_t
*plcf
);
138 static ngx_int_t
ngx_http_proxy_set_vars(ngx_pool_t
*pool
, ngx_url_t
*u
,
139 ngx_http_proxy_vars_t
*v
);
142 static ngx_conf_post_t ngx_http_proxy_lowat_post
=
143 { ngx_http_proxy_lowat_check
};
146 static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks
[] = {
147 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR
},
148 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT
},
149 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
},
150 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500
},
151 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503
},
152 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404
},
153 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF
},
154 { ngx_null_string
, 0 }
158 static ngx_command_t ngx_http_proxy_commands
[] = {
160 { ngx_string("proxy_pass"),
161 NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
|NGX_HTTP_LMT_CONF
|NGX_CONF_TAKE1
,
163 NGX_HTTP_LOC_CONF_OFFSET
,
167 { ngx_string("proxy_redirect"),
168 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE12
,
169 ngx_http_proxy_redirect
,
170 NGX_HTTP_LOC_CONF_OFFSET
,
174 { ngx_string("proxy_store"),
175 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
176 ngx_http_proxy_store
,
177 NGX_HTTP_LOC_CONF_OFFSET
,
181 { ngx_string("proxy_store_access"),
182 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE123
,
183 ngx_conf_set_access_slot
,
184 NGX_HTTP_LOC_CONF_OFFSET
,
185 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.store_access
),
188 { ngx_string("proxy_buffering"),
189 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
190 ngx_conf_set_flag_slot
,
191 NGX_HTTP_LOC_CONF_OFFSET
,
192 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.buffering
),
195 { ngx_string("proxy_ignore_client_abort"),
196 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
197 ngx_conf_set_flag_slot
,
198 NGX_HTTP_LOC_CONF_OFFSET
,
199 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.ignore_client_abort
),
202 { ngx_string("proxy_connect_timeout"),
203 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
204 ngx_conf_set_msec_slot
,
205 NGX_HTTP_LOC_CONF_OFFSET
,
206 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.connect_timeout
),
209 { ngx_string("proxy_send_timeout"),
210 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
211 ngx_conf_set_msec_slot
,
212 NGX_HTTP_LOC_CONF_OFFSET
,
213 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.send_timeout
),
216 { ngx_string("proxy_send_lowat"),
217 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
218 ngx_conf_set_size_slot
,
219 NGX_HTTP_LOC_CONF_OFFSET
,
220 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.send_lowat
),
221 &ngx_http_proxy_lowat_post
},
223 { ngx_string("proxy_intercept_errors"),
224 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
225 ngx_conf_set_flag_slot
,
226 NGX_HTTP_LOC_CONF_OFFSET
,
227 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.intercept_errors
),
230 { ngx_string("proxy_set_header"),
231 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
232 ngx_conf_set_keyval_slot
,
233 NGX_HTTP_LOC_CONF_OFFSET
,
234 offsetof(ngx_http_proxy_loc_conf_t
, headers_source
),
237 { ngx_string("proxy_headers_hash_max_size"),
238 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
239 ngx_conf_set_num_slot
,
240 NGX_HTTP_LOC_CONF_OFFSET
,
241 offsetof(ngx_http_proxy_loc_conf_t
, headers_hash_max_size
),
244 { ngx_string("proxy_headers_hash_bucket_size"),
245 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
246 ngx_conf_set_num_slot
,
247 NGX_HTTP_LOC_CONF_OFFSET
,
248 offsetof(ngx_http_proxy_loc_conf_t
, headers_hash_bucket_size
),
251 { ngx_string("proxy_set_body"),
252 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
253 ngx_conf_set_str_slot
,
254 NGX_HTTP_LOC_CONF_OFFSET
,
255 offsetof(ngx_http_proxy_loc_conf_t
, body_source
),
258 { ngx_string("proxy_method"),
259 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
260 ngx_conf_set_str_slot
,
261 NGX_HTTP_LOC_CONF_OFFSET
,
262 offsetof(ngx_http_proxy_loc_conf_t
, method
),
265 { ngx_string("proxy_pass_request_headers"),
266 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
267 ngx_conf_set_flag_slot
,
268 NGX_HTTP_LOC_CONF_OFFSET
,
269 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.pass_request_headers
),
272 { ngx_string("proxy_pass_request_body"),
273 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
274 ngx_conf_set_flag_slot
,
275 NGX_HTTP_LOC_CONF_OFFSET
,
276 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.pass_request_body
),
279 { ngx_string("proxy_buffer_size"),
280 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
281 ngx_conf_set_size_slot
,
282 NGX_HTTP_LOC_CONF_OFFSET
,
283 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.buffer_size
),
286 { ngx_string("proxy_read_timeout"),
287 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
288 ngx_conf_set_msec_slot
,
289 NGX_HTTP_LOC_CONF_OFFSET
,
290 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.read_timeout
),
293 { ngx_string("proxy_buffers"),
294 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
295 ngx_conf_set_bufs_slot
,
296 NGX_HTTP_LOC_CONF_OFFSET
,
297 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.bufs
),
300 { ngx_string("proxy_busy_buffers_size"),
301 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
302 ngx_conf_set_size_slot
,
303 NGX_HTTP_LOC_CONF_OFFSET
,
304 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.busy_buffers_size_conf
),
307 { ngx_string("proxy_temp_path"),
308 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1234
,
309 ngx_conf_set_path_slot
,
310 NGX_HTTP_LOC_CONF_OFFSET
,
311 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.temp_path
),
312 (void *) ngx_garbage_collector_temp_handler
},
314 { ngx_string("proxy_max_temp_file_size"),
315 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
316 ngx_conf_set_size_slot
,
317 NGX_HTTP_LOC_CONF_OFFSET
,
318 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.max_temp_file_size_conf
),
321 { ngx_string("proxy_temp_file_write_size"),
322 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
323 ngx_conf_set_size_slot
,
324 NGX_HTTP_LOC_CONF_OFFSET
,
325 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.temp_file_write_size_conf
),
328 { ngx_string("proxy_next_upstream"),
329 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
330 ngx_conf_set_bitmask_slot
,
331 NGX_HTTP_LOC_CONF_OFFSET
,
332 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.next_upstream
),
333 &ngx_http_proxy_next_upstream_masks
},
335 { ngx_string("proxy_upstream_max_fails"),
336 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
337 ngx_http_proxy_upstream_max_fails_unsupported
,
342 { ngx_string("proxy_upstream_fail_timeout"),
343 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
344 ngx_http_proxy_upstream_fail_timeout_unsupported
,
349 { ngx_string("proxy_pass_header"),
350 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
351 ngx_conf_set_str_array_slot
,
352 NGX_HTTP_LOC_CONF_OFFSET
,
353 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.pass_headers
),
356 { ngx_string("proxy_hide_header"),
357 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
358 ngx_conf_set_str_array_slot
,
359 NGX_HTTP_LOC_CONF_OFFSET
,
360 offsetof(ngx_http_proxy_loc_conf_t
, upstream
.hide_headers
),
367 static ngx_http_module_t ngx_http_proxy_module_ctx
= {
368 ngx_http_proxy_add_variables
, /* preconfiguration */
369 NULL
, /* postconfiguration */
371 NULL
, /* create main configuration */
372 NULL
, /* init main configuration */
374 NULL
, /* create server configuration */
375 NULL
, /* merge server configuration */
377 ngx_http_proxy_create_loc_conf
, /* create location configration */
378 ngx_http_proxy_merge_loc_conf
/* merge location configration */
382 ngx_module_t ngx_http_proxy_module
= {
384 &ngx_http_proxy_module_ctx
, /* module context */
385 ngx_http_proxy_commands
, /* module directives */
386 NGX_HTTP_MODULE
, /* module type */
387 NULL
, /* init master */
388 NULL
, /* init module */
389 NULL
, /* init process */
390 NULL
, /* init thread */
391 NULL
, /* exit thread */
392 NULL
, /* exit process */
393 NULL
, /* exit master */
394 NGX_MODULE_V1_PADDING
398 static char ngx_http_proxy_version
[] = " HTTP/1.0" CRLF
;
401 static ngx_keyval_t ngx_http_proxy_headers
[] = {
402 { ngx_string("Host"), ngx_string("$proxy_host") },
403 { ngx_string("Connection"), ngx_string("close") },
404 { ngx_string("Keep-Alive"), ngx_string("") },
405 { ngx_string("Expect"), ngx_string("") },
406 { ngx_null_string
, ngx_null_string
}
410 static ngx_str_t ngx_http_proxy_hide_headers
[] = {
412 ngx_string("Server"),
414 ngx_string("X-Accel-Expires"),
415 ngx_string("X-Accel-Redirect"),
416 ngx_string("X-Accel-Limit-Rate"),
417 ngx_string("X-Accel-Buffering"),
418 ngx_string("X-Accel-Charset"),
423 static ngx_http_variable_t ngx_http_proxy_vars
[] = {
425 { ngx_string("proxy_host"), NULL
, ngx_http_proxy_host_variable
, 0,
426 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
|NGX_HTTP_VAR_NOHASH
, 0 },
428 { ngx_string("proxy_port"), NULL
, ngx_http_proxy_port_variable
, 0,
429 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
|NGX_HTTP_VAR_NOHASH
, 0 },
431 { ngx_string("proxy_add_x_forwarded_for"), NULL
,
432 ngx_http_proxy_add_x_forwarded_for_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
435 { ngx_string("proxy_add_via"), NULL
, NULL
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
438 { ngx_string("proxy_internal_body_length"), NULL
,
439 ngx_http_proxy_internal_body_length_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
441 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
446 ngx_http_proxy_handler(ngx_http_request_t
*r
)
449 ngx_http_upstream_t
*u
;
450 ngx_http_proxy_ctx_t
*ctx
;
451 ngx_http_proxy_loc_conf_t
*plcf
;
453 u
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_upstream_t
));
455 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
460 ctx
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_proxy_ctx_t
));
465 ngx_http_set_ctx(r
, ctx
, ngx_http_proxy_module
);
467 plcf
= ngx_http_get_module_loc_conf(r
, ngx_http_proxy_module
);
469 if (plcf
->proxy_lengths
== 0) {
470 ctx
->vars
= plcf
->vars
;
471 u
->schema
= plcf
->upstream
.schema
;
473 u
->ssl
= (plcf
->upstream
.ssl
!= NULL
);
477 if (ngx_http_proxy_eval(r
, ctx
, plcf
) != NGX_OK
) {
478 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
482 u
->peer
.log
= r
->connection
->log
;
483 u
->peer
.log_error
= NGX_ERROR_ERR
;
485 u
->peer
.lock
= &r
->connection
->lock
;
488 u
->output
.tag
= (ngx_buf_tag_t
) &ngx_http_proxy_module
;
490 u
->conf
= &plcf
->upstream
;
492 u
->create_request
= ngx_http_proxy_create_request
;
493 u
->reinit_request
= ngx_http_proxy_reinit_request
;
494 u
->process_header
= ngx_http_proxy_process_status_line
;
495 u
->abort_request
= ngx_http_proxy_abort_request
;
496 u
->finalize_request
= ngx_http_proxy_finalize_request
;
498 if (plcf
->redirects
) {
499 u
->rewrite_redirect
= ngx_http_proxy_rewrite_redirect
;
502 u
->buffering
= plcf
->upstream
.buffering
;
504 u
->pipe
= ngx_pcalloc(r
->pool
, sizeof(ngx_event_pipe_t
));
505 if (u
->pipe
== NULL
) {
506 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
509 u
->pipe
->input_filter
= ngx_event_pipe_copy_input_filter
;
513 rc
= ngx_http_read_client_request_body(r
, ngx_http_upstream_init
);
515 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
) {
524 ngx_http_proxy_eval(ngx_http_request_t
*r
, ngx_http_proxy_ctx_t
*ctx
,
525 ngx_http_proxy_loc_conf_t
*plcf
)
532 if (ngx_http_script_run(r
, &proxy
, plcf
->proxy_lengths
->elts
, 0,
533 plcf
->proxy_values
->elts
)
539 if (ngx_strncasecmp(proxy
.data
, (u_char
*) "http://", 7) == 0) {
546 } else if (ngx_strncasecmp(proxy
.data
, (u_char
*) "https://", 8) == 0) {
550 r
->upstream
->ssl
= 1;
555 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
556 "invalid URL prefix in \"%V\"", &proxy
);
560 r
->upstream
->schema
.len
= add
;
561 r
->upstream
->schema
.data
= proxy
.data
;
563 ngx_memzero(&u
, sizeof(ngx_url_t
));
565 u
.url
.len
= proxy
.len
- add
;
566 u
.url
.data
= proxy
.data
+ add
;
567 u
.default_port
= port
;
571 if (ngx_parse_url(r
->pool
, &u
) != NGX_OK
) {
573 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
574 "%s in upstream \"%V\"", u
.err
, &u
.url
);
580 if (ngx_http_proxy_set_vars(r
->pool
, &u
, &ctx
->vars
) != NGX_OK
) {
584 r
->upstream
->resolved
= ngx_pcalloc(r
->pool
,
585 sizeof(ngx_http_upstream_resolved_t
));
586 if (r
->upstream
->resolved
== NULL
) {
590 r
->upstream
->resolved
->host
= u
.host
;
591 r
->upstream
->resolved
->port
= (in_port_t
) (u
.no_port
? u
.default_port
:
593 r
->upstream
->resolved
->default_port
= u
.default_port
;
600 ngx_http_proxy_create_request(ngx_http_request_t
*r
)
602 size_t len
, loc_len
, body_len
;
606 ngx_uint_t i
, unparsed_uri
;
607 ngx_chain_t
*cl
, *body
;
608 ngx_list_part_t
*part
;
609 ngx_table_elt_t
*header
;
610 ngx_http_upstream_t
*u
;
611 ngx_http_proxy_ctx_t
*ctx
;
612 ngx_http_script_code_pt code
;
613 ngx_http_script_engine_t e
, le
;
614 ngx_http_proxy_loc_conf_t
*plcf
;
615 ngx_http_script_len_code_pt lcode
;
619 plcf
= ngx_http_get_module_loc_conf(r
, ngx_http_proxy_module
);
622 /* HEAD was changed to GET to cache response */
626 } else if (plcf
->method
.len
) {
627 method
= plcf
->method
;
630 method
= r
->method_name
;
634 len
= method
.len
+ sizeof(ngx_http_proxy_version
) - 1 + sizeof(CRLF
) - 1;
640 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
642 if (plcf
->proxy_lengths
) {
643 len
+= ctx
->vars
.uri
.len
;
645 } else if (ctx
->vars
.uri
.len
== 0 && r
->valid_unparsed_uri
&& r
== r
->main
)
648 len
+= r
->unparsed_uri
.len
;
651 loc_len
= (r
->valid_location
&& ctx
->vars
.uri
.len
) ?
652 plcf
->location
.len
: 0;
654 if (r
->quoted_uri
|| r
->internal
) {
655 escape
= 2 * ngx_escape_uri(NULL
, r
->uri
.data
+ loc_len
,
656 r
->uri
.len
- loc_len
, NGX_ESCAPE_URI
);
659 len
+= ctx
->vars
.uri
.len
+ r
->uri
.len
- loc_len
+ escape
660 + sizeof("?") - 1 + r
->args
.len
;
663 ngx_http_script_flush_no_cacheable_variables(r
, plcf
->flushes
);
665 if (plcf
->body_set_len
) {
666 le
.ip
= plcf
->body_set_len
->elts
;
671 while (*(uintptr_t *) le
.ip
) {
672 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
673 body_len
+= lcode(&le
);
676 ctx
->internal_body_length
= body_len
;
680 le
.ip
= plcf
->headers_set_len
->elts
;
684 while (*(uintptr_t *) le
.ip
) {
685 while (*(uintptr_t *) le
.ip
) {
686 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
689 le
.ip
+= sizeof(uintptr_t);
693 if (plcf
->upstream
.pass_request_headers
) {
694 part
= &r
->headers_in
.headers
.part
;
697 for (i
= 0; /* void */; i
++) {
699 if (i
>= part
->nelts
) {
700 if (part
->next
== NULL
) {
709 if (ngx_hash_find(&plcf
->headers_set_hash
, header
[i
].hash
,
710 header
[i
].lowcase_key
, header
[i
].key
.len
))
715 len
+= header
[i
].key
.len
+ sizeof(": ") - 1
716 + header
[i
].value
.len
+ sizeof(CRLF
) - 1;
721 b
= ngx_create_temp_buf(r
->pool
, len
);
726 cl
= ngx_alloc_chain_link(r
->pool
);
734 /* the request line */
736 b
->last
= ngx_copy(b
->last
, method
.data
, method
.len
);
738 u
->uri
.data
= b
->last
;
740 if (plcf
->proxy_lengths
) {
741 b
->last
= ngx_copy(b
->last
, ctx
->vars
.uri
.data
, ctx
->vars
.uri
.len
);
743 } else if (unparsed_uri
) {
744 b
->last
= ngx_copy(b
->last
, r
->unparsed_uri
.data
, r
->unparsed_uri
.len
);
747 if (r
->valid_location
) {
748 b
->last
= ngx_copy(b
->last
, ctx
->vars
.uri
.data
, ctx
->vars
.uri
.len
);
752 ngx_escape_uri(b
->last
, r
->uri
.data
+ loc_len
,
753 r
->uri
.len
- loc_len
, NGX_ESCAPE_URI
);
754 b
->last
+= r
->uri
.len
- loc_len
+ escape
;
757 b
->last
= ngx_copy(b
->last
, r
->uri
.data
+ loc_len
,
758 r
->uri
.len
- loc_len
);
761 if (r
->args
.len
> 0) {
763 b
->last
= ngx_copy(b
->last
, r
->args
.data
, r
->args
.len
);
767 u
->uri
.len
= b
->last
- u
->uri
.data
;
769 b
->last
= ngx_cpymem(b
->last
, ngx_http_proxy_version
,
770 sizeof(ngx_http_proxy_version
) - 1);
772 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
774 e
.ip
= plcf
->headers_set
->elts
;
779 le
.ip
= plcf
->headers_set_len
->elts
;
781 while (*(uintptr_t *) le
.ip
) {
782 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
784 /* skip the header line name length */
787 if (*(ngx_http_script_len_code_pt
*) le
.ip
) {
789 for (len
= 0; *(uintptr_t *) le
.ip
; len
+= lcode(&le
)) {
790 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
793 e
.skip
= (len
== sizeof(CRLF
) - 1) ? 1 : 0;
799 le
.ip
+= sizeof(uintptr_t);
801 while (*(uintptr_t *) e
.ip
) {
802 code
= *(ngx_http_script_code_pt
*) e
.ip
;
803 code((ngx_http_script_engine_t
*) &e
);
805 e
.ip
+= sizeof(uintptr_t);
811 if (plcf
->upstream
.pass_request_headers
) {
812 part
= &r
->headers_in
.headers
.part
;
815 for (i
= 0; /* void */; i
++) {
817 if (i
>= part
->nelts
) {
818 if (part
->next
== NULL
) {
827 if (ngx_hash_find(&plcf
->headers_set_hash
, header
[i
].hash
,
828 header
[i
].lowcase_key
, header
[i
].key
.len
))
833 b
->last
= ngx_copy(b
->last
, header
[i
].key
.data
, header
[i
].key
.len
);
835 *b
->last
++ = ':'; *b
->last
++ = ' ';
837 b
->last
= ngx_copy(b
->last
, header
[i
].value
.data
,
838 header
[i
].value
.len
);
840 *b
->last
++ = CR
; *b
->last
++ = LF
;
842 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
843 "http proxy header: \"%V: %V\"",
844 &header
[i
].key
, &header
[i
].value
);
849 /* add "\r\n" at the header end */
850 *b
->last
++ = CR
; *b
->last
++ = LF
;
852 if (plcf
->body_set
) {
853 e
.ip
= plcf
->body_set
->elts
;
856 while (*(uintptr_t *) e
.ip
) {
857 code
= *(ngx_http_script_code_pt
*) e
.ip
;
858 code((ngx_http_script_engine_t
*) &e
);
864 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
865 "http proxy header:\n\"%*s\"",
866 (size_t) (b
->last
- b
->pos
), b
->pos
);
868 if (plcf
->body_set
== NULL
&& plcf
->upstream
.pass_request_body
) {
870 body
= u
->request_bufs
;
871 u
->request_bufs
= cl
;
874 b
= ngx_alloc_buf(r
->pool
);
879 ngx_memcpy(b
, body
->buf
, sizeof(ngx_buf_t
));
881 cl
->next
= ngx_alloc_chain_link(r
->pool
);
882 if (cl
->next
== NULL
) {
895 u
->request_bufs
= cl
;
905 ngx_http_proxy_reinit_request(ngx_http_request_t
*r
)
907 ngx_http_proxy_ctx_t
*ctx
;
909 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
916 ctx
->status_count
= 0;
917 ctx
->status_start
= NULL
;
918 ctx
->status_end
= NULL
;
920 r
->upstream
->process_header
= ngx_http_proxy_process_status_line
;
927 ngx_http_proxy_process_status_line(ngx_http_request_t
*r
)
930 ngx_http_upstream_t
*u
;
931 ngx_http_proxy_ctx_t
*ctx
;
933 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
939 rc
= ngx_http_proxy_parse_status_line(r
, ctx
);
941 if (rc
== NGX_AGAIN
) {
947 if (rc
== NGX_HTTP_PROXY_PARSE_NO_HEADER
) {
948 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
949 "upstream sent no valid HTTP/1.0 header");
953 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
957 r
->http_version
= NGX_HTTP_VERSION_9
;
958 u
->headers_in
.status_n
= NGX_HTTP_OK
;
959 u
->state
->status
= NGX_HTTP_OK
;
964 u
->headers_in
.status_n
= ctx
->status
;
965 u
->state
->status
= ctx
->status
;
967 u
->headers_in
.status_line
.len
= ctx
->status_end
- ctx
->status_start
;
968 u
->headers_in
.status_line
.data
= ngx_pnalloc(r
->pool
,
969 u
->headers_in
.status_line
.len
);
970 if (u
->headers_in
.status_line
.data
== NULL
) {
974 ngx_memcpy(u
->headers_in
.status_line
.data
, ctx
->status_start
,
975 u
->headers_in
.status_line
.len
);
977 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
978 "http proxy status %ui \"%V\"",
979 u
->headers_in
.status_n
, &u
->headers_in
.status_line
);
981 u
->process_header
= ngx_http_proxy_process_header
;
983 return ngx_http_proxy_process_header(r
);
988 ngx_http_proxy_parse_status_line(ngx_http_request_t
*r
,
989 ngx_http_proxy_ctx_t
*ctx
)
993 ngx_http_upstream_t
*u
;
1000 sw_first_major_digit
,
1002 sw_first_minor_digit
,
1005 sw_space_after_status
,
1014 for (p
= u
->buffer
.pos
; p
< u
->buffer
.last
; p
++) {
1026 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1036 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1046 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1056 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1063 state
= sw_first_major_digit
;
1066 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1070 /* the first digit of major HTTP version */
1071 case sw_first_major_digit
:
1072 if (ch
< '1' || ch
> '9') {
1073 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1076 state
= sw_major_digit
;
1079 /* the major HTTP version or dot */
1080 case sw_major_digit
:
1082 state
= sw_first_minor_digit
;
1086 if (ch
< '0' || ch
> '9') {
1087 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1092 /* the first digit of minor HTTP version */
1093 case sw_first_minor_digit
:
1094 if (ch
< '0' || ch
> '9') {
1095 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1098 state
= sw_minor_digit
;
1101 /* the minor HTTP version or the end of the request line */
1102 case sw_minor_digit
:
1108 if (ch
< '0' || ch
> '9') {
1109 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1114 /* HTTP status code */
1120 if (ch
< '0' || ch
> '9') {
1121 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1124 ctx
->status
= ctx
->status
* 10 + ch
- '0';
1126 if (++ctx
->status_count
== 3) {
1127 state
= sw_space_after_status
;
1128 ctx
->status_start
= p
- 2;
1133 /* space or end of line */
1134 case sw_space_after_status
:
1137 state
= sw_status_text
;
1139 case '.': /* IIS may send 403.1, 403.2, etc */
1140 state
= sw_status_text
;
1143 state
= sw_almost_done
;
1148 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1152 /* any text until end of line */
1153 case sw_status_text
:
1156 state
= sw_almost_done
;
1164 /* end of status line */
1165 case sw_almost_done
:
1166 ctx
->status_end
= p
- 1;
1171 return NGX_HTTP_PROXY_PARSE_NO_HEADER
;
1183 u
->buffer
.pos
= p
+ 1;
1185 if (ctx
->status_end
== NULL
) {
1186 ctx
->status_end
= p
;
1189 r
->state
= sw_start
;
1196 ngx_http_proxy_process_header(ngx_http_request_t
*r
)
1200 ngx_http_upstream_header_t
*hh
;
1201 ngx_http_upstream_main_conf_t
*umcf
;
1203 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
1207 rc
= ngx_http_parse_header_line(r
, &r
->upstream
->buffer
);
1211 /* a header line has been parsed successfully */
1213 h
= ngx_list_push(&r
->upstream
->headers_in
.headers
);
1218 h
->hash
= r
->header_hash
;
1220 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
1221 h
->value
.len
= r
->header_end
- r
->header_start
;
1223 h
->key
.data
= ngx_pnalloc(r
->pool
,
1224 h
->key
.len
+ 1 + h
->value
.len
+ 1 + h
->key
.len
);
1225 if (h
->key
.data
== NULL
) {
1229 h
->value
.data
= h
->key
.data
+ h
->key
.len
+ 1;
1230 h
->lowcase_key
= h
->key
.data
+ h
->key
.len
+ 1 + h
->value
.len
+ 1;
1232 ngx_cpystrn(h
->key
.data
, r
->header_name_start
, h
->key
.len
+ 1);
1233 ngx_cpystrn(h
->value
.data
, r
->header_start
, h
->value
.len
+ 1);
1235 if (h
->key
.len
== r
->lowcase_index
) {
1236 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
1239 ngx_strlow(h
->lowcase_key
, h
->key
.data
, h
->key
.len
);
1242 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
->hash
,
1243 h
->lowcase_key
, h
->key
.len
);
1245 if (hh
&& hh
->handler(r
, h
, hh
->offset
) != NGX_OK
) {
1249 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1250 "http proxy header: \"%V: %V\"",
1251 &h
->key
, &h
->value
);
1256 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1258 /* a whole header has been parsed successfully */
1260 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1261 "http proxy header done");
1264 * if no "Server" and "Date" in header line,
1265 * then add the special empty headers
1268 if (r
->upstream
->headers_in
.server
== NULL
) {
1269 h
= ngx_list_push(&r
->upstream
->headers_in
.headers
);
1274 h
->hash
= ngx_hash(ngx_hash(ngx_hash(ngx_hash(
1275 ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
1277 h
->key
.len
= sizeof("Server") - 1;
1278 h
->key
.data
= (u_char
*) "Server";
1280 h
->value
.data
= NULL
;
1281 h
->lowcase_key
= (u_char
*) "server";
1284 if (r
->upstream
->headers_in
.date
== NULL
) {
1285 h
= ngx_list_push(&r
->upstream
->headers_in
.headers
);
1290 h
->hash
= ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
1292 h
->key
.len
= sizeof("Date") - 1;
1293 h
->key
.data
= (u_char
*) "Date";
1295 h
->value
.data
= NULL
;
1296 h
->lowcase_key
= (u_char
*) "date";
1302 if (rc
== NGX_AGAIN
) {
1306 /* there was error while a header line parsing */
1308 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1309 "upstream sent invalid header");
1311 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1317 ngx_http_proxy_abort_request(ngx_http_request_t
*r
)
1319 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1320 "abort http proxy request");
1327 ngx_http_proxy_finalize_request(ngx_http_request_t
*r
, ngx_int_t rc
)
1329 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1330 "finalize http proxy request");
1337 ngx_http_proxy_host_variable(ngx_http_request_t
*r
,
1338 ngx_http_variable_value_t
*v
, uintptr_t data
)
1340 ngx_http_proxy_ctx_t
*ctx
;
1342 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
1349 v
->len
= ctx
->vars
.host_header
.len
;
1351 v
->no_cacheable
= 0;
1353 v
->data
= ctx
->vars
.host_header
.data
;
1360 ngx_http_proxy_port_variable(ngx_http_request_t
*r
,
1361 ngx_http_variable_value_t
*v
, uintptr_t data
)
1363 ngx_http_proxy_ctx_t
*ctx
;
1365 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
1372 v
->len
= ctx
->vars
.port
.len
;
1374 v
->no_cacheable
= 0;
1376 v
->data
= ctx
->vars
.port
.data
;
1383 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t
*r
,
1384 ngx_http_variable_value_t
*v
, uintptr_t data
)
1389 v
->no_cacheable
= 0;
1392 if (r
->headers_in
.x_forwarded_for
== NULL
) {
1393 v
->len
= r
->connection
->addr_text
.len
;
1394 v
->data
= r
->connection
->addr_text
.data
;
1398 v
->len
= r
->headers_in
.x_forwarded_for
->value
.len
1399 + sizeof(", ") - 1 + r
->connection
->addr_text
.len
;
1401 p
= ngx_pnalloc(r
->pool
, v
->len
);
1408 p
= ngx_copy(p
, r
->headers_in
.x_forwarded_for
->value
.data
,
1409 r
->headers_in
.x_forwarded_for
->value
.len
);
1411 *p
++ = ','; *p
++ = ' ';
1413 ngx_memcpy(p
, r
->connection
->addr_text
.data
, r
->connection
->addr_text
.len
);
1420 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t
*r
,
1421 ngx_http_variable_value_t
*v
, uintptr_t data
)
1423 ngx_http_proxy_ctx_t
*ctx
;
1425 ctx
= ngx_http_get_module_ctx(r
, ngx_http_proxy_module
);
1433 v
->no_cacheable
= 0;
1436 v
->data
= ngx_pnalloc(r
->connection
->pool
, NGX_SIZE_T_LEN
);
1438 if (v
->data
== NULL
) {
1442 v
->len
= ngx_sprintf(v
->data
, "%uz", ctx
->internal_body_length
) - v
->data
;
1449 ngx_http_proxy_rewrite_redirect(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1454 ngx_http_proxy_loc_conf_t
*plcf
;
1455 ngx_http_proxy_redirect_t
*pr
;
1457 plcf
= ngx_http_get_module_loc_conf(r
, ngx_http_proxy_module
);
1459 pr
= plcf
->redirects
->elts
;
1462 return NGX_DECLINED
;
1465 for (i
= 0; i
< plcf
->redirects
->nelts
; i
++) {
1466 rc
= pr
[i
].handler(r
, h
, prefix
, &pr
[i
]);
1468 if (rc
!= NGX_DECLINED
) {
1473 return NGX_DECLINED
;
1478 ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1479 size_t prefix
, ngx_http_proxy_redirect_t
*pr
)
1484 if (pr
->redirect
.len
> h
->value
.len
- prefix
1485 || ngx_rstrncmp(h
->value
.data
+ prefix
, pr
->redirect
.data
,
1486 pr
->redirect
.len
) != 0)
1488 return NGX_DECLINED
;
1491 len
= prefix
+ pr
->replacement
.text
.len
+ h
->value
.len
- pr
->redirect
.len
;
1493 data
= ngx_pnalloc(r
->pool
, len
);
1500 p
= ngx_copy(p
, h
->value
.data
, prefix
);
1502 if (pr
->replacement
.text
.len
) {
1503 p
= ngx_copy(p
, pr
->replacement
.text
.data
, pr
->replacement
.text
.len
);
1506 ngx_memcpy(p
, h
->value
.data
+ prefix
+ pr
->redirect
.len
,
1507 h
->value
.len
- pr
->redirect
.len
- prefix
);
1510 h
->value
.data
= data
;
1517 ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1518 size_t prefix
, ngx_http_proxy_redirect_t
*pr
)
1522 ngx_http_script_code_pt code
;
1523 ngx_http_script_engine_t e
;
1524 ngx_http_script_len_code_pt lcode
;
1526 if (pr
->redirect
.len
> h
->value
.len
- prefix
1527 || ngx_rstrncmp(h
->value
.data
+ prefix
, pr
->redirect
.data
,
1528 pr
->redirect
.len
) != 0)
1530 return NGX_DECLINED
;
1533 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
1535 e
.ip
= pr
->replacement
.vars
.lengths
;
1538 len
= prefix
+ h
->value
.len
- pr
->redirect
.len
;
1540 while (*(uintptr_t *) e
.ip
) {
1541 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
1545 data
= ngx_pnalloc(r
->pool
, len
);
1552 p
= ngx_copy(p
, h
->value
.data
, prefix
);
1554 e
.ip
= pr
->replacement
.vars
.values
;
1557 while (*(uintptr_t *) e
.ip
) {
1558 code
= *(ngx_http_script_code_pt
*) e
.ip
;
1562 ngx_memcpy(e
.pos
, h
->value
.data
+ prefix
+ pr
->redirect
.len
,
1563 h
->value
.len
- pr
->redirect
.len
- prefix
);
1566 h
->value
.data
= data
;
1573 ngx_http_proxy_add_variables(ngx_conf_t
*cf
)
1575 ngx_http_variable_t
*var
, *v
;
1577 for (v
= ngx_http_proxy_vars
; v
->name
.len
; v
++) {
1578 var
= ngx_http_add_variable(cf
, &v
->name
, v
->flags
);
1583 var
->get_handler
= v
->get_handler
;
1584 var
->data
= v
->data
;
1592 ngx_http_proxy_create_loc_conf(ngx_conf_t
*cf
)
1594 ngx_http_proxy_loc_conf_t
*conf
;
1596 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_proxy_loc_conf_t
));
1598 return NGX_CONF_ERROR
;
1602 * set by ngx_pcalloc():
1604 * conf->upstream.bufs.num = 0;
1605 * conf->upstream.next_upstream = 0;
1606 * conf->upstream.temp_path = NULL;
1607 * conf->upstream.hide_headers_hash = { NULL, 0 };
1608 * conf->upstream.schema = { 0, NULL };
1609 * conf->upstream.uri = { 0, NULL };
1610 * conf->upstream.location = NULL;
1611 * conf->upstream.store_lengths = NULL;
1612 * conf->upstream.store_values = NULL;
1614 * conf->method = NULL;
1615 * conf->headers_source = NULL;
1616 * conf->headers_set_len = NULL;
1617 * conf->headers_set = NULL;
1618 * conf->headers_set_hash = NULL;
1619 * conf->body_set_len = NULL;
1620 * conf->body_set = NULL;
1621 * conf->body_source = { 0, NULL };
1622 * conf->rewrite_locations = NULL;
1625 conf
->upstream
.store
= NGX_CONF_UNSET
;
1626 conf
->upstream
.store_access
= NGX_CONF_UNSET_UINT
;
1627 conf
->upstream
.buffering
= NGX_CONF_UNSET
;
1628 conf
->upstream
.ignore_client_abort
= NGX_CONF_UNSET
;
1630 conf
->upstream
.connect_timeout
= NGX_CONF_UNSET_MSEC
;
1631 conf
->upstream
.send_timeout
= NGX_CONF_UNSET_MSEC
;
1632 conf
->upstream
.read_timeout
= NGX_CONF_UNSET_MSEC
;
1634 conf
->upstream
.send_lowat
= NGX_CONF_UNSET_SIZE
;
1635 conf
->upstream
.buffer_size
= NGX_CONF_UNSET_SIZE
;
1637 conf
->upstream
.busy_buffers_size_conf
= NGX_CONF_UNSET_SIZE
;
1638 conf
->upstream
.max_temp_file_size_conf
= NGX_CONF_UNSET_SIZE
;
1639 conf
->upstream
.temp_file_write_size_conf
= NGX_CONF_UNSET_SIZE
;
1641 conf
->upstream
.pass_request_headers
= NGX_CONF_UNSET
;
1642 conf
->upstream
.pass_request_body
= NGX_CONF_UNSET
;
1644 conf
->upstream
.hide_headers
= NGX_CONF_UNSET_PTR
;
1645 conf
->upstream
.pass_headers
= NGX_CONF_UNSET_PTR
;
1647 conf
->upstream
.intercept_errors
= NGX_CONF_UNSET
;
1649 /* "proxy_cyclic_temp_file" is disabled */
1650 conf
->upstream
.cyclic_temp_file
= 0;
1652 conf
->redirect
= NGX_CONF_UNSET
;
1653 conf
->upstream
.change_buffering
= 1;
1655 conf
->headers_hash_max_size
= NGX_CONF_UNSET_UINT
;
1656 conf
->headers_hash_bucket_size
= NGX_CONF_UNSET_UINT
;
1663 ngx_http_proxy_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
1665 ngx_http_proxy_loc_conf_t
*prev
= parent
;
1666 ngx_http_proxy_loc_conf_t
*conf
= child
;
1672 ngx_keyval_t
*src
, *s
, *h
;
1674 ngx_hash_init_t hash
;
1675 ngx_http_proxy_redirect_t
*pr
;
1676 ngx_http_script_compile_t sc
;
1677 ngx_http_script_copy_code_t
*copy
;
1679 if (conf
->upstream
.store
!= 0) {
1680 ngx_conf_merge_value(conf
->upstream
.store
,
1681 prev
->upstream
.store
, 0);
1683 if (conf
->upstream
.store_lengths
== NULL
) {
1684 conf
->upstream
.store_lengths
= prev
->upstream
.store_lengths
;
1685 conf
->upstream
.store_values
= prev
->upstream
.store_values
;
1689 ngx_conf_merge_uint_value(conf
->upstream
.store_access
,
1690 prev
->upstream
.store_access
, 0600);
1692 ngx_conf_merge_value(conf
->upstream
.buffering
,
1693 prev
->upstream
.buffering
, 1);
1695 ngx_conf_merge_value(conf
->upstream
.ignore_client_abort
,
1696 prev
->upstream
.ignore_client_abort
, 0);
1698 ngx_conf_merge_msec_value(conf
->upstream
.connect_timeout
,
1699 prev
->upstream
.connect_timeout
, 60000);
1701 ngx_conf_merge_msec_value(conf
->upstream
.send_timeout
,
1702 prev
->upstream
.send_timeout
, 60000);
1704 ngx_conf_merge_msec_value(conf
->upstream
.read_timeout
,
1705 prev
->upstream
.read_timeout
, 60000);
1707 ngx_conf_merge_size_value(conf
->upstream
.send_lowat
,
1708 prev
->upstream
.send_lowat
, 0);
1710 ngx_conf_merge_size_value(conf
->upstream
.buffer_size
,
1711 prev
->upstream
.buffer_size
,
1712 (size_t) ngx_pagesize
);
1714 ngx_conf_merge_bufs_value(conf
->upstream
.bufs
, prev
->upstream
.bufs
,
1717 if (conf
->upstream
.bufs
.num
< 2) {
1718 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1719 "there must be at least 2 \"proxy_buffers\"");
1720 return NGX_CONF_ERROR
;
1724 size
= conf
->upstream
.buffer_size
;
1725 if (size
< conf
->upstream
.bufs
.size
) {
1726 size
= conf
->upstream
.bufs
.size
;
1730 ngx_conf_merge_size_value(conf
->upstream
.busy_buffers_size_conf
,
1731 prev
->upstream
.busy_buffers_size_conf
,
1732 NGX_CONF_UNSET_SIZE
);
1734 if (conf
->upstream
.busy_buffers_size_conf
== NGX_CONF_UNSET_SIZE
) {
1735 conf
->upstream
.busy_buffers_size
= 2 * size
;
1737 conf
->upstream
.busy_buffers_size
=
1738 conf
->upstream
.busy_buffers_size_conf
;
1741 if (conf
->upstream
.busy_buffers_size
< size
) {
1742 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1743 "\"proxy_busy_buffers_size\" must be equal or bigger than "
1744 "maximum of the value of \"proxy_buffer_size\" and "
1745 "one of the \"proxy_buffers\"");
1747 return NGX_CONF_ERROR
;
1750 if (conf
->upstream
.busy_buffers_size
1751 > (conf
->upstream
.bufs
.num
- 1) * conf
->upstream
.bufs
.size
)
1753 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1754 "\"proxy_busy_buffers_size\" must be less than "
1755 "the size of all \"proxy_buffers\" minus one buffer");
1757 return NGX_CONF_ERROR
;
1761 ngx_conf_merge_size_value(conf
->upstream
.temp_file_write_size_conf
,
1762 prev
->upstream
.temp_file_write_size_conf
,
1763 NGX_CONF_UNSET_SIZE
);
1765 if (conf
->upstream
.temp_file_write_size_conf
== NGX_CONF_UNSET_SIZE
) {
1766 conf
->upstream
.temp_file_write_size
= 2 * size
;
1768 conf
->upstream
.temp_file_write_size
=
1769 conf
->upstream
.temp_file_write_size_conf
;
1772 if (conf
->upstream
.temp_file_write_size
< size
) {
1773 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1774 "\"proxy_temp_file_write_size\" must be equal or bigger than "
1775 "maximum of the value of \"proxy_buffer_size\" and "
1776 "one of the \"proxy_buffers\"");
1778 return NGX_CONF_ERROR
;
1781 ngx_conf_merge_size_value(conf
->upstream
.max_temp_file_size_conf
,
1782 prev
->upstream
.max_temp_file_size_conf
,
1783 NGX_CONF_UNSET_SIZE
);
1785 if (conf
->upstream
.max_temp_file_size_conf
== NGX_CONF_UNSET_SIZE
) {
1786 conf
->upstream
.max_temp_file_size
= 1024 * 1024 * 1024;
1788 conf
->upstream
.max_temp_file_size
=
1789 conf
->upstream
.max_temp_file_size_conf
;
1792 if (conf
->upstream
.max_temp_file_size
!= 0
1793 && conf
->upstream
.max_temp_file_size
< size
)
1795 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1796 "\"proxy_max_temp_file_size\" must be equal to zero to disable "
1797 "the temporary files usage or must be equal or bigger than "
1798 "maximum of the value of \"proxy_buffer_size\" and "
1799 "one of the \"proxy_buffers\"");
1801 return NGX_CONF_ERROR
;
1805 ngx_conf_merge_bitmask_value(conf
->upstream
.next_upstream
,
1806 prev
->upstream
.next_upstream
,
1807 (NGX_CONF_BITMASK_SET
1808 |NGX_HTTP_UPSTREAM_FT_ERROR
1809 |NGX_HTTP_UPSTREAM_FT_TIMEOUT
));
1811 if (conf
->upstream
.next_upstream
& NGX_HTTP_UPSTREAM_FT_OFF
) {
1812 conf
->upstream
.next_upstream
= NGX_CONF_BITMASK_SET
1813 |NGX_HTTP_UPSTREAM_FT_OFF
;
1816 ngx_conf_merge_path_value(conf
->upstream
.temp_path
,
1817 prev
->upstream
.temp_path
,
1818 NGX_HTTP_PROXY_TEMP_PATH
, 1, 2, 0,
1819 ngx_garbage_collector_temp_handler
, cf
);
1821 if (conf
->method
.len
== 0) {
1822 conf
->method
= prev
->method
;
1825 conf
->method
.data
[conf
->method
.len
] = ' ';
1829 ngx_conf_merge_value(conf
->upstream
.pass_request_headers
,
1830 prev
->upstream
.pass_request_headers
, 1);
1831 ngx_conf_merge_value(conf
->upstream
.pass_request_body
,
1832 prev
->upstream
.pass_request_body
, 1);
1834 ngx_conf_merge_value(conf
->upstream
.intercept_errors
,
1835 prev
->upstream
.intercept_errors
, 0);
1837 ngx_conf_merge_value(conf
->redirect
, prev
->redirect
, 1);
1839 if (conf
->redirect
) {
1841 if (conf
->redirects
== NULL
) {
1842 conf
->redirects
= prev
->redirects
;
1845 if (conf
->redirects
== NULL
&& conf
->url
.data
) {
1847 conf
->redirects
= ngx_array_create(cf
->pool
, 1,
1848 sizeof(ngx_http_proxy_redirect_t
));
1849 if (conf
->redirects
== NULL
) {
1850 return NGX_CONF_ERROR
;
1853 pr
= ngx_array_push(conf
->redirects
);
1855 return NGX_CONF_ERROR
;
1858 pr
->handler
= ngx_http_proxy_rewrite_redirect_text
;
1859 pr
->redirect
= conf
->url
;
1861 if (conf
->vars
.uri
.len
) {
1862 pr
->replacement
.text
= conf
->location
;
1865 pr
->replacement
.text
.len
= 0;
1866 pr
->replacement
.text
.data
= NULL
;
1872 if (prev
->proxy_lengths
) {
1873 conf
->proxy_lengths
= prev
->proxy_lengths
;
1874 conf
->proxy_values
= prev
->proxy_values
;
1877 ngx_conf_merge_uint_value(conf
->headers_hash_max_size
,
1878 prev
->headers_hash_max_size
, 512);
1880 ngx_conf_merge_uint_value(conf
->headers_hash_bucket_size
,
1881 prev
->headers_hash_bucket_size
, 64);
1883 conf
->headers_hash_bucket_size
= ngx_align(conf
->headers_hash_bucket_size
,
1884 ngx_cacheline_size
);
1886 hash
.max_size
= conf
->headers_hash_max_size
;
1887 hash
.bucket_size
= conf
->headers_hash_bucket_size
;
1888 hash
.name
= "proxy_headers_hash";
1890 if (ngx_http_upstream_hide_headers_hash(cf
, &conf
->upstream
,
1892 ngx_http_proxy_hide_headers
, &hash
)
1895 return NGX_CONF_ERROR
;
1898 if (conf
->upstream
.upstream
== NULL
) {
1899 conf
->upstream
.upstream
= prev
->upstream
.upstream
;
1901 conf
->vars
= prev
->vars
;
1902 conf
->upstream
.schema
= prev
->upstream
.schema
;
1906 if (conf
->body_source
.data
== NULL
) {
1907 conf
->body_source
= prev
->body_source
;
1908 conf
->body_set_len
= prev
->body_set_len
;
1909 conf
->body_set
= prev
->body_set
;
1912 if (conf
->body_source
.data
&& conf
->body_set_len
== NULL
) {
1914 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1917 sc
.source
= &conf
->body_source
;
1918 sc
.flushes
= &conf
->flushes
;
1919 sc
.lengths
= &conf
->body_set_len
;
1920 sc
.values
= &conf
->body_set
;
1921 sc
.complete_lengths
= 1;
1922 sc
.complete_values
= 1;
1924 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1925 return NGX_CONF_ERROR
;
1928 if (conf
->headers_source
== NULL
) {
1929 conf
->headers_source
= ngx_array_create(cf
->pool
, 4,
1930 sizeof(ngx_keyval_t
));
1931 if (conf
->headers_source
== NULL
) {
1932 return NGX_CONF_ERROR
;
1936 s
= ngx_array_push(conf
->headers_source
);
1938 return NGX_CONF_ERROR
;
1941 s
->key
.len
= sizeof("Content-Length") - 1;
1942 s
->key
.data
= (u_char
*) "Content-Length";
1943 s
->value
.len
= sizeof("$proxy_internal_body_length") - 1;
1944 s
->value
.data
= (u_char
*) "$proxy_internal_body_length";
1948 if (conf
->headers_source
== NULL
) {
1949 conf
->flushes
= prev
->flushes
;
1950 conf
->headers_set_len
= prev
->headers_set_len
;
1951 conf
->headers_set
= prev
->headers_set
;
1952 conf
->headers_set_hash
= prev
->headers_set_hash
;
1953 conf
->headers_source
= prev
->headers_source
;
1956 if (conf
->headers_set_hash
.buckets
) {
1961 conf
->headers_names
= ngx_array_create(cf
->pool
, 4, sizeof(ngx_hash_key_t
));
1962 if (conf
->headers_names
== NULL
) {
1963 return NGX_CONF_ERROR
;
1966 if (conf
->headers_source
== NULL
) {
1967 conf
->headers_source
= ngx_array_create(cf
->pool
, 4,
1968 sizeof(ngx_keyval_t
));
1969 if (conf
->headers_source
== NULL
) {
1970 return NGX_CONF_ERROR
;
1974 conf
->headers_set_len
= ngx_array_create(cf
->pool
, 64, 1);
1975 if (conf
->headers_set_len
== NULL
) {
1976 return NGX_CONF_ERROR
;
1979 conf
->headers_set
= ngx_array_create(cf
->pool
, 512, 1);
1980 if (conf
->headers_set
== NULL
) {
1981 return NGX_CONF_ERROR
;
1985 src
= conf
->headers_source
->elts
;
1987 for (h
= ngx_http_proxy_headers
; h
->key
.len
; h
++) {
1989 for (i
= 0; i
< conf
->headers_source
->nelts
; i
++) {
1990 if (ngx_strcasecmp(h
->key
.data
, src
[i
].key
.data
) == 0) {
1995 s
= ngx_array_push(conf
->headers_source
);
1997 return NGX_CONF_ERROR
;
2002 src
= conf
->headers_source
->elts
;
2010 src
= conf
->headers_source
->elts
;
2011 for (i
= 0; i
< conf
->headers_source
->nelts
; i
++) {
2013 hk
= ngx_array_push(conf
->headers_names
);
2015 return NGX_CONF_ERROR
;
2018 hk
->key
= src
[i
].key
;
2019 hk
->key_hash
= ngx_hash_key_lc(src
[i
].key
.data
, src
[i
].key
.len
);
2020 hk
->value
= (void *) 1;
2022 if (src
[i
].value
.len
== 0) {
2026 if (ngx_http_script_variables_count(&src
[i
].value
) == 0) {
2027 copy
= ngx_array_push_n(conf
->headers_set_len
,
2028 sizeof(ngx_http_script_copy_code_t
));
2030 return NGX_CONF_ERROR
;
2033 copy
->code
= (ngx_http_script_code_pt
)
2034 ngx_http_script_copy_len_code
;
2035 copy
->len
= src
[i
].key
.len
+ sizeof(": ") - 1
2036 + src
[i
].value
.len
+ sizeof(CRLF
) - 1;
2039 size
= (sizeof(ngx_http_script_copy_code_t
)
2040 + src
[i
].key
.len
+ sizeof(": ") - 1
2041 + src
[i
].value
.len
+ sizeof(CRLF
) - 1
2042 + sizeof(uintptr_t) - 1)
2043 & ~(sizeof(uintptr_t) - 1);
2045 copy
= ngx_array_push_n(conf
->headers_set
, size
);
2047 return NGX_CONF_ERROR
;
2050 copy
->code
= ngx_http_script_copy_code
;
2051 copy
->len
= src
[i
].key
.len
+ sizeof(": ") - 1
2052 + src
[i
].value
.len
+ sizeof(CRLF
) - 1;
2054 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
2056 p
= ngx_cpymem(p
, src
[i
].key
.data
, src
[i
].key
.len
);
2057 *p
++ = ':'; *p
++ = ' ';
2058 p
= ngx_cpymem(p
, src
[i
].value
.data
, src
[i
].value
.len
);
2062 copy
= ngx_array_push_n(conf
->headers_set_len
,
2063 sizeof(ngx_http_script_copy_code_t
));
2065 return NGX_CONF_ERROR
;
2068 copy
->code
= (ngx_http_script_code_pt
)
2069 ngx_http_script_copy_len_code
;
2070 copy
->len
= src
[i
].key
.len
+ sizeof(": ") - 1;
2073 size
= (sizeof(ngx_http_script_copy_code_t
)
2074 + src
[i
].key
.len
+ sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
2075 & ~(sizeof(uintptr_t) - 1);
2077 copy
= ngx_array_push_n(conf
->headers_set
, size
);
2079 return NGX_CONF_ERROR
;
2082 copy
->code
= ngx_http_script_copy_code
;
2083 copy
->len
= src
[i
].key
.len
+ sizeof(": ") - 1;
2085 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
2086 p
= ngx_cpymem(p
, src
[i
].key
.data
, src
[i
].key
.len
);
2087 *p
++ = ':'; *p
= ' ';
2090 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2093 sc
.source
= &src
[i
].value
;
2094 sc
.flushes
= &conf
->flushes
;
2095 sc
.lengths
= &conf
->headers_set_len
;
2096 sc
.values
= &conf
->headers_set
;
2098 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2099 return NGX_CONF_ERROR
;
2103 copy
= ngx_array_push_n(conf
->headers_set_len
,
2104 sizeof(ngx_http_script_copy_code_t
));
2106 return NGX_CONF_ERROR
;
2109 copy
->code
= (ngx_http_script_code_pt
)
2110 ngx_http_script_copy_len_code
;
2111 copy
->len
= sizeof(CRLF
) - 1;
2114 size
= (sizeof(ngx_http_script_copy_code_t
)
2115 + sizeof(CRLF
) - 1 + sizeof(uintptr_t) - 1)
2116 & ~(sizeof(uintptr_t) - 1);
2118 copy
= ngx_array_push_n(conf
->headers_set
, size
);
2120 return NGX_CONF_ERROR
;
2123 copy
->code
= ngx_http_script_copy_code
;
2124 copy
->len
= sizeof(CRLF
) - 1;
2126 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
2130 code
= ngx_array_push_n(conf
->headers_set_len
, sizeof(uintptr_t));
2132 return NGX_CONF_ERROR
;
2135 *code
= (uintptr_t) NULL
;
2137 code
= ngx_array_push_n(conf
->headers_set
, sizeof(uintptr_t));
2139 return NGX_CONF_ERROR
;
2142 *code
= (uintptr_t) NULL
;
2145 code
= ngx_array_push_n(conf
->headers_set_len
, sizeof(uintptr_t));
2147 return NGX_CONF_ERROR
;
2150 *code
= (uintptr_t) NULL
;
2153 hash
.hash
= &conf
->headers_set_hash
;
2154 hash
.key
= ngx_hash_key_lc
;
2155 hash
.max_size
= conf
->headers_hash_max_size
;
2156 hash
.bucket_size
= conf
->headers_hash_bucket_size
;
2157 hash
.name
= "proxy_headers_hash";
2158 hash
.pool
= cf
->pool
;
2159 hash
.temp_pool
= NULL
;
2161 if (ngx_hash_init(&hash
, conf
->headers_names
->elts
,
2162 conf
->headers_names
->nelts
)
2165 return NGX_CONF_ERROR
;
2173 ngx_http_proxy_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2175 ngx_http_proxy_loc_conf_t
*plcf
= conf
;
2179 ngx_str_t
*value
, *url
;
2182 ngx_http_core_loc_conf_t
*clcf
;
2183 ngx_http_script_compile_t sc
;
2185 if (plcf
->upstream
.schema
.len
) {
2186 return "is duplicate";
2189 clcf
= ngx_http_conf_get_module_loc_conf(cf
, ngx_http_core_module
);
2191 value
= cf
->args
->elts
;
2195 n
= ngx_http_script_variables_count(url
);
2199 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2203 sc
.lengths
= &plcf
->proxy_lengths
;
2204 sc
.values
= &plcf
->proxy_values
;
2206 sc
.complete_lengths
= 1;
2207 sc
.complete_values
= 1;
2209 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2210 return NGX_CONF_ERROR
;
2214 if (ngx_http_proxy_set_ssl(cf
, plcf
) != NGX_OK
) {
2215 return NGX_CONF_ERROR
;
2219 clcf
->handler
= ngx_http_proxy_handler
;
2224 if (ngx_strncasecmp(url
->data
, (u_char
*) "http://", 7) == 0) {
2228 } else if (ngx_strncasecmp(url
->data
, (u_char
*) "https://", 8) == 0) {
2231 if (ngx_http_proxy_set_ssl(cf
, plcf
) != NGX_OK
) {
2232 return NGX_CONF_ERROR
;
2238 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2239 "https protocol requires SSL support");
2240 return NGX_CONF_ERROR
;
2244 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0, "invalid URL prefix");
2245 return NGX_CONF_ERROR
;
2248 ngx_memzero(&u
, sizeof(ngx_url_t
));
2250 u
.url
.len
= url
->len
- add
;
2251 u
.url
.data
= url
->data
+ add
;
2252 u
.default_port
= port
;
2256 plcf
->upstream
.upstream
= ngx_http_upstream_add(cf
, &u
, 0);
2257 if (plcf
->upstream
.upstream
== NULL
) {
2258 return NGX_CONF_ERROR
;
2261 if (ngx_http_proxy_set_vars(cf
->pool
, &u
, &plcf
->vars
) != NGX_OK
) {
2262 return NGX_CONF_ERROR
;
2265 plcf
->upstream
.schema
.len
= add
;
2266 plcf
->upstream
.schema
.data
= url
->data
;
2267 plcf
->location
= clcf
->name
;
2269 clcf
->handler
= ngx_http_proxy_handler
;
2277 if (plcf
->vars
.uri
.len
) {
2278 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2279 "\"proxy_pass\" may not have URI part in "
2280 "location given by regular expression, "
2281 "or inside named location, "
2282 "or inside the \"if\" statement, "
2283 "or inside the \"limit_except\" block");
2284 return NGX_CONF_ERROR
;
2287 plcf
->location
.len
= 0;
2292 if (clcf
->name
.data
[clcf
->name
.len
- 1] == '/') {
2293 clcf
->auto_redirect
= 1;
2301 ngx_http_proxy_redirect(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2303 ngx_http_proxy_loc_conf_t
*plcf
= conf
;
2306 ngx_array_t
*vars_lengths
, *vars_values
;
2307 ngx_http_script_compile_t sc
;
2308 ngx_http_proxy_redirect_t
*pr
;
2310 if (plcf
->redirect
== 0) {
2314 value
= cf
->args
->elts
;
2316 if (ngx_strcmp(value
[1].data
, "off") == 0) {
2318 plcf
->redirects
= NULL
;
2322 if (plcf
->redirects
== NULL
) {
2323 plcf
->redirects
= ngx_array_create(cf
->pool
, 1,
2324 sizeof(ngx_http_proxy_redirect_t
));
2325 if (plcf
->redirects
== NULL
) {
2326 return NGX_CONF_ERROR
;
2330 pr
= ngx_array_push(plcf
->redirects
);
2332 return NGX_CONF_ERROR
;
2335 if (cf
->args
->nelts
== 2 && ngx_strcmp(value
[1].data
, "default") == 0) {
2336 if (plcf
->url
.data
== NULL
) {
2337 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2338 "\"proxy_rewrite_location default\" must go "
2339 "after the \"proxy_pass\" directive");
2340 return NGX_CONF_ERROR
;
2343 pr
->handler
= ngx_http_proxy_rewrite_redirect_text
;
2344 pr
->redirect
= plcf
->url
;
2346 if (plcf
->vars
.uri
.len
) {
2347 pr
->replacement
.text
= plcf
->location
;
2350 pr
->replacement
.text
.len
= 0;
2351 pr
->replacement
.text
.data
= NULL
;
2357 if (ngx_http_script_variables_count(&value
[2]) == 0) {
2358 pr
->handler
= ngx_http_proxy_rewrite_redirect_text
;
2359 pr
->redirect
= value
[1];
2360 pr
->replacement
.text
= value
[2];
2365 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2367 vars_lengths
= NULL
;
2371 sc
.source
= &value
[2];
2372 sc
.lengths
= &vars_lengths
;
2373 sc
.values
= &vars_values
;
2374 sc
.complete_lengths
= 1;
2375 sc
.complete_values
= 1;
2377 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2378 return NGX_CONF_ERROR
;
2381 pr
->handler
= ngx_http_proxy_rewrite_redirect_vars
;
2382 pr
->redirect
= value
[1];
2383 pr
->replacement
.vars
.lengths
= vars_lengths
->elts
;
2384 pr
->replacement
.vars
.values
= vars_values
->elts
;
2391 ngx_http_proxy_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2393 ngx_http_proxy_loc_conf_t
*plcf
= conf
;
2396 ngx_http_script_compile_t sc
;
2398 if (plcf
->upstream
.store
!= NGX_CONF_UNSET
|| plcf
->upstream
.store_lengths
)
2400 return "is duplicate";
2403 value
= cf
->args
->elts
;
2405 if (ngx_strcmp(value
[1].data
, "on") == 0) {
2406 plcf
->upstream
.store
= 1;
2410 if (ngx_strcmp(value
[1].data
, "off") == 0) {
2411 plcf
->upstream
.store
= 0;
2415 /* include the terminating '\0' into script */
2418 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2421 sc
.source
= &value
[1];
2422 sc
.lengths
= &plcf
->upstream
.store_lengths
;
2423 sc
.values
= &plcf
->upstream
.store_values
;
2424 sc
.variables
= ngx_http_script_variables_count(&value
[1]);
2425 sc
.complete_lengths
= 1;
2426 sc
.complete_values
= 1;
2428 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2429 return NGX_CONF_ERROR
;
2437 ngx_http_proxy_lowat_check(ngx_conf_t
*cf
, void *post
, void *data
)
2442 if ((u_long
) *np
>= ngx_freebsd_net_inet_tcp_sendspace
) {
2443 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2444 "\"proxy_send_lowat\" must be less than %d "
2445 "(sysctl net.inet.tcp.sendspace)",
2446 ngx_freebsd_net_inet_tcp_sendspace
);
2448 return NGX_CONF_ERROR
;
2451 #elif !(NGX_HAVE_SO_SNDLOWAT)
2454 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
2455 "\"proxy_send_lowat\" is not supported, ignored");
2466 ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t
*cf
,
2467 ngx_command_t
*cmd
, void *conf
)
2469 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2470 "\"proxy_upstream_max_fails\" is not supported, "
2471 "use the \"max_fails\" parameter of the \"server\" directive ",
2472 "inside the \"upstream\" block");
2474 return NGX_CONF_ERROR
;
2479 ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t
*cf
,
2480 ngx_command_t
*cmd
, void *conf
)
2482 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2483 "\"proxy_upstream_fail_timeout\" is not supported, "
2484 "use the \"fail_timeout\" parameter of the \"server\" directive ",
2485 "inside the \"upstream\" block");
2487 return NGX_CONF_ERROR
;
2494 ngx_http_proxy_set_ssl(ngx_conf_t
*cf
, ngx_http_proxy_loc_conf_t
*plcf
)
2496 ngx_pool_cleanup_t
*cln
;
2498 plcf
->upstream
.ssl
= ngx_pcalloc(cf
->pool
, sizeof(ngx_ssl_t
));
2499 if (plcf
->upstream
.ssl
== NULL
) {
2503 plcf
->upstream
.ssl
->log
= cf
->log
;
2505 if (ngx_ssl_create(plcf
->upstream
.ssl
,
2506 NGX_SSL_SSLv2
|NGX_SSL_SSLv3
|NGX_SSL_TLSv1
, NULL
)
2512 cln
= ngx_pool_cleanup_add(cf
->pool
, 0);
2517 cln
->handler
= ngx_ssl_cleanup_ctx
;
2518 cln
->data
= plcf
->upstream
.ssl
;
2527 ngx_http_proxy_set_vars(ngx_pool_t
*pool
, ngx_url_t
*u
,
2528 ngx_http_proxy_vars_t
*v
)
2530 if (!u
->unix_socket
) {
2531 if (u
->no_port
|| u
->port
== u
->default_port
) {
2532 v
->host_header
= u
->host
;
2534 if (u
->default_port
== 80) {
2535 v
->port
.len
= sizeof("80") - 1;
2536 v
->port
.data
= (u_char
*) "80";
2539 v
->port
.len
= sizeof("443") - 1;
2540 v
->port
.data
= (u_char
*) "443";
2544 v
->host_header
.len
= u
->host
.len
+ 1 + u
->port_text
.len
;
2545 v
->host_header
.data
= u
->host
.data
;
2546 v
->port
= u
->port_text
;
2550 v
->host_header
.len
= sizeof("localhost") - 1;
2551 v
->host_header
.data
= (u_char
*) "localhost";
2553 v
->port
.data
= (u_char
*) "";