3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
14 static ngx_int_t
ngx_http_upstream_cache(ngx_http_request_t
*r
,
15 ngx_http_upstream_t
*u
);
16 static ngx_int_t
ngx_http_upstream_cache_send(ngx_http_request_t
*r
,
17 ngx_http_upstream_t
*u
);
18 static ngx_int_t
ngx_http_upstream_cache_status(ngx_http_request_t
*r
,
19 ngx_http_variable_value_t
*v
, uintptr_t data
);
22 static void ngx_http_upstream_init_request(ngx_http_request_t
*r
);
23 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t
*ctx
);
24 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
);
25 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
);
26 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
28 static void ngx_http_upstream_connect(ngx_http_request_t
*r
,
29 ngx_http_upstream_t
*u
);
30 static ngx_int_t
ngx_http_upstream_reinit(ngx_http_request_t
*r
,
31 ngx_http_upstream_t
*u
);
32 static void ngx_http_upstream_send_request(ngx_http_request_t
*r
,
33 ngx_http_upstream_t
*u
);
34 static void ngx_http_upstream_send_request_handler(ngx_http_request_t
*r
,
35 ngx_http_upstream_t
*u
);
36 static void ngx_http_upstream_process_header(ngx_http_request_t
*r
,
37 ngx_http_upstream_t
*u
);
38 static ngx_int_t
ngx_http_upstream_test_next(ngx_http_request_t
*r
,
39 ngx_http_upstream_t
*u
);
40 static ngx_int_t
ngx_http_upstream_intercept_errors(ngx_http_request_t
*r
,
41 ngx_http_upstream_t
*u
);
42 static ngx_int_t
ngx_http_upstream_test_connect(ngx_connection_t
*c
);
43 static ngx_int_t
ngx_http_upstream_process_headers(ngx_http_request_t
*r
,
44 ngx_http_upstream_t
*u
);
45 static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t
*r
,
46 ngx_http_upstream_t
*u
);
47 static void ngx_http_upstream_send_response(ngx_http_request_t
*r
,
48 ngx_http_upstream_t
*u
);
49 static void ngx_http_upstream_upgrade(ngx_http_request_t
*r
,
50 ngx_http_upstream_t
*u
);
51 static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t
*r
);
52 static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t
*r
);
53 static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t
*r
,
54 ngx_http_upstream_t
*u
);
55 static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t
*r
,
56 ngx_http_upstream_t
*u
);
57 static void ngx_http_upstream_process_upgraded(ngx_http_request_t
*r
,
58 ngx_uint_t from_upstream
, ngx_uint_t do_write
);
60 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
);
62 ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t
*r
,
63 ngx_http_upstream_t
*u
);
65 ngx_http_upstream_process_non_buffered_request(ngx_http_request_t
*r
,
67 static ngx_int_t
ngx_http_upstream_non_buffered_filter_init(void *data
);
68 static ngx_int_t
ngx_http_upstream_non_buffered_filter(void *data
,
70 static void ngx_http_upstream_process_downstream(ngx_http_request_t
*r
);
71 static void ngx_http_upstream_process_upstream(ngx_http_request_t
*r
,
72 ngx_http_upstream_t
*u
);
73 static void ngx_http_upstream_process_request(ngx_http_request_t
*r
);
74 static void ngx_http_upstream_store(ngx_http_request_t
*r
,
75 ngx_http_upstream_t
*u
);
76 static void ngx_http_upstream_dummy_handler(ngx_http_request_t
*r
,
77 ngx_http_upstream_t
*u
);
78 static void ngx_http_upstream_next(ngx_http_request_t
*r
,
79 ngx_http_upstream_t
*u
, ngx_uint_t ft_type
);
80 static void ngx_http_upstream_cleanup(void *data
);
81 static void ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
82 ngx_http_upstream_t
*u
, ngx_int_t rc
);
84 static ngx_int_t
ngx_http_upstream_process_header_line(ngx_http_request_t
*r
,
85 ngx_table_elt_t
*h
, ngx_uint_t offset
);
86 static ngx_int_t
ngx_http_upstream_process_content_length(ngx_http_request_t
*r
,
87 ngx_table_elt_t
*h
, ngx_uint_t offset
);
88 static ngx_int_t
ngx_http_upstream_process_set_cookie(ngx_http_request_t
*r
,
89 ngx_table_elt_t
*h
, ngx_uint_t offset
);
91 ngx_http_upstream_process_cache_control(ngx_http_request_t
*r
,
92 ngx_table_elt_t
*h
, ngx_uint_t offset
);
93 static ngx_int_t
ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
,
94 ngx_table_elt_t
*h
, ngx_uint_t offset
);
95 static ngx_int_t
ngx_http_upstream_process_expires(ngx_http_request_t
*r
,
96 ngx_table_elt_t
*h
, ngx_uint_t offset
);
97 static ngx_int_t
ngx_http_upstream_process_accel_expires(ngx_http_request_t
*r
,
98 ngx_table_elt_t
*h
, ngx_uint_t offset
);
99 static ngx_int_t
ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
,
100 ngx_table_elt_t
*h
, ngx_uint_t offset
);
101 static ngx_int_t
ngx_http_upstream_process_buffering(ngx_http_request_t
*r
,
102 ngx_table_elt_t
*h
, ngx_uint_t offset
);
103 static ngx_int_t
ngx_http_upstream_process_charset(ngx_http_request_t
*r
,
104 ngx_table_elt_t
*h
, ngx_uint_t offset
);
105 static ngx_int_t
ngx_http_upstream_process_connection(ngx_http_request_t
*r
,
106 ngx_table_elt_t
*h
, ngx_uint_t offset
);
108 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t
*r
,
109 ngx_table_elt_t
*h
, ngx_uint_t offset
);
110 static ngx_int_t
ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
,
111 ngx_table_elt_t
*h
, ngx_uint_t offset
);
113 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
114 ngx_table_elt_t
*h
, ngx_uint_t offset
);
115 static ngx_int_t
ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
,
116 ngx_table_elt_t
*h
, ngx_uint_t offset
);
117 static ngx_int_t
ngx_http_upstream_copy_last_modified(ngx_http_request_t
*r
,
118 ngx_table_elt_t
*h
, ngx_uint_t offset
);
119 static ngx_int_t
ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
,
120 ngx_table_elt_t
*h
, ngx_uint_t offset
);
121 static ngx_int_t
ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
,
122 ngx_table_elt_t
*h
, ngx_uint_t offset
);
123 static ngx_int_t
ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t
*r
,
124 ngx_table_elt_t
*h
, ngx_uint_t offset
);
125 static ngx_int_t
ngx_http_upstream_copy_allow_ranges(ngx_http_request_t
*r
,
126 ngx_table_elt_t
*h
, ngx_uint_t offset
);
129 static ngx_int_t
ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
130 ngx_table_elt_t
*h
, ngx_uint_t offset
);
133 static ngx_int_t
ngx_http_upstream_add_variables(ngx_conf_t
*cf
);
134 static ngx_int_t
ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
135 ngx_http_variable_value_t
*v
, uintptr_t data
);
136 static ngx_int_t
ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
137 ngx_http_variable_value_t
*v
, uintptr_t data
);
138 static ngx_int_t
ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
139 ngx_http_variable_value_t
*v
, uintptr_t data
);
140 static ngx_int_t
ngx_http_upstream_response_length_variable(
141 ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
, uintptr_t data
);
143 static char *ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
);
144 static char *ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
147 static ngx_addr_t
*ngx_http_upstream_get_local(ngx_http_request_t
*r
,
148 ngx_http_upstream_local_t
*local
);
150 static void *ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
);
151 static char *ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
);
154 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*,
155 ngx_http_upstream_t
*u
, ngx_connection_t
*c
);
156 static void ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
);
160 ngx_http_upstream_header_t ngx_http_upstream_headers_in
[] = {
162 { ngx_string("Status"),
163 ngx_http_upstream_process_header_line
,
164 offsetof(ngx_http_upstream_headers_in_t
, status
),
165 ngx_http_upstream_copy_header_line
, 0, 0 },
167 { ngx_string("Content-Type"),
168 ngx_http_upstream_process_header_line
,
169 offsetof(ngx_http_upstream_headers_in_t
, content_type
),
170 ngx_http_upstream_copy_content_type
, 0, 1 },
172 { ngx_string("Content-Length"),
173 ngx_http_upstream_process_content_length
,
174 offsetof(ngx_http_upstream_headers_in_t
, content_length
),
175 ngx_http_upstream_ignore_header_line
, 0, 0 },
177 { ngx_string("Date"),
178 ngx_http_upstream_process_header_line
,
179 offsetof(ngx_http_upstream_headers_in_t
, date
),
180 ngx_http_upstream_copy_header_line
,
181 offsetof(ngx_http_headers_out_t
, date
), 0 },
183 { ngx_string("Last-Modified"),
184 ngx_http_upstream_process_header_line
,
185 offsetof(ngx_http_upstream_headers_in_t
, last_modified
),
186 ngx_http_upstream_copy_last_modified
, 0, 0 },
188 { ngx_string("ETag"),
189 ngx_http_upstream_process_header_line
,
190 offsetof(ngx_http_upstream_headers_in_t
, etag
),
191 ngx_http_upstream_copy_header_line
,
192 offsetof(ngx_http_headers_out_t
, etag
), 0 },
194 { ngx_string("Server"),
195 ngx_http_upstream_process_header_line
,
196 offsetof(ngx_http_upstream_headers_in_t
, server
),
197 ngx_http_upstream_copy_header_line
,
198 offsetof(ngx_http_headers_out_t
, server
), 0 },
200 { ngx_string("WWW-Authenticate"),
201 ngx_http_upstream_process_header_line
,
202 offsetof(ngx_http_upstream_headers_in_t
, www_authenticate
),
203 ngx_http_upstream_copy_header_line
, 0, 0 },
205 { ngx_string("Location"),
206 ngx_http_upstream_process_header_line
,
207 offsetof(ngx_http_upstream_headers_in_t
, location
),
208 ngx_http_upstream_rewrite_location
, 0, 0 },
210 { ngx_string("Refresh"),
211 ngx_http_upstream_ignore_header_line
, 0,
212 ngx_http_upstream_rewrite_refresh
, 0, 0 },
214 { ngx_string("Set-Cookie"),
215 ngx_http_upstream_process_set_cookie
, 0,
216 ngx_http_upstream_rewrite_set_cookie
, 0, 1 },
218 { ngx_string("Content-Disposition"),
219 ngx_http_upstream_ignore_header_line
, 0,
220 ngx_http_upstream_copy_header_line
, 0, 1 },
222 { ngx_string("Cache-Control"),
223 ngx_http_upstream_process_cache_control
, 0,
224 ngx_http_upstream_copy_multi_header_lines
,
225 offsetof(ngx_http_headers_out_t
, cache_control
), 1 },
227 { ngx_string("Expires"),
228 ngx_http_upstream_process_expires
, 0,
229 ngx_http_upstream_copy_header_line
,
230 offsetof(ngx_http_headers_out_t
, expires
), 1 },
232 { ngx_string("Accept-Ranges"),
233 ngx_http_upstream_process_header_line
,
234 offsetof(ngx_http_upstream_headers_in_t
, accept_ranges
),
235 ngx_http_upstream_copy_allow_ranges
,
236 offsetof(ngx_http_headers_out_t
, accept_ranges
), 1 },
238 { ngx_string("Connection"),
239 ngx_http_upstream_process_connection
, 0,
240 ngx_http_upstream_ignore_header_line
, 0, 0 },
242 { ngx_string("Keep-Alive"),
243 ngx_http_upstream_ignore_header_line
, 0,
244 ngx_http_upstream_ignore_header_line
, 0, 0 },
246 { ngx_string("X-Powered-By"),
247 ngx_http_upstream_ignore_header_line
, 0,
248 ngx_http_upstream_copy_header_line
, 0, 0 },
250 { ngx_string("X-Accel-Expires"),
251 ngx_http_upstream_process_accel_expires
, 0,
252 ngx_http_upstream_copy_header_line
, 0, 0 },
254 { ngx_string("X-Accel-Redirect"),
255 ngx_http_upstream_process_header_line
,
256 offsetof(ngx_http_upstream_headers_in_t
, x_accel_redirect
),
257 ngx_http_upstream_copy_header_line
, 0, 0 },
259 { ngx_string("X-Accel-Limit-Rate"),
260 ngx_http_upstream_process_limit_rate
, 0,
261 ngx_http_upstream_copy_header_line
, 0, 0 },
263 { ngx_string("X-Accel-Buffering"),
264 ngx_http_upstream_process_buffering
, 0,
265 ngx_http_upstream_copy_header_line
, 0, 0 },
267 { ngx_string("X-Accel-Charset"),
268 ngx_http_upstream_process_charset
, 0,
269 ngx_http_upstream_copy_header_line
, 0, 0 },
271 { ngx_string("Transfer-Encoding"),
272 ngx_http_upstream_process_transfer_encoding
, 0,
273 ngx_http_upstream_ignore_header_line
, 0, 0 },
276 { ngx_string("Content-Encoding"),
277 ngx_http_upstream_process_header_line
,
278 offsetof(ngx_http_upstream_headers_in_t
, content_encoding
),
279 ngx_http_upstream_copy_content_encoding
, 0, 0 },
282 { ngx_null_string
, NULL
, 0, NULL
, 0, 0 }
286 static ngx_command_t ngx_http_upstream_commands
[] = {
288 { ngx_string("upstream"),
289 NGX_HTTP_MAIN_CONF
|NGX_CONF_BLOCK
|NGX_CONF_TAKE1
,
295 { ngx_string("server"),
296 NGX_HTTP_UPS_CONF
|NGX_CONF_1MORE
,
297 ngx_http_upstream_server
,
298 NGX_HTTP_SRV_CONF_OFFSET
,
306 static ngx_http_module_t ngx_http_upstream_module_ctx
= {
307 ngx_http_upstream_add_variables
, /* preconfiguration */
308 NULL
, /* postconfiguration */
310 ngx_http_upstream_create_main_conf
, /* create main configuration */
311 ngx_http_upstream_init_main_conf
, /* init main configuration */
313 NULL
, /* create server configuration */
314 NULL
, /* merge server configuration */
316 NULL
, /* create location configuration */
317 NULL
/* merge location configuration */
321 ngx_module_t ngx_http_upstream_module
= {
323 &ngx_http_upstream_module_ctx
, /* module context */
324 ngx_http_upstream_commands
, /* module directives */
325 NGX_HTTP_MODULE
, /* module type */
326 NULL
, /* init master */
327 NULL
, /* init module */
328 NULL
, /* init process */
329 NULL
, /* init thread */
330 NULL
, /* exit thread */
331 NULL
, /* exit process */
332 NULL
, /* exit master */
333 NGX_MODULE_V1_PADDING
337 static ngx_http_variable_t ngx_http_upstream_vars
[] = {
339 { ngx_string("upstream_addr"), NULL
,
340 ngx_http_upstream_addr_variable
, 0,
341 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
343 { ngx_string("upstream_status"), NULL
,
344 ngx_http_upstream_status_variable
, 0,
345 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
347 { ngx_string("upstream_response_time"), NULL
,
348 ngx_http_upstream_response_time_variable
, 0,
349 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
351 { ngx_string("upstream_response_length"), NULL
,
352 ngx_http_upstream_response_length_variable
, 0,
353 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
357 { ngx_string("upstream_cache_status"), NULL
,
358 ngx_http_upstream_cache_status
, 0,
359 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
363 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
367 static ngx_http_upstream_next_t ngx_http_upstream_next_errors
[] = {
368 { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500
},
369 { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502
},
370 { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503
},
371 { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504
},
372 { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404
},
377 ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask
[] = {
378 { ngx_string("GET"), NGX_HTTP_GET
},
379 { ngx_string("HEAD"), NGX_HTTP_HEAD
},
380 { ngx_string("POST"), NGX_HTTP_POST
},
381 { ngx_null_string
, 0 }
385 ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks
[] = {
386 { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT
},
387 { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES
},
388 { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE
},
389 { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING
},
390 { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET
},
391 { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES
},
392 { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL
},
393 { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE
},
394 { ngx_null_string
, 0 }
399 ngx_http_upstream_create(ngx_http_request_t
*r
)
401 ngx_http_upstream_t
*u
;
405 if (u
&& u
->cleanup
) {
407 ngx_http_upstream_cleanup(r
);
410 u
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_upstream_t
));
417 u
->peer
.log
= r
->connection
->log
;
418 u
->peer
.log_error
= NGX_ERROR_ERR
;
420 u
->peer
.lock
= &r
->connection
->lock
;
427 u
->headers_in
.content_length_n
= -1;
434 ngx_http_upstream_init(ngx_http_request_t
*r
)
440 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
441 "http init upstream, client timer: %d", c
->read
->timer_set
);
444 if (r
->spdy_stream
) {
445 ngx_http_upstream_init_request(r
);
450 if (c
->read
->timer_set
) {
451 ngx_del_timer(c
->read
);
454 if (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) {
456 if (!c
->write
->active
) {
457 if (ngx_add_event(c
->write
, NGX_WRITE_EVENT
, NGX_CLEAR_EVENT
)
460 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
466 ngx_http_upstream_init_request(r
);
471 ngx_http_upstream_init_request(ngx_http_request_t
*r
)
475 ngx_resolver_ctx_t
*ctx
, temp
;
476 ngx_http_cleanup_t
*cln
;
477 ngx_http_upstream_t
*u
;
478 ngx_http_core_loc_conf_t
*clcf
;
479 ngx_http_upstream_srv_conf_t
*uscf
, **uscfp
;
480 ngx_http_upstream_main_conf_t
*umcf
;
490 if (u
->conf
->cache
) {
493 rc
= ngx_http_upstream_cache(r
, u
);
495 if (rc
== NGX_BUSY
) {
496 r
->write_event_handler
= ngx_http_upstream_init_request
;
500 r
->write_event_handler
= ngx_http_request_empty_handler
;
502 if (rc
== NGX_DONE
) {
506 if (rc
!= NGX_DECLINED
) {
507 ngx_http_finalize_request(r
, rc
);
514 u
->store
= (u
->conf
->store
|| u
->conf
->store_lengths
);
516 if (!u
->store
&& !r
->post_action
&& !u
->conf
->ignore_client_abort
) {
517 r
->read_event_handler
= ngx_http_upstream_rd_check_broken_connection
;
518 r
->write_event_handler
= ngx_http_upstream_wr_check_broken_connection
;
521 if (r
->request_body
) {
522 u
->request_bufs
= r
->request_body
->bufs
;
525 if (u
->create_request(r
) != NGX_OK
) {
526 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
530 u
->peer
.local
= ngx_http_upstream_get_local(r
, u
->conf
->local
);
532 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
534 u
->output
.alignment
= clcf
->directio_alignment
;
535 u
->output
.pool
= r
->pool
;
536 u
->output
.bufs
.num
= 1;
537 u
->output
.bufs
.size
= clcf
->client_body_buffer_size
;
538 u
->output
.output_filter
= ngx_chain_writer
;
539 u
->output
.filter_ctx
= &u
->writer
;
541 u
->writer
.pool
= r
->pool
;
543 if (r
->upstream_states
== NULL
) {
545 r
->upstream_states
= ngx_array_create(r
->pool
, 1,
546 sizeof(ngx_http_upstream_state_t
));
547 if (r
->upstream_states
== NULL
) {
548 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
554 u
->state
= ngx_array_push(r
->upstream_states
);
555 if (u
->state
== NULL
) {
556 ngx_http_upstream_finalize_request(r
, u
,
557 NGX_HTTP_INTERNAL_SERVER_ERROR
);
561 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
564 cln
= ngx_http_cleanup_add(r
, 0);
566 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
570 cln
->handler
= ngx_http_upstream_cleanup
;
572 u
->cleanup
= &cln
->handler
;
574 if (u
->resolved
== NULL
) {
576 uscf
= u
->conf
->upstream
;
580 if (u
->resolved
->sockaddr
) {
582 if (ngx_http_upstream_create_round_robin_peer(r
, u
->resolved
)
585 ngx_http_upstream_finalize_request(r
, u
,
586 NGX_HTTP_INTERNAL_SERVER_ERROR
);
590 ngx_http_upstream_connect(r
, u
);
595 host
= &u
->resolved
->host
;
597 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
599 uscfp
= umcf
->upstreams
.elts
;
601 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
605 if (uscf
->host
.len
== host
->len
606 && ((uscf
->port
== 0 && u
->resolved
->no_port
)
607 || uscf
->port
== u
->resolved
->port
)
608 && ngx_memcmp(uscf
->host
.data
, host
->data
, host
->len
) == 0)
614 if (u
->resolved
->port
== 0) {
615 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
616 "no port in upstream \"%V\"", host
);
617 ngx_http_upstream_finalize_request(r
, u
,
618 NGX_HTTP_INTERNAL_SERVER_ERROR
);
624 ctx
= ngx_resolve_start(clcf
->resolver
, &temp
);
626 ngx_http_upstream_finalize_request(r
, u
,
627 NGX_HTTP_INTERNAL_SERVER_ERROR
);
631 if (ctx
== NGX_NO_RESOLVER
) {
632 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
633 "no resolver defined to resolve %V", host
);
635 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_BAD_GATEWAY
);
640 ctx
->type
= NGX_RESOLVE_A
;
641 ctx
->handler
= ngx_http_upstream_resolve_handler
;
643 ctx
->timeout
= clcf
->resolver_timeout
;
645 u
->resolved
->ctx
= ctx
;
647 if (ngx_resolve_name(ctx
) != NGX_OK
) {
648 u
->resolved
->ctx
= NULL
;
649 ngx_http_upstream_finalize_request(r
, u
,
650 NGX_HTTP_INTERNAL_SERVER_ERROR
);
660 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
661 "no upstream configuration");
662 ngx_http_upstream_finalize_request(r
, u
,
663 NGX_HTTP_INTERNAL_SERVER_ERROR
);
667 if (uscf
->peer
.init(r
, uscf
) != NGX_OK
) {
668 ngx_http_upstream_finalize_request(r
, u
,
669 NGX_HTTP_INTERNAL_SERVER_ERROR
);
673 ngx_http_upstream_connect(r
, u
);
680 ngx_http_upstream_cache(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
689 if (!(r
->method
& u
->conf
->cache_methods
)) {
693 if (r
->method
& NGX_HTTP_HEAD
) {
694 u
->method
= ngx_http_core_get_method
;
697 if (ngx_http_file_cache_new(r
) != NGX_OK
) {
701 if (u
->create_key(r
) != NGX_OK
) {
707 ngx_http_file_cache_create_key(r
);
709 if (r
->cache
->header_start
+ 256 >= u
->conf
->buffer_size
) {
710 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
711 "%V_buffer_size %uz is not enough for cache key, "
712 "it should increased at least to %uz",
713 &u
->conf
->module
, u
->conf
->buffer_size
,
714 ngx_align(r
->cache
->header_start
+ 256, 1024));
722 switch (ngx_http_test_predicates(r
, u
->conf
->cache_bypass
)) {
728 u
->cache_status
= NGX_HTTP_CACHE_BYPASS
;
731 default: /* NGX_OK */
737 c
->min_uses
= u
->conf
->cache_min_uses
;
738 c
->body_start
= u
->conf
->buffer_size
;
739 c
->file_cache
= u
->conf
->cache
->data
;
741 c
->lock
= u
->conf
->cache_lock
;
742 c
->lock_timeout
= u
->conf
->cache_lock_timeout
;
744 u
->cache_status
= NGX_HTTP_CACHE_MISS
;
747 rc
= ngx_http_file_cache_open(r
);
749 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
750 "http upstream cache: %i", rc
);
754 case NGX_HTTP_CACHE_UPDATING
:
756 if (u
->conf
->cache_use_stale
& NGX_HTTP_UPSTREAM_FT_UPDATING
) {
757 u
->cache_status
= rc
;
761 rc
= NGX_HTTP_CACHE_STALE
;
767 u
->cache_status
= NGX_HTTP_CACHE_HIT
;
774 rc
= ngx_http_upstream_cache_send(r
, u
);
776 if (rc
!= NGX_HTTP_UPSTREAM_INVALID_HEADER
) {
782 case NGX_HTTP_CACHE_STALE
:
785 u
->buffer
.start
= NULL
;
786 u
->cache_status
= NGX_HTTP_CACHE_EXPIRED
;
792 if ((size_t) (u
->buffer
.end
- u
->buffer
.start
) < u
->conf
->buffer_size
) {
793 u
->buffer
.start
= NULL
;
796 u
->buffer
.pos
= u
->buffer
.start
+ c
->header_start
;
797 u
->buffer
.last
= u
->buffer
.pos
;
802 case NGX_HTTP_CACHE_SCARCE
:
818 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
820 u
->cache_status
= NGX_HTTP_CACHE_HIT
;
832 ngx_http_upstream_cache_send(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
840 if (c
->header_start
== c
->body_start
) {
841 r
->http_version
= NGX_HTTP_VERSION_9
;
842 return ngx_http_cache_send(r
);
845 /* TODO: cache stack */
848 u
->buffer
.pos
+= c
->header_start
;
850 ngx_memzero(&u
->headers_in
, sizeof(ngx_http_upstream_headers_in_t
));
851 u
->headers_in
.content_length_n
= -1;
853 if (ngx_list_init(&u
->headers_in
.headers
, r
->pool
, 8,
854 sizeof(ngx_table_elt_t
))
860 rc
= u
->process_header(r
);
864 if (ngx_http_upstream_process_headers(r
, u
) != NGX_OK
) {
868 return ngx_http_cache_send(r
);
871 if (rc
== NGX_ERROR
) {
875 /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
877 /* TODO: delete file */
886 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t
*ctx
)
889 ngx_http_request_t
*r
;
890 ngx_http_upstream_t
*u
;
891 ngx_http_upstream_resolved_t
*ur
;
900 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
901 "%V could not be resolved (%i: %s)",
902 &ctx
->name
, ctx
->state
,
903 ngx_resolver_strerror(ctx
->state
));
905 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_BAD_GATEWAY
);
909 ur
->naddrs
= ctx
->naddrs
;
910 ur
->addrs
= ctx
->addrs
;
917 for (i
= 0; i
< ctx
->naddrs
; i
++) {
918 addr
= ntohl(ur
->addrs
[i
]);
920 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
921 "name was resolved to %ud.%ud.%ud.%ud",
922 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
923 (addr
>> 8) & 0xff, addr
& 0xff);
928 if (ngx_http_upstream_create_round_robin_peer(r
, ur
) != NGX_OK
) {
929 ngx_http_upstream_finalize_request(r
, u
,
930 NGX_HTTP_INTERNAL_SERVER_ERROR
);
934 ngx_resolve_name_done(ctx
);
937 ngx_http_upstream_connect(r
, u
);
941 ngx_http_run_posted_requests(c
);
946 ngx_http_upstream_handler(ngx_event_t
*ev
)
949 ngx_http_request_t
*r
;
950 ngx_http_log_ctx_t
*ctx
;
951 ngx_http_upstream_t
*u
;
960 ctx
->current_request
= r
;
962 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
963 "http upstream request: \"%V?%V\"", &r
->uri
, &r
->args
);
966 u
->write_event_handler(r
, u
);
969 u
->read_event_handler(r
, u
);
972 ngx_http_run_posted_requests(c
);
977 ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
)
979 ngx_http_upstream_check_broken_connection(r
, r
->connection
->read
);
984 ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
)
986 ngx_http_upstream_check_broken_connection(r
, r
->connection
->write
);
991 ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
999 ngx_http_upstream_t
*u
;
1001 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, ev
->log
, 0,
1002 "http upstream check client, write event:%d, \"%V\"",
1003 ev
->write
, &r
->uri
);
1009 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && ev
->active
) {
1011 event
= ev
->write
? NGX_WRITE_EVENT
: NGX_READ_EVENT
;
1013 if (ngx_del_event(ev
, event
, 0) != NGX_OK
) {
1014 ngx_http_upstream_finalize_request(r
, u
,
1015 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1020 if (!u
->cacheable
) {
1021 ngx_http_upstream_finalize_request(r
, u
,
1022 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
1029 if (r
->spdy_stream
) {
1034 #if (NGX_HAVE_KQUEUE)
1036 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1038 if (!ev
->pending_eof
) {
1049 if (!u
->cacheable
&& u
->peer
.connection
) {
1050 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
1051 "kevent() reported that client prematurely closed "
1052 "connection, so upstream connection is closed too");
1053 ngx_http_upstream_finalize_request(r
, u
,
1054 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
1058 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
1059 "kevent() reported that client prematurely closed "
1062 if (u
->peer
.connection
== NULL
) {
1063 ngx_http_upstream_finalize_request(r
, u
,
1064 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
1072 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
1074 err
= ngx_socket_errno
;
1076 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, ev
->log
, err
,
1077 "http upstream recv(): %d", n
);
1079 if (ev
->write
&& (n
>= 0 || err
== NGX_EAGAIN
)) {
1083 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && ev
->active
) {
1085 event
= ev
->write
? NGX_WRITE_EVENT
: NGX_READ_EVENT
;
1087 if (ngx_del_event(ev
, event
, 0) != NGX_OK
) {
1088 ngx_http_upstream_finalize_request(r
, u
,
1089 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1099 if (err
== NGX_EAGAIN
) {
1105 } else { /* n == 0 */
1112 if (!u
->cacheable
&& u
->peer
.connection
) {
1113 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
1114 "client prematurely closed connection, "
1115 "so upstream connection is closed too");
1116 ngx_http_upstream_finalize_request(r
, u
,
1117 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
1121 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
1122 "client prematurely closed connection");
1124 if (u
->peer
.connection
== NULL
) {
1125 ngx_http_upstream_finalize_request(r
, u
,
1126 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
1132 ngx_http_upstream_connect(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1136 ngx_connection_t
*c
;
1138 r
->connection
->log
->action
= "connecting to upstream";
1140 if (u
->state
&& u
->state
->response_sec
) {
1141 tp
= ngx_timeofday();
1142 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
1143 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
1146 u
->state
= ngx_array_push(r
->upstream_states
);
1147 if (u
->state
== NULL
) {
1148 ngx_http_upstream_finalize_request(r
, u
,
1149 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1153 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
1155 tp
= ngx_timeofday();
1156 u
->state
->response_sec
= tp
->sec
;
1157 u
->state
->response_msec
= tp
->msec
;
1159 rc
= ngx_event_connect_peer(&u
->peer
);
1161 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1162 "http upstream connect: %i", rc
);
1164 if (rc
== NGX_ERROR
) {
1165 ngx_http_upstream_finalize_request(r
, u
,
1166 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1170 u
->state
->peer
= u
->peer
.name
;
1172 if (rc
== NGX_BUSY
) {
1173 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0, "no live upstreams");
1174 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_NOLIVE
);
1178 if (rc
== NGX_DECLINED
) {
1179 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1183 /* rc == NGX_OK || rc == NGX_AGAIN */
1185 c
= u
->peer
.connection
;
1189 c
->write
->handler
= ngx_http_upstream_handler
;
1190 c
->read
->handler
= ngx_http_upstream_handler
;
1192 u
->write_event_handler
= ngx_http_upstream_send_request_handler
;
1193 u
->read_event_handler
= ngx_http_upstream_process_header
;
1195 c
->sendfile
&= r
->connection
->sendfile
;
1196 u
->output
.sendfile
= c
->sendfile
;
1198 if (c
->pool
== NULL
) {
1200 /* we need separate pool here to be able to cache SSL connections */
1202 c
->pool
= ngx_create_pool(128, r
->connection
->log
);
1203 if (c
->pool
== NULL
) {
1204 ngx_http_upstream_finalize_request(r
, u
,
1205 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1210 c
->log
= r
->connection
->log
;
1211 c
->pool
->log
= c
->log
;
1212 c
->read
->log
= c
->log
;
1213 c
->write
->log
= c
->log
;
1215 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
1217 u
->writer
.out
= NULL
;
1218 u
->writer
.last
= &u
->writer
.out
;
1219 u
->writer
.connection
= c
;
1220 u
->writer
.limit
= 0;
1222 if (u
->request_sent
) {
1223 if (ngx_http_upstream_reinit(r
, u
) != NGX_OK
) {
1224 ngx_http_upstream_finalize_request(r
, u
,
1225 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1231 && r
->request_body
->buf
1232 && r
->request_body
->temp_file
1236 * the r->request_body->buf can be reused for one request only,
1237 * the subrequests should allocate their own temporary bufs
1240 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
1241 if (u
->output
.free
== NULL
) {
1242 ngx_http_upstream_finalize_request(r
, u
,
1243 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1247 u
->output
.free
->buf
= r
->request_body
->buf
;
1248 u
->output
.free
->next
= NULL
;
1249 u
->output
.allocated
= 1;
1251 r
->request_body
->buf
->pos
= r
->request_body
->buf
->start
;
1252 r
->request_body
->buf
->last
= r
->request_body
->buf
->start
;
1253 r
->request_body
->buf
->tag
= u
->output
.tag
;
1256 u
->request_sent
= 0;
1258 if (rc
== NGX_AGAIN
) {
1259 ngx_add_timer(c
->write
, u
->conf
->connect_timeout
);
1265 if (u
->ssl
&& c
->ssl
== NULL
) {
1266 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
1272 ngx_http_upstream_send_request(r
, u
);
1279 ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*r
,
1280 ngx_http_upstream_t
*u
, ngx_connection_t
*c
)
1284 if (ngx_ssl_create_connection(u
->conf
->ssl
, c
,
1285 NGX_SSL_BUFFER
|NGX_SSL_CLIENT
)
1288 ngx_http_upstream_finalize_request(r
, u
,
1289 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1294 u
->output
.sendfile
= 0;
1296 if (u
->conf
->ssl_session_reuse
) {
1297 if (u
->peer
.set_session(&u
->peer
, u
->peer
.data
) != NGX_OK
) {
1298 ngx_http_upstream_finalize_request(r
, u
,
1299 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1304 r
->connection
->log
->action
= "SSL handshaking to upstream";
1306 rc
= ngx_ssl_handshake(c
);
1308 if (rc
== NGX_AGAIN
) {
1309 c
->ssl
->handler
= ngx_http_upstream_ssl_handshake
;
1313 ngx_http_upstream_ssl_handshake(c
);
1318 ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
)
1320 ngx_http_request_t
*r
;
1321 ngx_http_upstream_t
*u
;
1326 if (c
->ssl
->handshaked
) {
1328 if (u
->conf
->ssl_session_reuse
) {
1329 u
->peer
.save_session(&u
->peer
, u
->peer
.data
);
1332 c
->write
->handler
= ngx_http_upstream_handler
;
1333 c
->read
->handler
= ngx_http_upstream_handler
;
1335 ngx_http_upstream_send_request(r
, u
);
1340 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1348 ngx_http_upstream_reinit(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1352 if (u
->reinit_request(r
) != NGX_OK
) {
1359 ngx_memzero(&u
->headers_in
, sizeof(ngx_http_upstream_headers_in_t
));
1360 u
->headers_in
.content_length_n
= -1;
1362 if (ngx_list_init(&u
->headers_in
.headers
, r
->pool
, 8,
1363 sizeof(ngx_table_elt_t
))
1369 /* reinit the request chain */
1371 for (cl
= u
->request_bufs
; cl
; cl
= cl
->next
) {
1372 cl
->buf
->pos
= cl
->buf
->start
;
1373 cl
->buf
->file_pos
= 0;
1376 /* reinit the subrequest's ngx_output_chain() context */
1378 if (r
->request_body
&& r
->request_body
->temp_file
1379 && r
!= r
->main
&& u
->output
.buf
)
1381 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
1382 if (u
->output
.free
== NULL
) {
1386 u
->output
.free
->buf
= u
->output
.buf
;
1387 u
->output
.free
->next
= NULL
;
1389 u
->output
.buf
->pos
= u
->output
.buf
->start
;
1390 u
->output
.buf
->last
= u
->output
.buf
->start
;
1393 u
->output
.buf
= NULL
;
1394 u
->output
.in
= NULL
;
1395 u
->output
.busy
= NULL
;
1397 /* reinit u->buffer */
1399 u
->buffer
.pos
= u
->buffer
.start
;
1401 #if (NGX_HTTP_CACHE)
1404 u
->buffer
.pos
+= r
->cache
->header_start
;
1409 u
->buffer
.last
= u
->buffer
.pos
;
1416 ngx_http_upstream_send_request(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1419 ngx_connection_t
*c
;
1421 c
= u
->peer
.connection
;
1423 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1424 "http upstream send request");
1426 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
1427 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1431 c
->log
->action
= "sending request to upstream";
1433 rc
= ngx_output_chain(&u
->output
, u
->request_sent
? NULL
: u
->request_bufs
);
1435 u
->request_sent
= 1;
1437 if (rc
== NGX_ERROR
) {
1438 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1442 if (c
->write
->timer_set
) {
1443 ngx_del_timer(c
->write
);
1446 if (rc
== NGX_AGAIN
) {
1447 ngx_add_timer(c
->write
, u
->conf
->send_timeout
);
1449 if (ngx_handle_write_event(c
->write
, u
->conf
->send_lowat
) != NGX_OK
) {
1450 ngx_http_upstream_finalize_request(r
, u
,
1451 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1460 if (c
->tcp_nopush
== NGX_TCP_NOPUSH_SET
) {
1461 if (ngx_tcp_push(c
->fd
) == NGX_ERROR
) {
1462 ngx_log_error(NGX_LOG_CRIT
, c
->log
, ngx_socket_errno
,
1463 ngx_tcp_push_n
" failed");
1464 ngx_http_upstream_finalize_request(r
, u
,
1465 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1469 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
1472 ngx_add_timer(c
->read
, u
->conf
->read_timeout
);
1475 if (c
->read
->ready
) {
1477 /* post aio operation */
1481 * although we can post aio operation just in the end
1482 * of ngx_http_upstream_connect() CHECK IT !!!
1483 * it's better to do here because we postpone header buffer allocation
1486 ngx_http_upstream_process_header(r
, u
);
1491 u
->write_event_handler
= ngx_http_upstream_dummy_handler
;
1493 if (ngx_handle_write_event(c
->write
, 0) != NGX_OK
) {
1494 ngx_http_upstream_finalize_request(r
, u
,
1495 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1502 ngx_http_upstream_send_request_handler(ngx_http_request_t
*r
,
1503 ngx_http_upstream_t
*u
)
1505 ngx_connection_t
*c
;
1507 c
= u
->peer
.connection
;
1509 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1510 "http upstream send request handler");
1512 if (c
->write
->timedout
) {
1513 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
1519 if (u
->ssl
&& c
->ssl
== NULL
) {
1520 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
1526 if (u
->header_sent
) {
1527 u
->write_event_handler
= ngx_http_upstream_dummy_handler
;
1529 (void) ngx_handle_write_event(c
->write
, 0);
1534 ngx_http_upstream_send_request(r
, u
);
1539 ngx_http_upstream_process_header(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1543 ngx_connection_t
*c
;
1545 c
= u
->peer
.connection
;
1547 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1548 "http upstream process header");
1550 c
->log
->action
= "reading response header from upstream";
1552 if (c
->read
->timedout
) {
1553 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
1557 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
1558 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1562 if (u
->buffer
.start
== NULL
) {
1563 u
->buffer
.start
= ngx_palloc(r
->pool
, u
->conf
->buffer_size
);
1564 if (u
->buffer
.start
== NULL
) {
1565 ngx_http_upstream_finalize_request(r
, u
,
1566 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1570 u
->buffer
.pos
= u
->buffer
.start
;
1571 u
->buffer
.last
= u
->buffer
.start
;
1572 u
->buffer
.end
= u
->buffer
.start
+ u
->conf
->buffer_size
;
1573 u
->buffer
.temporary
= 1;
1575 u
->buffer
.tag
= u
->output
.tag
;
1577 if (ngx_list_init(&u
->headers_in
.headers
, r
->pool
, 8,
1578 sizeof(ngx_table_elt_t
))
1581 ngx_http_upstream_finalize_request(r
, u
,
1582 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1586 #if (NGX_HTTP_CACHE)
1589 u
->buffer
.pos
+= r
->cache
->header_start
;
1590 u
->buffer
.last
= u
->buffer
.pos
;
1597 n
= c
->recv(c
, u
->buffer
.last
, u
->buffer
.end
- u
->buffer
.last
);
1599 if (n
== NGX_AGAIN
) {
1601 ngx_add_timer(rev
, u
->read_timeout
);
1604 if (ngx_handle_read_event(c
->read
, 0) != NGX_OK
) {
1605 ngx_http_upstream_finalize_request(r
, u
,
1606 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1614 ngx_log_error(NGX_LOG_ERR
, c
->log
, 0,
1615 "upstream prematurely closed connection");
1618 if (n
== NGX_ERROR
|| n
== 0) {
1619 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1623 u
->buffer
.last
+= n
;
1626 u
->valid_header_in
= 0;
1631 rc
= u
->process_header(r
);
1633 if (rc
== NGX_AGAIN
) {
1635 if (u
->buffer
.last
== u
->buffer
.end
) {
1636 ngx_log_error(NGX_LOG_ERR
, c
->log
, 0,
1637 "upstream sent too big header");
1639 ngx_http_upstream_next(r
, u
,
1640 NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1650 if (rc
== NGX_HTTP_UPSTREAM_INVALID_HEADER
) {
1651 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1655 if (rc
== NGX_ERROR
) {
1656 ngx_http_upstream_finalize_request(r
, u
,
1657 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1663 if (u
->headers_in
.status_n
> NGX_HTTP_SPECIAL_RESPONSE
) {
1665 if (r
->subrequest_in_memory
) {
1666 u
->buffer
.last
= u
->buffer
.pos
;
1669 if (ngx_http_upstream_test_next(r
, u
) == NGX_OK
) {
1673 if (ngx_http_upstream_intercept_errors(r
, u
) == NGX_OK
) {
1678 if (ngx_http_upstream_process_headers(r
, u
) != NGX_OK
) {
1682 if (!r
->subrequest_in_memory
) {
1683 ngx_http_upstream_send_response(r
, u
);
1687 /* subrequest content in memory */
1689 if (u
->input_filter
== NULL
) {
1690 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
1691 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
1692 u
->input_filter_ctx
= r
;
1695 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
1696 ngx_http_upstream_finalize_request(r
, u
,
1697 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1701 n
= u
->buffer
.last
- u
->buffer
.pos
;
1704 u
->buffer
.last
-= n
;
1706 u
->state
->response_length
+= n
;
1708 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
1709 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1713 if (u
->length
== 0) {
1714 ngx_http_upstream_finalize_request(r
, u
, 0);
1719 u
->read_event_handler
= ngx_http_upstream_process_body_in_memory
;
1721 ngx_http_upstream_process_body_in_memory(r
, u
);
1726 ngx_http_upstream_test_next(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1729 ngx_http_upstream_next_t
*un
;
1731 status
= u
->headers_in
.status_n
;
1733 for (un
= ngx_http_upstream_next_errors
; un
->status
; un
++) {
1735 if (status
!= un
->status
) {
1739 if (u
->peer
.tries
> 1 && (u
->conf
->next_upstream
& un
->mask
)) {
1740 ngx_http_upstream_next(r
, u
, un
->mask
);
1744 #if (NGX_HTTP_CACHE)
1746 if (u
->cache_status
== NGX_HTTP_CACHE_EXPIRED
1747 && (u
->conf
->cache_use_stale
& un
->mask
))
1751 rc
= u
->reinit_request(r
);
1754 u
->cache_status
= NGX_HTTP_CACHE_STALE
;
1755 rc
= ngx_http_upstream_cache_send(r
, u
);
1758 ngx_http_upstream_finalize_request(r
, u
, rc
);
1765 return NGX_DECLINED
;
1770 ngx_http_upstream_intercept_errors(ngx_http_request_t
*r
,
1771 ngx_http_upstream_t
*u
)
1776 ngx_http_err_page_t
*err_page
;
1777 ngx_http_core_loc_conf_t
*clcf
;
1779 status
= u
->headers_in
.status_n
;
1781 if (status
== NGX_HTTP_NOT_FOUND
&& u
->conf
->intercept_404
) {
1782 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_NOT_FOUND
);
1786 if (!u
->conf
->intercept_errors
) {
1787 return NGX_DECLINED
;
1790 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1792 if (clcf
->error_pages
== NULL
) {
1793 return NGX_DECLINED
;
1796 err_page
= clcf
->error_pages
->elts
;
1797 for (i
= 0; i
< clcf
->error_pages
->nelts
; i
++) {
1799 if (err_page
[i
].status
== status
) {
1801 if (status
== NGX_HTTP_UNAUTHORIZED
1802 && u
->headers_in
.www_authenticate
)
1804 h
= ngx_list_push(&r
->headers_out
.headers
);
1807 ngx_http_upstream_finalize_request(r
, u
,
1808 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1812 *h
= *u
->headers_in
.www_authenticate
;
1814 r
->headers_out
.www_authenticate
= h
;
1817 #if (NGX_HTTP_CACHE)
1822 valid
= ngx_http_file_cache_valid(u
->conf
->cache_valid
, status
);
1825 r
->cache
->valid_sec
= ngx_time() + valid
;
1826 r
->cache
->error
= status
;
1829 ngx_http_file_cache_free(r
->cache
, u
->pipe
->temp_file
);
1832 ngx_http_upstream_finalize_request(r
, u
, status
);
1838 return NGX_DECLINED
;
1843 ngx_http_upstream_test_connect(ngx_connection_t
*c
)
1848 #if (NGX_HAVE_KQUEUE)
1850 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1851 if (c
->write
->pending_eof
|| c
->read
->pending_eof
) {
1852 if (c
->write
->pending_eof
) {
1853 err
= c
->write
->kq_errno
;
1856 err
= c
->read
->kq_errno
;
1859 c
->log
->action
= "connecting to upstream";
1860 (void) ngx_connection_error(c
, err
,
1861 "kevent() reported that connect() failed");
1872 * BSDs and Linux return 0 and set a pending error in err
1873 * Solaris returns -1 and sets errno
1876 if (getsockopt(c
->fd
, SOL_SOCKET
, SO_ERROR
, (void *) &err
, &len
)
1883 c
->log
->action
= "connecting to upstream";
1884 (void) ngx_connection_error(c
, err
, "connect() failed");
1894 ngx_http_upstream_process_headers(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1896 ngx_str_t
*uri
, args
;
1897 ngx_uint_t i
, flags
;
1898 ngx_list_part_t
*part
;
1900 ngx_http_upstream_header_t
*hh
;
1901 ngx_http_upstream_main_conf_t
*umcf
;
1903 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
1905 if (u
->headers_in
.x_accel_redirect
1906 && !(u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT
))
1908 ngx_http_upstream_finalize_request(r
, u
, NGX_DECLINED
);
1910 part
= &u
->headers_in
.headers
.part
;
1913 for (i
= 0; /* void */; i
++) {
1915 if (i
>= part
->nelts
) {
1916 if (part
->next
== NULL
) {
1925 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1926 h
[i
].lowcase_key
, h
[i
].key
.len
);
1928 if (hh
&& hh
->redirect
) {
1929 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1930 ngx_http_finalize_request(r
,
1931 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1937 uri
= &u
->headers_in
.x_accel_redirect
->value
;
1938 ngx_str_null(&args
);
1939 flags
= NGX_HTTP_LOG_UNSAFE
;
1941 if (ngx_http_parse_unsafe_uri(r
, uri
, &args
, &flags
) != NGX_OK
) {
1942 ngx_http_finalize_request(r
, NGX_HTTP_NOT_FOUND
);
1946 if (r
->method
!= NGX_HTTP_HEAD
) {
1947 r
->method
= NGX_HTTP_GET
;
1950 ngx_http_internal_redirect(r
, uri
, &args
);
1951 ngx_http_finalize_request(r
, NGX_DONE
);
1955 part
= &u
->headers_in
.headers
.part
;
1958 for (i
= 0; /* void */; i
++) {
1960 if (i
>= part
->nelts
) {
1961 if (part
->next
== NULL
) {
1970 if (ngx_hash_find(&u
->conf
->hide_headers_hash
, h
[i
].hash
,
1971 h
[i
].lowcase_key
, h
[i
].key
.len
))
1976 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1977 h
[i
].lowcase_key
, h
[i
].key
.len
);
1980 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1981 ngx_http_upstream_finalize_request(r
, u
,
1982 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1989 if (ngx_http_upstream_copy_header_line(r
, &h
[i
], 0) != NGX_OK
) {
1990 ngx_http_upstream_finalize_request(r
, u
,
1991 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1996 if (r
->headers_out
.server
&& r
->headers_out
.server
->value
.data
== NULL
) {
1997 r
->headers_out
.server
->hash
= 0;
2000 if (r
->headers_out
.date
&& r
->headers_out
.date
->value
.data
== NULL
) {
2001 r
->headers_out
.date
->hash
= 0;
2004 r
->headers_out
.status
= u
->headers_in
.status_n
;
2005 r
->headers_out
.status_line
= u
->headers_in
.status_line
;
2007 r
->headers_out
.content_length_n
= u
->headers_in
.content_length_n
;
2009 u
->length
= u
->headers_in
.content_length_n
;
2016 ngx_http_upstream_process_body_in_memory(ngx_http_request_t
*r
,
2017 ngx_http_upstream_t
*u
)
2023 ngx_connection_t
*c
;
2025 c
= u
->peer
.connection
;
2028 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2029 "http upstream process body on memory");
2031 if (rev
->timedout
) {
2032 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
2033 ngx_http_upstream_finalize_request(r
, u
, NGX_ETIMEDOUT
);
2041 size
= b
->end
- b
->last
;
2044 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
2045 "upstream buffer is too small to read response");
2046 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
2050 n
= c
->recv(c
, b
->last
, size
);
2052 if (n
== NGX_AGAIN
) {
2056 if (n
== 0 || n
== NGX_ERROR
) {
2057 ngx_http_upstream_finalize_request(r
, u
, n
);
2061 u
->state
->response_length
+= n
;
2063 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
2064 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
2073 if (u
->length
== 0) {
2074 ngx_http_upstream_finalize_request(r
, u
, 0);
2078 if (ngx_handle_read_event(rev
, 0) != NGX_OK
) {
2079 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
2084 ngx_add_timer(rev
, u
->conf
->read_timeout
);
2086 } else if (rev
->timer_set
) {
2093 ngx_http_upstream_send_response(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
2098 ngx_event_pipe_t
*p
;
2099 ngx_connection_t
*c
;
2100 ngx_http_core_loc_conf_t
*clcf
;
2102 rc
= ngx_http_send_header(r
);
2104 if (rc
== NGX_ERROR
|| rc
> NGX_OK
|| r
->post_action
) {
2105 ngx_http_upstream_finalize_request(r
, u
, rc
);
2110 ngx_http_upstream_upgrade(r
, u
);
2116 if (r
->header_only
) {
2118 if (u
->cacheable
|| u
->store
) {
2120 if (ngx_shutdown_socket(c
->fd
, NGX_WRITE_SHUTDOWN
) == -1) {
2121 ngx_connection_error(c
, ngx_socket_errno
,
2122 ngx_shutdown_socket_n
" failed");
2125 r
->read_event_handler
= ngx_http_request_empty_handler
;
2126 r
->write_event_handler
= ngx_http_request_empty_handler
;
2130 ngx_http_upstream_finalize_request(r
, u
, rc
);
2137 if (r
->request_body
&& r
->request_body
->temp_file
) {
2138 ngx_pool_run_cleanup_file(r
->pool
, r
->request_body
->temp_file
->file
.fd
);
2139 r
->request_body
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
2142 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2144 if (!u
->buffering
) {
2146 if (u
->input_filter
== NULL
) {
2147 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
2148 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
2149 u
->input_filter_ctx
= r
;
2152 u
->read_event_handler
= ngx_http_upstream_process_non_buffered_upstream
;
2153 r
->write_event_handler
=
2154 ngx_http_upstream_process_non_buffered_downstream
;
2158 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
2159 ngx_http_upstream_finalize_request(r
, u
, 0);
2163 if (clcf
->tcp_nodelay
&& c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
) {
2164 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
2168 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
2169 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
2171 ngx_connection_error(c
, ngx_socket_errno
,
2172 "setsockopt(TCP_NODELAY) failed");
2173 ngx_http_upstream_finalize_request(r
, u
, 0);
2177 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
2180 n
= u
->buffer
.last
- u
->buffer
.pos
;
2183 u
->buffer
.last
= u
->buffer
.pos
;
2185 u
->state
->response_length
+= n
;
2187 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
2188 ngx_http_upstream_finalize_request(r
, u
, 0);
2192 ngx_http_upstream_process_non_buffered_downstream(r
);
2195 u
->buffer
.pos
= u
->buffer
.start
;
2196 u
->buffer
.last
= u
->buffer
.start
;
2198 if (ngx_http_send_special(r
, NGX_HTTP_FLUSH
) == NGX_ERROR
) {
2199 ngx_http_upstream_finalize_request(r
, u
, 0);
2203 if (u
->peer
.connection
->read
->ready
|| u
->length
== 0) {
2204 ngx_http_upstream_process_non_buffered_upstream(r
, u
);
2211 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
2213 #if (NGX_HTTP_CACHE)
2215 if (r
->cache
&& r
->cache
->file
.fd
!= NGX_INVALID_FILE
) {
2216 ngx_pool_run_cleanup_file(r
->pool
, r
->cache
->file
.fd
);
2217 r
->cache
->file
.fd
= NGX_INVALID_FILE
;
2220 switch (ngx_http_test_predicates(r
, u
->conf
->no_cache
)) {
2223 ngx_http_upstream_finalize_request(r
, u
, 0);
2230 default: /* NGX_OK */
2232 if (u
->cache_status
== NGX_HTTP_CACHE_BYPASS
) {
2234 r
->cache
->min_uses
= u
->conf
->cache_min_uses
;
2235 r
->cache
->body_start
= u
->conf
->buffer_size
;
2236 r
->cache
->file_cache
= u
->conf
->cache
->data
;
2238 if (ngx_http_file_cache_create(r
) != NGX_OK
) {
2239 ngx_http_upstream_finalize_request(r
, u
, 0);
2252 valid
= r
->cache
->valid_sec
;
2255 valid
= ngx_http_file_cache_valid(u
->conf
->cache_valid
,
2256 u
->headers_in
.status_n
);
2258 r
->cache
->valid_sec
= now
+ valid
;
2263 r
->cache
->last_modified
= r
->headers_out
.last_modified_time
;
2264 r
->cache
->date
= now
;
2265 r
->cache
->body_start
= (u_short
) (u
->buffer
.pos
- u
->buffer
.start
);
2267 ngx_http_file_cache_set_header(r
, u
->buffer
.start
);
2271 r
->headers_out
.last_modified_time
= -1;
2275 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2276 "http cacheable: %d", u
->cacheable
);
2278 if (u
->cacheable
== 0 && r
->cache
) {
2279 ngx_http_file_cache_free(r
->cache
, u
->pipe
->temp_file
);
2286 p
->output_filter
= (ngx_event_pipe_output_filter_pt
) ngx_http_output_filter
;
2288 p
->tag
= u
->output
.tag
;
2289 p
->bufs
= u
->conf
->bufs
;
2290 p
->busy_size
= u
->conf
->busy_buffers_size
;
2291 p
->upstream
= u
->peer
.connection
;
2296 p
->cacheable
= u
->cacheable
|| u
->store
;
2298 p
->temp_file
= ngx_pcalloc(r
->pool
, sizeof(ngx_temp_file_t
));
2299 if (p
->temp_file
== NULL
) {
2300 ngx_http_upstream_finalize_request(r
, u
, 0);
2304 p
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
2305 p
->temp_file
->file
.log
= c
->log
;
2306 p
->temp_file
->path
= u
->conf
->temp_path
;
2307 p
->temp_file
->pool
= r
->pool
;
2310 p
->temp_file
->persistent
= 1;
2313 p
->temp_file
->log_level
= NGX_LOG_WARN
;
2314 p
->temp_file
->warn
= "an upstream response is buffered "
2315 "to a temporary file";
2318 p
->max_temp_file_size
= u
->conf
->max_temp_file_size
;
2319 p
->temp_file_write_size
= u
->conf
->temp_file_write_size
;
2321 p
->preread_bufs
= ngx_alloc_chain_link(r
->pool
);
2322 if (p
->preread_bufs
== NULL
) {
2323 ngx_http_upstream_finalize_request(r
, u
, 0);
2327 p
->preread_bufs
->buf
= &u
->buffer
;
2328 p
->preread_bufs
->next
= NULL
;
2329 u
->buffer
.recycled
= 1;
2331 p
->preread_size
= u
->buffer
.last
- u
->buffer
.pos
;
2335 p
->buf_to_file
= ngx_calloc_buf(r
->pool
);
2336 if (p
->buf_to_file
== NULL
) {
2337 ngx_http_upstream_finalize_request(r
, u
, 0);
2341 p
->buf_to_file
->start
= u
->buffer
.start
;
2342 p
->buf_to_file
->pos
= u
->buffer
.start
;
2343 p
->buf_to_file
->last
= u
->buffer
.pos
;
2344 p
->buf_to_file
->temporary
= 1;
2347 if (ngx_event_flags
& NGX_USE_AIO_EVENT
) {
2348 /* the posted aio operation may corrupt a shadow buffer */
2352 /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
2356 * event_pipe would do u->buffer.last += p->preread_size
2357 * as though these bytes were read
2359 u
->buffer
.last
= u
->buffer
.pos
;
2361 if (u
->conf
->cyclic_temp_file
) {
2364 * we need to disable the use of sendfile() if we use cyclic temp file
2365 * because the writing a new data may interfere with sendfile()
2366 * that uses the same kernel file pages (at least on FreeBSD)
2369 p
->cyclic_temp_file
= 1;
2373 p
->cyclic_temp_file
= 0;
2376 p
->read_timeout
= u
->conf
->read_timeout
;
2377 p
->send_timeout
= clcf
->send_timeout
;
2378 p
->send_lowat
= clcf
->send_lowat
;
2382 if (u
->input_filter_init
2383 && u
->input_filter_init(p
->input_ctx
) != NGX_OK
)
2385 ngx_http_upstream_finalize_request(r
, u
, 0);
2389 u
->read_event_handler
= ngx_http_upstream_process_upstream
;
2390 r
->write_event_handler
= ngx_http_upstream_process_downstream
;
2392 ngx_http_upstream_process_upstream(r
, u
);
2397 ngx_http_upstream_upgrade(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
2400 ngx_connection_t
*c
;
2401 ngx_http_core_loc_conf_t
*clcf
;
2404 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2406 /* TODO: prevent upgrade if not requested or not possible */
2409 c
->log
->action
= "proxying upgraded connection";
2411 u
->read_event_handler
= ngx_http_upstream_upgraded_read_upstream
;
2412 u
->write_event_handler
= ngx_http_upstream_upgraded_write_upstream
;
2413 r
->read_event_handler
= ngx_http_upstream_upgraded_read_downstream
;
2414 r
->write_event_handler
= ngx_http_upstream_upgraded_write_downstream
;
2416 if (clcf
->tcp_nodelay
) {
2419 if (c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
) {
2420 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
2422 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
2423 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
2425 ngx_connection_error(c
, ngx_socket_errno
,
2426 "setsockopt(TCP_NODELAY) failed");
2427 ngx_http_upstream_finalize_request(r
, u
, 0);
2431 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
2434 if (u
->peer
.connection
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
) {
2435 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, u
->peer
.connection
->log
, 0,
2438 if (setsockopt(u
->peer
.connection
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
2439 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
2441 ngx_connection_error(u
->peer
.connection
, ngx_socket_errno
,
2442 "setsockopt(TCP_NODELAY) failed");
2443 ngx_http_upstream_finalize_request(r
, u
, 0);
2447 u
->peer
.connection
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
2451 if (ngx_http_send_special(r
, NGX_HTTP_FLUSH
) == NGX_ERROR
) {
2452 ngx_http_upstream_finalize_request(r
, u
, 0);
2456 if (u
->peer
.connection
->read
->ready
2457 || u
->buffer
.pos
!= u
->buffer
.last
)
2459 ngx_http_upstream_process_upgraded(r
, 1, 1);
2463 || r
->header_in
->pos
!= r
->header_in
->last
)
2465 ngx_http_upstream_process_upgraded(r
, 0, 1);
2471 ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t
*r
)
2473 ngx_http_upstream_process_upgraded(r
, 0, 0);
2478 ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t
*r
)
2480 ngx_http_upstream_process_upgraded(r
, 1, 1);
2485 ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t
*r
,
2486 ngx_http_upstream_t
*u
)
2488 ngx_http_upstream_process_upgraded(r
, 1, 0);
2493 ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t
*r
,
2494 ngx_http_upstream_t
*u
)
2496 ngx_http_upstream_process_upgraded(r
, 0, 1);
2501 ngx_http_upstream_process_upgraded(ngx_http_request_t
*r
,
2502 ngx_uint_t from_upstream
, ngx_uint_t do_write
)
2507 ngx_connection_t
*c
, *downstream
, *upstream
, *dst
, *src
;
2508 ngx_http_upstream_t
*u
;
2509 ngx_http_core_loc_conf_t
*clcf
;
2514 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2515 "http upstream process upgraded, fu:%ui", from_upstream
);
2518 upstream
= u
->peer
.connection
;
2520 if (downstream
->write
->timedout
) {
2522 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
2523 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_REQUEST_TIME_OUT
);
2527 if (upstream
->read
->timedout
|| upstream
->write
->timedout
) {
2528 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
2529 ngx_http_upstream_finalize_request(r
, u
, 0);
2533 if (from_upstream
) {
2541 b
= &u
->from_client
;
2543 if (r
->header_in
->last
> r
->header_in
->pos
) {
2549 if (b
->start
== NULL
) {
2550 b
->start
= ngx_palloc(r
->pool
, u
->conf
->buffer_size
);
2551 if (b
->start
== NULL
) {
2552 ngx_http_upstream_finalize_request(r
, u
, 0);
2558 b
->end
= b
->start
+ u
->conf
->buffer_size
;
2560 b
->tag
= u
->output
.tag
;
2568 size
= b
->last
- b
->pos
;
2570 if (size
&& dst
->write
->ready
) {
2572 n
= dst
->send(dst
, b
->pos
, size
);
2574 if (n
== NGX_ERROR
) {
2575 ngx_http_upstream_finalize_request(r
, u
, 0);
2582 if (b
->pos
== b
->last
) {
2590 size
= b
->end
- b
->last
;
2592 if (size
&& src
->read
->ready
) {
2594 n
= src
->recv(src
, b
->last
, size
);
2596 if (n
== NGX_AGAIN
|| n
== 0) {
2607 if (n
== NGX_ERROR
) {
2615 if ((upstream
->read
->eof
&& u
->buffer
.pos
== u
->buffer
.last
)
2616 || (downstream
->read
->eof
&& u
->from_client
.pos
== u
->from_client
.last
)
2617 || (downstream
->read
->eof
&& upstream
->read
->eof
))
2619 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2620 "http upstream upgraded done");
2621 ngx_http_upstream_finalize_request(r
, u
, 0);
2625 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2627 if (ngx_handle_write_event(upstream
->write
, u
->conf
->send_lowat
)
2630 ngx_http_upstream_finalize_request(r
, u
, 0);
2634 if (upstream
->write
->active
&& !upstream
->write
->ready
) {
2635 ngx_add_timer(upstream
->write
, u
->conf
->send_timeout
);
2637 } else if (upstream
->write
->timer_set
) {
2638 ngx_del_timer(upstream
->write
);
2641 if (ngx_handle_read_event(upstream
->read
, 0) != NGX_OK
) {
2642 ngx_http_upstream_finalize_request(r
, u
, 0);
2646 if (upstream
->read
->active
&& !upstream
->read
->ready
) {
2647 ngx_add_timer(upstream
->read
, u
->conf
->read_timeout
);
2649 } else if (upstream
->read
->timer_set
) {
2650 ngx_del_timer(upstream
->read
);
2653 if (ngx_handle_write_event(downstream
->write
, clcf
->send_lowat
)
2656 ngx_http_upstream_finalize_request(r
, u
, 0);
2660 if (ngx_handle_read_event(downstream
->read
, 0) != NGX_OK
) {
2661 ngx_http_upstream_finalize_request(r
, u
, 0);
2665 if (downstream
->write
->active
&& !downstream
->write
->ready
) {
2666 ngx_add_timer(downstream
->write
, clcf
->send_timeout
);
2668 } else if (downstream
->write
->timer_set
) {
2669 ngx_del_timer(downstream
->write
);
2675 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
)
2678 ngx_connection_t
*c
;
2679 ngx_http_upstream_t
*u
;
2685 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2686 "http upstream process non buffered downstream");
2688 c
->log
->action
= "sending to client";
2690 if (wev
->timedout
) {
2692 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
2693 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_REQUEST_TIME_OUT
);
2697 ngx_http_upstream_process_non_buffered_request(r
, 1);
2702 ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t
*r
,
2703 ngx_http_upstream_t
*u
)
2705 ngx_connection_t
*c
;
2707 c
= u
->peer
.connection
;
2709 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2710 "http upstream process non buffered upstream");
2712 c
->log
->action
= "reading upstream";
2714 if (c
->read
->timedout
) {
2715 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
2716 ngx_http_upstream_finalize_request(r
, u
, 0);
2720 ngx_http_upstream_process_non_buffered_request(r
, 0);
2725 ngx_http_upstream_process_non_buffered_request(ngx_http_request_t
*r
,
2726 ngx_uint_t do_write
)
2732 ngx_connection_t
*downstream
, *upstream
;
2733 ngx_http_upstream_t
*u
;
2734 ngx_http_core_loc_conf_t
*clcf
;
2737 downstream
= r
->connection
;
2738 upstream
= u
->peer
.connection
;
2742 do_write
= do_write
|| u
->length
== 0;
2748 if (u
->out_bufs
|| u
->busy_bufs
) {
2749 rc
= ngx_http_output_filter(r
, u
->out_bufs
);
2751 if (rc
== NGX_ERROR
) {
2752 ngx_http_upstream_finalize_request(r
, u
, 0);
2756 ngx_chain_update_chains(r
->pool
, &u
->free_bufs
, &u
->busy_bufs
,
2757 &u
->out_bufs
, u
->output
.tag
);
2760 if (u
->busy_bufs
== NULL
) {
2763 || upstream
->read
->eof
2764 || upstream
->read
->error
)
2766 ngx_http_upstream_finalize_request(r
, u
, 0);
2775 size
= b
->end
- b
->last
;
2777 if (size
&& upstream
->read
->ready
) {
2779 n
= upstream
->recv(upstream
, b
->last
, size
);
2781 if (n
== NGX_AGAIN
) {
2786 u
->state
->response_length
+= n
;
2788 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
2789 ngx_http_upstream_finalize_request(r
, u
, 0);
2802 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2804 if (downstream
->data
== r
) {
2805 if (ngx_handle_write_event(downstream
->write
, clcf
->send_lowat
)
2808 ngx_http_upstream_finalize_request(r
, u
, 0);
2813 if (downstream
->write
->active
&& !downstream
->write
->ready
) {
2814 ngx_add_timer(downstream
->write
, clcf
->send_timeout
);
2816 } else if (downstream
->write
->timer_set
) {
2817 ngx_del_timer(downstream
->write
);
2820 if (ngx_handle_read_event(upstream
->read
, 0) != NGX_OK
) {
2821 ngx_http_upstream_finalize_request(r
, u
, 0);
2825 if (upstream
->read
->active
&& !upstream
->read
->ready
) {
2826 ngx_add_timer(upstream
->read
, u
->conf
->read_timeout
);
2828 } else if (upstream
->read
->timer_set
) {
2829 ngx_del_timer(upstream
->read
);
2835 ngx_http_upstream_non_buffered_filter_init(void *data
)
2842 ngx_http_upstream_non_buffered_filter(void *data
, ssize_t bytes
)
2844 ngx_http_request_t
*r
= data
;
2847 ngx_chain_t
*cl
, **ll
;
2848 ngx_http_upstream_t
*u
;
2852 for (cl
= u
->out_bufs
, ll
= &u
->out_bufs
; cl
; cl
= cl
->next
) {
2856 cl
= ngx_chain_get_free_buf(r
->pool
, &u
->free_bufs
);
2864 cl
->buf
->memory
= 1;
2868 cl
->buf
->pos
= b
->last
;
2870 cl
->buf
->last
= b
->last
;
2871 cl
->buf
->tag
= u
->output
.tag
;
2873 if (u
->length
== -1) {
2884 ngx_http_upstream_process_downstream(ngx_http_request_t
*r
)
2887 ngx_connection_t
*c
;
2888 ngx_event_pipe_t
*p
;
2889 ngx_http_upstream_t
*u
;
2896 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2897 "http upstream process downstream");
2899 c
->log
->action
= "sending to client";
2901 if (wev
->timedout
) {
2909 ngx_add_timer(wev
, p
->send_timeout
);
2911 if (ngx_handle_write_event(wev
, p
->send_lowat
) != NGX_OK
) {
2912 ngx_http_upstream_finalize_request(r
, u
, 0);
2918 if (ngx_event_pipe(p
, wev
->write
) == NGX_ABORT
) {
2919 ngx_http_upstream_finalize_request(r
, u
, 0);
2924 p
->downstream_error
= 1;
2926 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
2933 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2934 "http downstream delayed");
2936 if (ngx_handle_write_event(wev
, p
->send_lowat
) != NGX_OK
) {
2937 ngx_http_upstream_finalize_request(r
, u
, 0);
2943 if (ngx_event_pipe(p
, 1) == NGX_ABORT
) {
2944 ngx_http_upstream_finalize_request(r
, u
, 0);
2949 ngx_http_upstream_process_request(r
);
2954 ngx_http_upstream_process_upstream(ngx_http_request_t
*r
,
2955 ngx_http_upstream_t
*u
)
2957 ngx_connection_t
*c
;
2959 c
= u
->peer
.connection
;
2961 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2962 "http upstream process upstream");
2964 c
->log
->action
= "reading upstream";
2966 if (c
->read
->timedout
) {
2967 u
->pipe
->upstream_error
= 1;
2968 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
2971 if (ngx_event_pipe(u
->pipe
, 0) == NGX_ABORT
) {
2972 ngx_http_upstream_finalize_request(r
, u
, 0);
2977 ngx_http_upstream_process_request(r
);
2982 ngx_http_upstream_process_request(ngx_http_request_t
*r
)
2984 ngx_temp_file_t
*tf
;
2985 ngx_event_pipe_t
*p
;
2986 ngx_http_upstream_t
*u
;
2991 if (u
->peer
.connection
) {
2995 if (p
->upstream_eof
|| p
->upstream_done
) {
2997 tf
= u
->pipe
->temp_file
;
2999 if (u
->headers_in
.status_n
== NGX_HTTP_OK
3000 && (u
->headers_in
.content_length_n
== -1
3001 || (u
->headers_in
.content_length_n
== tf
->offset
)))
3003 ngx_http_upstream_store(r
, u
);
3009 #if (NGX_HTTP_CACHE)
3013 if (p
->upstream_done
) {
3014 ngx_http_file_cache_update(r
, u
->pipe
->temp_file
);
3016 } else if (p
->upstream_eof
) {
3018 tf
= u
->pipe
->temp_file
;
3020 if (u
->headers_in
.content_length_n
== -1
3021 || u
->headers_in
.content_length_n
3022 == tf
->offset
- (off_t
) r
->cache
->body_start
)
3024 ngx_http_file_cache_update(r
, tf
);
3027 ngx_http_file_cache_free(r
->cache
, tf
);
3030 } else if (p
->upstream_error
) {
3031 ngx_http_file_cache_free(r
->cache
, u
->pipe
->temp_file
);
3037 if (p
->upstream_done
|| p
->upstream_eof
|| p
->upstream_error
) {
3038 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3039 "http upstream exit: %p", p
->out
);
3041 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
3043 ngx_http_upstream_finalize_request(r
, u
, 0);
3048 if (p
->downstream_error
) {
3049 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3050 "http upstream downstream error");
3052 if (!u
->cacheable
&& !u
->store
&& u
->peer
.connection
) {
3053 ngx_http_upstream_finalize_request(r
, u
, 0);
3060 ngx_http_upstream_store(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
3065 ngx_temp_file_t
*tf
;
3066 ngx_ext_rename_file_t ext
;
3068 tf
= u
->pipe
->temp_file
;
3070 if (tf
->file
.fd
== NGX_INVALID_FILE
) {
3072 /* create file for empty 200 response */
3074 tf
= ngx_pcalloc(r
->pool
, sizeof(ngx_temp_file_t
));
3079 tf
->file
.fd
= NGX_INVALID_FILE
;
3080 tf
->file
.log
= r
->connection
->log
;
3081 tf
->path
= u
->conf
->temp_path
;
3085 if (ngx_create_temp_file(&tf
->file
, tf
->path
, tf
->pool
,
3086 tf
->persistent
, tf
->clean
, tf
->access
)
3092 u
->pipe
->temp_file
= tf
;
3095 ext
.access
= u
->conf
->store_access
;
3096 ext
.path_access
= u
->conf
->store_access
;
3098 ext
.create_path
= 1;
3099 ext
.delete_file
= 1;
3100 ext
.log
= r
->connection
->log
;
3102 if (u
->headers_in
.last_modified
) {
3104 lm
= ngx_http_parse_time(u
->headers_in
.last_modified
->value
.data
,
3105 u
->headers_in
.last_modified
->value
.len
);
3107 if (lm
!= NGX_ERROR
) {
3109 ext
.fd
= tf
->file
.fd
;
3113 if (u
->conf
->store_lengths
== NULL
) {
3115 ngx_http_map_uri_to_path(r
, &path
, &root
, 0);
3118 if (ngx_http_script_run(r
, &path
, u
->conf
->store_lengths
->elts
, 0,
3119 u
->conf
->store_values
->elts
)
3128 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3129 "upstream stores \"%s\" to \"%s\"",
3130 tf
->file
.name
.data
, path
.data
);
3132 (void) ngx_ext_rename_file(&tf
->file
.name
, &path
, &ext
);
3137 ngx_http_upstream_dummy_handler(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
3139 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3140 "http upstream dummy handler");
3145 ngx_http_upstream_next(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
,
3148 ngx_uint_t status
, state
;
3150 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3151 "http next upstream, %xi", ft_type
);
3154 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
3157 if (u
->peer
.sockaddr
) {
3159 if (ft_type
== NGX_HTTP_UPSTREAM_FT_HTTP_404
) {
3160 state
= NGX_PEER_NEXT
;
3162 state
= NGX_PEER_FAILED
;
3165 u
->peer
.free(&u
->peer
, u
->peer
.data
, state
);
3166 u
->peer
.sockaddr
= NULL
;
3169 if (ft_type
== NGX_HTTP_UPSTREAM_FT_TIMEOUT
) {
3170 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, NGX_ETIMEDOUT
,
3171 "upstream timed out");
3174 if (u
->peer
.cached
&& ft_type
== NGX_HTTP_UPSTREAM_FT_ERROR
) {
3177 /* TODO: inform balancer instead */
3184 case NGX_HTTP_UPSTREAM_FT_TIMEOUT
:
3185 status
= NGX_HTTP_GATEWAY_TIME_OUT
;
3188 case NGX_HTTP_UPSTREAM_FT_HTTP_500
:
3189 status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
3192 case NGX_HTTP_UPSTREAM_FT_HTTP_404
:
3193 status
= NGX_HTTP_NOT_FOUND
;
3197 * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
3202 status
= NGX_HTTP_BAD_GATEWAY
;
3206 if (r
->connection
->error
) {
3207 ngx_http_upstream_finalize_request(r
, u
,
3208 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
3213 u
->state
->status
= status
;
3215 if (u
->peer
.tries
== 0 || !(u
->conf
->next_upstream
& ft_type
)) {
3217 #if (NGX_HTTP_CACHE)
3219 if (u
->cache_status
== NGX_HTTP_CACHE_EXPIRED
3220 && (u
->conf
->cache_use_stale
& ft_type
))
3224 rc
= u
->reinit_request(r
);
3227 u
->cache_status
= NGX_HTTP_CACHE_STALE
;
3228 rc
= ngx_http_upstream_cache_send(r
, u
);
3231 ngx_http_upstream_finalize_request(r
, u
, rc
);
3236 ngx_http_upstream_finalize_request(r
, u
, status
);
3241 if (u
->peer
.connection
) {
3242 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3243 "close http upstream connection: %d",
3244 u
->peer
.connection
->fd
);
3247 if (u
->peer
.connection
->ssl
) {
3248 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
3249 u
->peer
.connection
->ssl
->no_send_shutdown
= 1;
3251 (void) ngx_ssl_shutdown(u
->peer
.connection
);
3255 if (u
->peer
.connection
->pool
) {
3256 ngx_destroy_pool(u
->peer
.connection
->pool
);
3259 ngx_close_connection(u
->peer
.connection
);
3260 u
->peer
.connection
= NULL
;
3264 if (u
->conf
->busy_lock
&& !u
->busy_locked
) {
3265 ngx_http_upstream_busy_lock(p
);
3270 ngx_http_upstream_connect(r
, u
);
3275 ngx_http_upstream_cleanup(void *data
)
3277 ngx_http_request_t
*r
= data
;
3279 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3280 "cleanup http upstream request: \"%V\"", &r
->uri
);
3282 ngx_http_upstream_finalize_request(r
, r
->upstream
, NGX_DONE
);
3287 ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
3288 ngx_http_upstream_t
*u
, ngx_int_t rc
)
3292 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3293 "finalize http upstream request: %i", rc
);
3300 if (u
->resolved
&& u
->resolved
->ctx
) {
3301 ngx_resolve_name_done(u
->resolved
->ctx
);
3302 u
->resolved
->ctx
= NULL
;
3305 if (u
->state
&& u
->state
->response_sec
) {
3306 tp
= ngx_timeofday();
3307 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
3308 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
3310 if (u
->pipe
&& u
->pipe
->read_length
) {
3311 u
->state
->response_length
= u
->pipe
->read_length
;
3315 u
->finalize_request(r
, rc
);
3317 if (u
->peer
.free
&& u
->peer
.sockaddr
) {
3318 u
->peer
.free(&u
->peer
, u
->peer
.data
, 0);
3319 u
->peer
.sockaddr
= NULL
;
3322 if (u
->peer
.connection
) {
3326 /* TODO: do not shutdown persistent connection */
3328 if (u
->peer
.connection
->ssl
) {
3331 * We send the "close notify" shutdown alert to the upstream only
3332 * and do not wait its "close notify" shutdown alert.
3333 * It is acceptable according to the TLS standard.
3336 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
3338 (void) ngx_ssl_shutdown(u
->peer
.connection
);
3342 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3343 "close http upstream connection: %d",
3344 u
->peer
.connection
->fd
);
3346 if (u
->peer
.connection
->pool
) {
3347 ngx_destroy_pool(u
->peer
.connection
->pool
);
3350 ngx_close_connection(u
->peer
.connection
);
3353 u
->peer
.connection
= NULL
;
3355 if (u
->pipe
&& u
->pipe
->temp_file
) {
3356 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3357 "http upstream temp fd: %d",
3358 u
->pipe
->temp_file
->file
.fd
);
3361 if (u
->store
&& u
->pipe
&& u
->pipe
->temp_file
3362 && u
->pipe
->temp_file
->file
.fd
!= NGX_INVALID_FILE
)
3364 if (ngx_delete_file(u
->pipe
->temp_file
->file
.name
.data
)
3367 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, ngx_errno
,
3368 ngx_delete_file_n
" \"%s\" failed",
3369 u
->pipe
->temp_file
->file
.name
.data
);
3373 #if (NGX_HTTP_CACHE)
3379 if (rc
== NGX_HTTP_BAD_GATEWAY
|| rc
== NGX_HTTP_GATEWAY_TIME_OUT
) {
3382 valid
= ngx_http_file_cache_valid(u
->conf
->cache_valid
, rc
);
3385 r
->cache
->valid_sec
= ngx_time() + valid
;
3386 r
->cache
->error
= rc
;
3391 ngx_http_file_cache_free(r
->cache
, u
->pipe
->temp_file
);
3397 && rc
!= NGX_HTTP_REQUEST_TIME_OUT
3398 && (rc
== NGX_ERROR
|| rc
>= NGX_HTTP_SPECIAL_RESPONSE
))
3403 if (rc
== NGX_DECLINED
) {
3407 r
->connection
->log
->action
= "sending to client";
3411 #if (NGX_HTTP_CACHE)
3416 rc
= ngx_http_send_special(r
, NGX_HTTP_LAST
);
3419 ngx_http_finalize_request(r
, rc
);
3424 ngx_http_upstream_process_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3427 ngx_table_elt_t
**ph
;
3429 ph
= (ngx_table_elt_t
**) ((char *) &r
->upstream
->headers_in
+ offset
);
3440 ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3448 ngx_http_upstream_process_content_length(ngx_http_request_t
*r
,
3449 ngx_table_elt_t
*h
, ngx_uint_t offset
)
3451 ngx_http_upstream_t
*u
;
3455 u
->headers_in
.content_length
= h
;
3456 u
->headers_in
.content_length_n
= ngx_atoof(h
->value
.data
, h
->value
.len
);
3463 ngx_http_upstream_process_set_cookie(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3466 #if (NGX_HTTP_CACHE)
3467 ngx_http_upstream_t
*u
;
3471 if (!(u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_SET_COOKIE
)) {
3481 ngx_http_upstream_process_cache_control(ngx_http_request_t
*r
,
3482 ngx_table_elt_t
*h
, ngx_uint_t offset
)
3485 ngx_table_elt_t
**ph
;
3486 ngx_http_upstream_t
*u
;
3489 pa
= &u
->headers_in
.cache_control
;
3491 if (pa
->elts
== NULL
) {
3492 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
3498 ph
= ngx_array_push(pa
);
3505 #if (NGX_HTTP_CACHE)
3510 if (u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL
) {
3514 if (r
->cache
== NULL
) {
3518 if (r
->cache
->valid_sec
!= 0) {
3523 last
= p
+ h
->value
.len
;
3525 if (ngx_strlcasestrn(p
, last
, (u_char
*) "no-cache", 8 - 1) != NULL
3526 || ngx_strlcasestrn(p
, last
, (u_char
*) "no-store", 8 - 1) != NULL
3527 || ngx_strlcasestrn(p
, last
, (u_char
*) "private", 7 - 1) != NULL
)
3533 p
= ngx_strlcasestrn(p
, last
, (u_char
*) "max-age=", 8 - 1);
3541 for (p
+= 8; p
< last
; p
++) {
3542 if (*p
== ',' || *p
== ';' || *p
== ' ') {
3546 if (*p
>= '0' && *p
<= '9') {
3547 n
= n
* 10 + *p
- '0';
3560 r
->cache
->valid_sec
= ngx_time() + n
;
3569 ngx_http_upstream_process_expires(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3572 ngx_http_upstream_t
*u
;
3575 u
->headers_in
.expires
= h
;
3577 #if (NGX_HTTP_CACHE)
3581 if (u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_EXPIRES
) {
3585 if (r
->cache
== NULL
) {
3589 if (r
->cache
->valid_sec
!= 0) {
3593 expires
= ngx_http_parse_time(h
->value
.data
, h
->value
.len
);
3595 if (expires
== NGX_ERROR
|| expires
< ngx_time()) {
3600 r
->cache
->valid_sec
= expires
;
3609 ngx_http_upstream_process_accel_expires(ngx_http_request_t
*r
,
3610 ngx_table_elt_t
*h
, ngx_uint_t offset
)
3612 ngx_http_upstream_t
*u
;
3615 u
->headers_in
.x_accel_expires
= h
;
3617 #if (NGX_HTTP_CACHE)
3623 if (u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES
) {
3627 if (r
->cache
== NULL
) {
3635 n
= ngx_atoi(p
, len
);
3646 r
->cache
->valid_sec
= ngx_time() + n
;
3654 n
= ngx_atoi(p
, len
);
3656 if (n
!= NGX_ERROR
) {
3657 r
->cache
->valid_sec
= n
;
3667 ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3671 ngx_http_upstream_t
*u
;
3674 u
->headers_in
.x_accel_limit_rate
= h
;
3676 if (u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE
) {
3680 n
= ngx_atoi(h
->value
.data
, h
->value
.len
);
3682 if (n
!= NGX_ERROR
) {
3683 r
->limit_rate
= (size_t) n
;
3691 ngx_http_upstream_process_buffering(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3695 ngx_http_upstream_t
*u
;
3699 if (u
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING
) {
3703 if (u
->conf
->change_buffering
) {
3705 if (h
->value
.len
== 2) {
3706 c0
= ngx_tolower(h
->value
.data
[0]);
3707 c1
= ngx_tolower(h
->value
.data
[1]);
3709 if (c0
== 'n' && c1
== 'o') {
3713 } else if (h
->value
.len
== 3) {
3714 c0
= ngx_tolower(h
->value
.data
[0]);
3715 c1
= ngx_tolower(h
->value
.data
[1]);
3716 c2
= ngx_tolower(h
->value
.data
[2]);
3718 if (c0
== 'y' && c1
== 'e' && c2
== 's') {
3729 ngx_http_upstream_process_charset(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3732 if (r
->upstream
->conf
->ignore_headers
& NGX_HTTP_UPSTREAM_IGN_XA_CHARSET
) {
3736 r
->headers_out
.override_charset
= &h
->value
;
3743 ngx_http_upstream_process_connection(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3746 r
->upstream
->headers_in
.connection
= h
;
3748 if (ngx_strlcasestrn(h
->value
.data
, h
->value
.data
+ h
->value
.len
,
3749 (u_char
*) "close", 5 - 1)
3752 r
->upstream
->headers_in
.connection_close
= 1;
3760 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t
*r
,
3761 ngx_table_elt_t
*h
, ngx_uint_t offset
)
3763 r
->upstream
->headers_in
.transfer_encoding
= h
;
3765 if (ngx_strlcasestrn(h
->value
.data
, h
->value
.data
+ h
->value
.len
,
3766 (u_char
*) "chunked", 7 - 1)
3769 r
->upstream
->headers_in
.chunked
= 1;
3777 ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3780 ngx_table_elt_t
*ho
, **ph
;
3782 ho
= ngx_list_push(&r
->headers_out
.headers
);
3790 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_out
+ offset
);
3799 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
3800 ngx_table_elt_t
*h
, ngx_uint_t offset
)
3803 ngx_table_elt_t
*ho
, **ph
;
3805 pa
= (ngx_array_t
*) ((char *) &r
->headers_out
+ offset
);
3807 if (pa
->elts
== NULL
) {
3808 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
3814 ph
= ngx_array_push(pa
);
3819 ho
= ngx_list_push(&r
->headers_out
.headers
);
3832 ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3837 r
->headers_out
.content_type_len
= h
->value
.len
;
3838 r
->headers_out
.content_type
= h
->value
;
3839 r
->headers_out
.content_type_lowcase
= NULL
;
3841 for (p
= h
->value
.data
; *p
; p
++) {
3849 while (*++p
== ' ') { /* void */ }
3855 if (ngx_strncasecmp(p
, (u_char
*) "charset=", 8) != 0) {
3861 r
->headers_out
.content_type_len
= last
- h
->value
.data
;
3867 last
= h
->value
.data
+ h
->value
.len
;
3869 if (*(last
- 1) == '"') {
3873 r
->headers_out
.charset
.len
= last
- p
;
3874 r
->headers_out
.charset
.data
= p
;
3884 ngx_http_upstream_copy_last_modified(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3887 ngx_table_elt_t
*ho
;
3889 ho
= ngx_list_push(&r
->headers_out
.headers
);
3896 r
->headers_out
.last_modified
= ho
;
3898 #if (NGX_HTTP_CACHE)
3900 if (r
->upstream
->cacheable
) {
3901 r
->headers_out
.last_modified_time
= ngx_http_parse_time(h
->value
.data
,
3912 ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3916 ngx_table_elt_t
*ho
;
3918 ho
= ngx_list_push(&r
->headers_out
.headers
);
3925 if (r
->upstream
->rewrite_redirect
) {
3926 rc
= r
->upstream
->rewrite_redirect(r
, ho
, 0);
3928 if (rc
== NGX_DECLINED
) {
3933 r
->headers_out
.location
= ho
;
3935 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3936 "rewritten location: \"%V\"", &ho
->value
);
3942 if (ho
->value
.data
[0] != '/') {
3943 r
->headers_out
.location
= ho
;
3947 * we do not set r->headers_out.location here to avoid the handling
3948 * the local redirects without a host name by ngx_http_header_filter()
3956 ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
3961 ngx_table_elt_t
*ho
;
3963 ho
= ngx_list_push(&r
->headers_out
.headers
);
3970 if (r
->upstream
->rewrite_redirect
) {
3972 p
= ngx_strcasestrn(ho
->value
.data
, "url=", 4 - 1);
3975 rc
= r
->upstream
->rewrite_redirect(r
, ho
, p
+ 4 - ho
->value
.data
);
3981 if (rc
== NGX_DECLINED
) {
3986 r
->headers_out
.refresh
= ho
;
3988 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
3989 "rewritten refresh: \"%V\"", &ho
->value
);
3995 r
->headers_out
.refresh
= ho
;
4002 ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
4006 ngx_table_elt_t
*ho
;
4008 ho
= ngx_list_push(&r
->headers_out
.headers
);
4015 if (r
->upstream
->rewrite_cookie
) {
4016 rc
= r
->upstream
->rewrite_cookie(r
, ho
);
4018 if (rc
== NGX_DECLINED
) {
4024 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
4025 "rewritten cookie: \"%V\"", &ho
->value
);
4037 ngx_http_upstream_copy_allow_ranges(ngx_http_request_t
*r
,
4038 ngx_table_elt_t
*h
, ngx_uint_t offset
)
4040 ngx_table_elt_t
*ho
;
4042 #if (NGX_HTTP_CACHE)
4045 r
->allow_ranges
= 1;
4052 ho
= ngx_list_push(&r
->headers_out
.headers
);
4059 r
->headers_out
.accept_ranges
= ho
;
4068 ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
4069 ngx_table_elt_t
*h
, ngx_uint_t offset
)
4071 ngx_table_elt_t
*ho
;
4073 ho
= ngx_list_push(&r
->headers_out
.headers
);
4080 r
->headers_out
.content_encoding
= ho
;
4089 ngx_http_upstream_add_variables(ngx_conf_t
*cf
)
4091 ngx_http_variable_t
*var
, *v
;
4093 for (v
= ngx_http_upstream_vars
; v
->name
.len
; v
++) {
4094 var
= ngx_http_add_variable(cf
, &v
->name
, v
->flags
);
4099 var
->get_handler
= v
->get_handler
;
4100 var
->data
= v
->data
;
4108 ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
4109 ngx_http_variable_value_t
*v
, uintptr_t data
)
4114 ngx_http_upstream_state_t
*state
;
4117 v
->no_cacheable
= 0;
4120 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
4126 state
= r
->upstream_states
->elts
;
4128 for (i
= 0; i
< r
->upstream_states
->nelts
; i
++) {
4129 if (state
[i
].peer
) {
4130 len
+= state
[i
].peer
->len
+ 2;
4137 p
= ngx_pnalloc(r
->pool
, len
);
4147 if (state
[i
].peer
) {
4148 p
= ngx_cpymem(p
, state
[i
].peer
->data
, state
[i
].peer
->len
);
4151 if (++i
== r
->upstream_states
->nelts
) {
4155 if (state
[i
].peer
) {
4164 if (++i
== r
->upstream_states
->nelts
) {
4172 v
->len
= p
- v
->data
;
4179 ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
4180 ngx_http_variable_value_t
*v
, uintptr_t data
)
4185 ngx_http_upstream_state_t
*state
;
4188 v
->no_cacheable
= 0;
4191 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
4196 len
= r
->upstream_states
->nelts
* (3 + 2);
4198 p
= ngx_pnalloc(r
->pool
, len
);
4206 state
= r
->upstream_states
->elts
;
4209 if (state
[i
].status
) {
4210 p
= ngx_sprintf(p
, "%ui", state
[i
].status
);
4216 if (++i
== r
->upstream_states
->nelts
) {
4220 if (state
[i
].peer
) {
4229 if (++i
== r
->upstream_states
->nelts
) {
4237 v
->len
= p
- v
->data
;
4244 ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
4245 ngx_http_variable_value_t
*v
, uintptr_t data
)
4251 ngx_http_upstream_state_t
*state
;
4254 v
->no_cacheable
= 0;
4257 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
4262 len
= r
->upstream_states
->nelts
* (NGX_TIME_T_LEN
+ 4 + 2);
4264 p
= ngx_pnalloc(r
->pool
, len
);
4272 state
= r
->upstream_states
->elts
;
4275 if (state
[i
].status
) {
4276 ms
= (ngx_msec_int_t
)
4277 (state
[i
].response_sec
* 1000 + state
[i
].response_msec
);
4278 ms
= ngx_max(ms
, 0);
4279 p
= ngx_sprintf(p
, "%d.%03d", ms
/ 1000, ms
% 1000);
4285 if (++i
== r
->upstream_states
->nelts
) {
4289 if (state
[i
].peer
) {
4298 if (++i
== r
->upstream_states
->nelts
) {
4306 v
->len
= p
- v
->data
;
4313 ngx_http_upstream_response_length_variable(ngx_http_request_t
*r
,
4314 ngx_http_variable_value_t
*v
, uintptr_t data
)
4319 ngx_http_upstream_state_t
*state
;
4322 v
->no_cacheable
= 0;
4325 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
4330 len
= r
->upstream_states
->nelts
* (NGX_OFF_T_LEN
+ 2);
4332 p
= ngx_pnalloc(r
->pool
, len
);
4340 state
= r
->upstream_states
->elts
;
4343 p
= ngx_sprintf(p
, "%O", state
[i
].response_length
);
4345 if (++i
== r
->upstream_states
->nelts
) {
4349 if (state
[i
].peer
) {
4358 if (++i
== r
->upstream_states
->nelts
) {
4366 v
->len
= p
- v
->data
;
4373 ngx_http_upstream_header_variable(ngx_http_request_t
*r
,
4374 ngx_http_variable_value_t
*v
, uintptr_t data
)
4376 if (r
->upstream
== NULL
) {
4381 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
4382 &r
->upstream
->headers_in
.headers
.part
,
4383 sizeof("upstream_http_") - 1);
4387 #if (NGX_HTTP_CACHE)
4390 ngx_http_upstream_cache_status(ngx_http_request_t
*r
,
4391 ngx_http_variable_value_t
*v
, uintptr_t data
)
4395 if (r
->upstream
== NULL
|| r
->upstream
->cache_status
== 0) {
4400 n
= r
->upstream
->cache_status
- 1;
4403 v
->no_cacheable
= 0;
4405 v
->len
= ngx_http_cache_status
[n
].len
;
4406 v
->data
= ngx_http_cache_status
[n
].data
;
4415 ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
)
4423 ngx_http_module_t
*module
;
4424 ngx_http_conf_ctx_t
*ctx
, *http_ctx
;
4425 ngx_http_upstream_srv_conf_t
*uscf
;
4427 ngx_memzero(&u
, sizeof(ngx_url_t
));
4429 value
= cf
->args
->elts
;
4434 uscf
= ngx_http_upstream_add(cf
, &u
, NGX_HTTP_UPSTREAM_CREATE
4435 |NGX_HTTP_UPSTREAM_WEIGHT
4436 |NGX_HTTP_UPSTREAM_MAX_FAILS
4437 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
4438 |NGX_HTTP_UPSTREAM_DOWN
4439 |NGX_HTTP_UPSTREAM_BACKUP
);
4441 return NGX_CONF_ERROR
;
4445 ctx
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_conf_ctx_t
));
4447 return NGX_CONF_ERROR
;
4451 ctx
->main_conf
= http_ctx
->main_conf
;
4453 /* the upstream{}'s srv_conf */
4455 ctx
->srv_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
4456 if (ctx
->srv_conf
== NULL
) {
4457 return NGX_CONF_ERROR
;
4460 ctx
->srv_conf
[ngx_http_upstream_module
.ctx_index
] = uscf
;
4462 uscf
->srv_conf
= ctx
->srv_conf
;
4465 /* the upstream{}'s loc_conf */
4467 ctx
->loc_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
4468 if (ctx
->loc_conf
== NULL
) {
4469 return NGX_CONF_ERROR
;
4472 for (m
= 0; ngx_modules
[m
]; m
++) {
4473 if (ngx_modules
[m
]->type
!= NGX_HTTP_MODULE
) {
4477 module
= ngx_modules
[m
]->ctx
;
4479 if (module
->create_srv_conf
) {
4480 mconf
= module
->create_srv_conf(cf
);
4481 if (mconf
== NULL
) {
4482 return NGX_CONF_ERROR
;
4485 ctx
->srv_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
4488 if (module
->create_loc_conf
) {
4489 mconf
= module
->create_loc_conf(cf
);
4490 if (mconf
== NULL
) {
4491 return NGX_CONF_ERROR
;
4494 ctx
->loc_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
4499 /* parse inside upstream{} */
4503 cf
->cmd_type
= NGX_HTTP_UPS_CONF
;
4505 rv
= ngx_conf_parse(cf
, NULL
);
4509 if (rv
!= NGX_CONF_OK
) {
4513 if (uscf
->servers
== NULL
) {
4514 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4515 "no servers are inside upstream");
4516 return NGX_CONF_ERROR
;
4524 ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
4526 ngx_http_upstream_srv_conf_t
*uscf
= conf
;
4528 time_t fail_timeout
;
4529 ngx_str_t
*value
, s
;
4531 ngx_int_t weight
, max_fails
;
4533 ngx_http_upstream_server_t
*us
;
4535 if (uscf
->servers
== NULL
) {
4536 uscf
->servers
= ngx_array_create(cf
->pool
, 4,
4537 sizeof(ngx_http_upstream_server_t
));
4538 if (uscf
->servers
== NULL
) {
4539 return NGX_CONF_ERROR
;
4543 us
= ngx_array_push(uscf
->servers
);
4545 return NGX_CONF_ERROR
;
4548 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
4550 value
= cf
->args
->elts
;
4552 ngx_memzero(&u
, sizeof(ngx_url_t
));
4555 u
.default_port
= 80;
4557 if (ngx_parse_url(cf
->pool
, &u
) != NGX_OK
) {
4559 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4560 "%s in upstream \"%V\"", u
.err
, &u
.url
);
4563 return NGX_CONF_ERROR
;
4570 for (i
= 2; i
< cf
->args
->nelts
; i
++) {
4572 if (ngx_strncmp(value
[i
].data
, "weight=", 7) == 0) {
4574 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_WEIGHT
)) {
4578 weight
= ngx_atoi(&value
[i
].data
[7], value
[i
].len
- 7);
4580 if (weight
== NGX_ERROR
|| weight
== 0) {
4587 if (ngx_strncmp(value
[i
].data
, "max_fails=", 10) == 0) {
4589 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_MAX_FAILS
)) {
4593 max_fails
= ngx_atoi(&value
[i
].data
[10], value
[i
].len
- 10);
4595 if (max_fails
== NGX_ERROR
) {
4602 if (ngx_strncmp(value
[i
].data
, "fail_timeout=", 13) == 0) {
4604 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
)) {
4608 s
.len
= value
[i
].len
- 13;
4609 s
.data
= &value
[i
].data
[13];
4611 fail_timeout
= ngx_parse_time(&s
, 1);
4613 if (fail_timeout
== (time_t) NGX_ERROR
) {
4620 if (ngx_strncmp(value
[i
].data
, "backup", 6) == 0) {
4622 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_BACKUP
)) {
4631 if (ngx_strncmp(value
[i
].data
, "down", 4) == 0) {
4633 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_DOWN
)) {
4645 us
->addrs
= u
.addrs
;
4646 us
->naddrs
= u
.naddrs
;
4647 us
->weight
= weight
;
4648 us
->max_fails
= max_fails
;
4649 us
->fail_timeout
= fail_timeout
;
4655 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4656 "invalid parameter \"%V\"", &value
[i
]);
4658 return NGX_CONF_ERROR
;
4662 ngx_http_upstream_srv_conf_t
*
4663 ngx_http_upstream_add(ngx_conf_t
*cf
, ngx_url_t
*u
, ngx_uint_t flags
)
4666 ngx_http_upstream_server_t
*us
;
4667 ngx_http_upstream_srv_conf_t
*uscf
, **uscfp
;
4668 ngx_http_upstream_main_conf_t
*umcf
;
4670 if (!(flags
& NGX_HTTP_UPSTREAM_CREATE
)) {
4672 if (ngx_parse_url(cf
->pool
, u
) != NGX_OK
) {
4674 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4675 "%s in upstream \"%V\"", u
->err
, &u
->url
);
4682 umcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_upstream_module
);
4684 uscfp
= umcf
->upstreams
.elts
;
4686 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
4688 if (uscfp
[i
]->host
.len
!= u
->host
.len
4689 || ngx_strncasecmp(uscfp
[i
]->host
.data
, u
->host
.data
, u
->host
.len
)
4695 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
)
4696 && (uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
))
4698 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4699 "duplicate upstream \"%V\"", &u
->host
);
4703 if ((uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
) && !u
->no_port
) {
4704 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
4705 "upstream \"%V\" may not have port %d",
4710 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
) && !uscfp
[i
]->no_port
) {
4711 ngx_log_error(NGX_LOG_WARN
, cf
->log
, 0,
4712 "upstream \"%V\" may not have port %d in %s:%ui",
4713 &u
->host
, uscfp
[i
]->port
,
4714 uscfp
[i
]->file_name
, uscfp
[i
]->line
);
4718 if (uscfp
[i
]->port
&& u
->port
4719 && uscfp
[i
]->port
!= u
->port
)
4724 if (uscfp
[i
]->default_port
&& u
->default_port
4725 && uscfp
[i
]->default_port
!= u
->default_port
)
4730 if (flags
& NGX_HTTP_UPSTREAM_CREATE
) {
4731 uscfp
[i
]->flags
= flags
;
4737 uscf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_srv_conf_t
));
4742 uscf
->flags
= flags
;
4743 uscf
->host
= u
->host
;
4744 uscf
->file_name
= cf
->conf_file
->file
.name
.data
;
4745 uscf
->line
= cf
->conf_file
->line
;
4746 uscf
->port
= u
->port
;
4747 uscf
->default_port
= u
->default_port
;
4748 uscf
->no_port
= u
->no_port
;
4750 if (u
->naddrs
== 1) {
4751 uscf
->servers
= ngx_array_create(cf
->pool
, 1,
4752 sizeof(ngx_http_upstream_server_t
));
4753 if (uscf
->servers
== NULL
) {
4757 us
= ngx_array_push(uscf
->servers
);
4762 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
4764 us
->addrs
= u
->addrs
;
4768 uscfp
= ngx_array_push(&umcf
->upstreams
);
4769 if (uscfp
== NULL
) {
4780 ngx_http_upstream_bind_set_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
4787 ngx_http_complex_value_t cv
;
4788 ngx_http_upstream_local_t
**plocal
, *local
;
4789 ngx_http_compile_complex_value_t ccv
;
4791 plocal
= (ngx_http_upstream_local_t
**) (p
+ cmd
->offset
);
4793 if (*plocal
!= NGX_CONF_UNSET_PTR
) {
4794 return "is duplicate";
4797 value
= cf
->args
->elts
;
4799 if (ngx_strcmp(value
[1].data
, "off") == 0) {
4804 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
4807 ccv
.value
= &value
[1];
4808 ccv
.complex_value
= &cv
;
4810 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
4811 return NGX_CONF_ERROR
;
4814 local
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_local_t
));
4815 if (local
== NULL
) {
4816 return NGX_CONF_ERROR
;
4822 local
->value
= ngx_palloc(cf
->pool
, sizeof(ngx_http_complex_value_t
));
4823 if (local
->value
== NULL
) {
4824 return NGX_CONF_ERROR
;
4832 local
->addr
= ngx_palloc(cf
->pool
, sizeof(ngx_addr_t
));
4833 if (local
->addr
== NULL
) {
4834 return NGX_CONF_ERROR
;
4837 rc
= ngx_parse_addr(cf
->pool
, local
->addr
, value
[1].data
, value
[1].len
);
4841 local
->addr
->name
= value
[1];
4845 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4846 "invalid address \"%V\"", &value
[1]);
4850 return NGX_CONF_ERROR
;
4856 ngx_http_upstream_get_local(ngx_http_request_t
*r
,
4857 ngx_http_upstream_local_t
*local
)
4863 if (local
== NULL
) {
4867 if (local
->value
== NULL
) {
4871 if (ngx_http_complex_value(r
, local
->value
, &val
) != NGX_OK
) {
4879 addr
= ngx_palloc(r
->pool
, sizeof(ngx_addr_t
));
4884 rc
= ngx_parse_addr(r
->pool
, addr
, val
.data
, val
.len
);
4892 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
4893 "invalid local address \"%V\"", &val
);
4903 ngx_http_upstream_param_set_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
4910 ngx_http_upstream_param_t
*param
;
4912 a
= (ngx_array_t
**) (p
+ cmd
->offset
);
4915 *a
= ngx_array_create(cf
->pool
, 4, sizeof(ngx_http_upstream_param_t
));
4917 return NGX_CONF_ERROR
;
4921 param
= ngx_array_push(*a
);
4922 if (param
== NULL
) {
4923 return NGX_CONF_ERROR
;
4926 value
= cf
->args
->elts
;
4928 param
->key
= value
[1];
4929 param
->value
= value
[2];
4930 param
->skip_empty
= 0;
4932 if (cf
->args
->nelts
== 4) {
4933 if (ngx_strcmp(value
[3].data
, "if_not_empty") != 0) {
4934 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
4935 "invalid parameter \"%V\"", &value
[3]);
4936 return NGX_CONF_ERROR
;
4939 param
->skip_empty
= 1;
4947 ngx_http_upstream_hide_headers_hash(ngx_conf_t
*cf
,
4948 ngx_http_upstream_conf_t
*conf
, ngx_http_upstream_conf_t
*prev
,
4949 ngx_str_t
*default_hide_headers
, ngx_hash_init_t
*hash
)
4953 ngx_array_t hide_headers
;
4956 if (conf
->hide_headers
== NGX_CONF_UNSET_PTR
4957 && conf
->pass_headers
== NGX_CONF_UNSET_PTR
)
4959 conf
->hide_headers
= prev
->hide_headers
;
4960 conf
->pass_headers
= prev
->pass_headers
;
4962 conf
->hide_headers_hash
= prev
->hide_headers_hash
;
4964 if (conf
->hide_headers_hash
.buckets
4965 #if (NGX_HTTP_CACHE)
4966 && ((conf
->cache
== NULL
) == (prev
->cache
== NULL
))
4974 if (conf
->hide_headers
== NGX_CONF_UNSET_PTR
) {
4975 conf
->hide_headers
= prev
->hide_headers
;
4978 if (conf
->pass_headers
== NGX_CONF_UNSET_PTR
) {
4979 conf
->pass_headers
= prev
->pass_headers
;
4983 if (ngx_array_init(&hide_headers
, cf
->temp_pool
, 4, sizeof(ngx_hash_key_t
))
4989 for (h
= default_hide_headers
; h
->len
; h
++) {
4990 hk
= ngx_array_push(&hide_headers
);
4996 hk
->key_hash
= ngx_hash_key_lc(h
->data
, h
->len
);
4997 hk
->value
= (void *) 1;
5000 if (conf
->hide_headers
!= NGX_CONF_UNSET_PTR
) {
5002 h
= conf
->hide_headers
->elts
;
5004 for (i
= 0; i
< conf
->hide_headers
->nelts
; i
++) {
5006 hk
= hide_headers
.elts
;
5008 for (j
= 0; j
< hide_headers
.nelts
; j
++) {
5009 if (ngx_strcasecmp(h
[i
].data
, hk
[j
].key
.data
) == 0) {
5014 hk
= ngx_array_push(&hide_headers
);
5020 hk
->key_hash
= ngx_hash_key_lc(h
[i
].data
, h
[i
].len
);
5021 hk
->value
= (void *) 1;
5029 if (conf
->pass_headers
!= NGX_CONF_UNSET_PTR
) {
5031 h
= conf
->pass_headers
->elts
;
5032 hk
= hide_headers
.elts
;
5034 for (i
= 0; i
< conf
->pass_headers
->nelts
; i
++) {
5035 for (j
= 0; j
< hide_headers
.nelts
; j
++) {
5037 if (hk
[j
].key
.data
== NULL
) {
5041 if (ngx_strcasecmp(h
[i
].data
, hk
[j
].key
.data
) == 0) {
5042 hk
[j
].key
.data
= NULL
;
5049 hash
->hash
= &conf
->hide_headers_hash
;
5050 hash
->key
= ngx_hash_key_lc
;
5051 hash
->pool
= cf
->pool
;
5052 hash
->temp_pool
= NULL
;
5054 return ngx_hash_init(hash
, hide_headers
.elts
, hide_headers
.nelts
);
5059 ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
)
5061 ngx_http_upstream_main_conf_t
*umcf
;
5063 umcf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_main_conf_t
));
5068 if (ngx_array_init(&umcf
->upstreams
, cf
->pool
, 4,
5069 sizeof(ngx_http_upstream_srv_conf_t
*))
5080 ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
)
5082 ngx_http_upstream_main_conf_t
*umcf
= conf
;
5085 ngx_array_t headers_in
;
5087 ngx_hash_init_t hash
;
5088 ngx_http_upstream_init_pt init
;
5089 ngx_http_upstream_header_t
*header
;
5090 ngx_http_upstream_srv_conf_t
**uscfp
;
5092 uscfp
= umcf
->upstreams
.elts
;
5094 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
5096 init
= uscfp
[i
]->peer
.init_upstream
? uscfp
[i
]->peer
.init_upstream
:
5097 ngx_http_upstream_init_round_robin
;
5099 if (init(cf
, uscfp
[i
]) != NGX_OK
) {
5100 return NGX_CONF_ERROR
;
5105 /* upstream_headers_in_hash */
5107 if (ngx_array_init(&headers_in
, cf
->temp_pool
, 32, sizeof(ngx_hash_key_t
))
5110 return NGX_CONF_ERROR
;
5113 for (header
= ngx_http_upstream_headers_in
; header
->name
.len
; header
++) {
5114 hk
= ngx_array_push(&headers_in
);
5116 return NGX_CONF_ERROR
;
5119 hk
->key
= header
->name
;
5120 hk
->key_hash
= ngx_hash_key_lc(header
->name
.data
, header
->name
.len
);
5124 hash
.hash
= &umcf
->headers_in_hash
;
5125 hash
.key
= ngx_hash_key_lc
;
5126 hash
.max_size
= 512;
5127 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
5128 hash
.name
= "upstream_headers_in_hash";
5129 hash
.pool
= cf
->pool
;
5130 hash
.temp_pool
= NULL
;
5132 if (ngx_hash_init(&hash
, headers_in
.elts
, headers_in
.nelts
) != NGX_OK
) {
5133 return NGX_CONF_ERROR
;