3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
);
13 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
);
14 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
16 static void ngx_http_upstream_connect(ngx_http_request_t
*r
,
17 ngx_http_upstream_t
*u
);
18 static ngx_int_t
ngx_http_upstream_reinit(ngx_http_request_t
*r
,
19 ngx_http_upstream_t
*u
);
20 static void ngx_http_upstream_send_request(ngx_http_request_t
*r
,
21 ngx_http_upstream_t
*u
);
22 static void ngx_http_upstream_send_request_handler(ngx_event_t
*wev
);
23 static void ngx_http_upstream_process_header(ngx_event_t
*rev
);
24 static ngx_int_t
ngx_http_upstream_test_connect(ngx_connection_t
*c
);
25 static void ngx_http_upstream_process_body_in_memory(ngx_event_t
*rev
);
26 static void ngx_http_upstream_send_response(ngx_http_request_t
*r
,
27 ngx_http_upstream_t
*u
);
29 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
);
30 static void ngx_http_upstream_process_non_buffered_body(ngx_event_t
*ev
);
31 static ngx_int_t
ngx_http_upstream_non_buffered_filter_init(void *data
);
32 static ngx_int_t
ngx_http_upstream_non_buffered_filter(void *data
,
34 static void ngx_http_upstream_process_downstream(ngx_http_request_t
*r
);
35 static void ngx_http_upstream_process_body(ngx_event_t
*ev
);
36 static void ngx_http_upstream_dummy_handler(ngx_event_t
*wev
);
37 static void ngx_http_upstream_next(ngx_http_request_t
*r
,
38 ngx_http_upstream_t
*u
, ngx_uint_t ft_type
);
39 static void ngx_http_upstream_cleanup(void *data
);
40 static void ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
41 ngx_http_upstream_t
*u
, ngx_int_t rc
);
43 static ngx_int_t
ngx_http_upstream_process_header_line(ngx_http_request_t
*r
,
44 ngx_table_elt_t
*h
, ngx_uint_t offset
);
46 ngx_http_upstream_process_multi_header_lines(ngx_http_request_t
*r
,
47 ngx_table_elt_t
*h
, ngx_uint_t offset
);
48 static ngx_int_t
ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
,
49 ngx_table_elt_t
*h
, ngx_uint_t offset
);
50 static ngx_int_t
ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
,
51 ngx_table_elt_t
*h
, ngx_uint_t offset
);
52 static ngx_int_t
ngx_http_upstream_process_buffering(ngx_http_request_t
*r
,
53 ngx_table_elt_t
*h
, ngx_uint_t offset
);
54 static ngx_int_t
ngx_http_upstream_process_charset(ngx_http_request_t
*r
,
55 ngx_table_elt_t
*h
, ngx_uint_t offset
);
56 static ngx_int_t
ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
,
57 ngx_table_elt_t
*h
, ngx_uint_t offset
);
59 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
60 ngx_table_elt_t
*h
, ngx_uint_t offset
);
61 static ngx_int_t
ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
,
62 ngx_table_elt_t
*h
, ngx_uint_t offset
);
63 static ngx_int_t
ngx_http_upstream_copy_content_length(ngx_http_request_t
*r
,
64 ngx_table_elt_t
*h
, ngx_uint_t offset
);
65 static ngx_int_t
ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
,
66 ngx_table_elt_t
*h
, ngx_uint_t offset
);
67 static ngx_int_t
ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
,
68 ngx_table_elt_t
*h
, ngx_uint_t offset
);
70 static ngx_int_t
ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
71 ngx_table_elt_t
*h
, ngx_uint_t offset
);
74 static ngx_int_t
ngx_http_upstream_add_variables(ngx_conf_t
*cf
);
75 static ngx_int_t
ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
76 ngx_http_variable_value_t
*v
, uintptr_t data
);
77 static ngx_int_t
ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
78 ngx_http_variable_value_t
*v
, uintptr_t data
);
79 static ngx_int_t
ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
80 ngx_http_variable_value_t
*v
, uintptr_t data
);
82 static char *ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
);
83 static char *ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
86 static void *ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
);
87 static char *ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
);
90 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*,
91 ngx_http_upstream_t
*u
, ngx_connection_t
*c
);
92 static void ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
);
96 ngx_http_upstream_header_t ngx_http_upstream_headers_in
[] = {
98 { ngx_string("Status"),
99 ngx_http_upstream_process_header_line
,
100 offsetof(ngx_http_upstream_headers_in_t
, status
),
101 ngx_http_upstream_copy_header_line
, 0, 0 },
103 { ngx_string("Content-Type"),
104 ngx_http_upstream_process_header_line
,
105 offsetof(ngx_http_upstream_headers_in_t
, content_type
),
106 ngx_http_upstream_copy_content_type
, 0, 1 },
108 { ngx_string("Content-Length"),
109 ngx_http_upstream_process_header_line
,
110 offsetof(ngx_http_upstream_headers_in_t
, content_length
),
111 ngx_http_upstream_copy_content_length
, 0, 0 },
113 { ngx_string("Date"),
114 ngx_http_upstream_process_header_line
,
115 offsetof(ngx_http_upstream_headers_in_t
, date
),
116 ngx_http_upstream_copy_header_line
,
117 offsetof(ngx_http_headers_out_t
, date
), 0 },
119 { ngx_string("Server"),
120 ngx_http_upstream_process_header_line
,
121 offsetof(ngx_http_upstream_headers_in_t
, server
),
122 ngx_http_upstream_copy_header_line
,
123 offsetof(ngx_http_headers_out_t
, server
), 0 },
125 { ngx_string("WWW-Authenticate"),
126 ngx_http_upstream_process_header_line
,
127 offsetof(ngx_http_upstream_headers_in_t
, www_authenticate
),
128 ngx_http_upstream_copy_header_line
, 0, 0 },
130 { ngx_string("Location"),
131 ngx_http_upstream_ignore_header_line
, 0,
132 ngx_http_upstream_rewrite_location
, 0, 0 },
134 { ngx_string("Refresh"),
135 ngx_http_upstream_ignore_header_line
, 0,
136 ngx_http_upstream_rewrite_refresh
, 0, 0 },
138 { ngx_string("Set-Cookie"),
139 ngx_http_upstream_ignore_header_line
, 0,
140 ngx_http_upstream_copy_header_line
, 0, 1 },
142 { ngx_string("Content-Disposition"),
143 ngx_http_upstream_ignore_header_line
, 0,
144 ngx_http_upstream_copy_header_line
, 0, 1 },
146 { ngx_string("Cache-Control"),
147 ngx_http_upstream_process_multi_header_lines
,
148 offsetof(ngx_http_upstream_headers_in_t
, cache_control
),
149 ngx_http_upstream_copy_multi_header_lines
,
150 offsetof(ngx_http_headers_out_t
, cache_control
), 1 },
152 { ngx_string("Expires"),
153 ngx_http_upstream_process_header_line
,
154 offsetof(ngx_http_upstream_headers_in_t
, expires
),
155 ngx_http_upstream_copy_header_line
,
156 offsetof(ngx_http_headers_out_t
, expires
), 1 },
158 { ngx_string("Accept-Ranges"),
159 ngx_http_upstream_process_header_line
,
160 offsetof(ngx_http_upstream_headers_in_t
, accept_ranges
),
161 ngx_http_upstream_copy_header_line
,
162 offsetof(ngx_http_headers_out_t
, accept_ranges
), 1 },
164 { ngx_string("Connection"),
165 ngx_http_upstream_ignore_header_line
, 0,
166 ngx_http_upstream_ignore_header_line
, 0, 0 },
168 { ngx_string("Keep-Alive"),
169 ngx_http_upstream_ignore_header_line
, 0,
170 ngx_http_upstream_ignore_header_line
, 0, 0 },
172 { ngx_string("X-Powered-By"),
173 ngx_http_upstream_ignore_header_line
, 0,
174 ngx_http_upstream_copy_header_line
, 0, 0 },
176 { ngx_string("X-Accel-Expires"),
177 ngx_http_upstream_process_header_line
,
178 offsetof(ngx_http_upstream_headers_in_t
, x_accel_expires
),
179 ngx_http_upstream_copy_header_line
, 0, 0 },
181 { ngx_string("X-Accel-Redirect"),
182 ngx_http_upstream_process_header_line
,
183 offsetof(ngx_http_upstream_headers_in_t
, x_accel_redirect
),
184 ngx_http_upstream_ignore_header_line
, 0, 0 },
186 { ngx_string("X-Accel-Limit-Rate"),
187 ngx_http_upstream_process_limit_rate
, 0,
188 ngx_http_upstream_ignore_header_line
, 0, 0 },
190 { ngx_string("X-Accel-Buffering"),
191 ngx_http_upstream_process_buffering
, 0,
192 ngx_http_upstream_ignore_header_line
, 0, 0 },
194 { ngx_string("X-Accel-Charset"),
195 ngx_http_upstream_process_charset
, 0,
196 ngx_http_upstream_ignore_header_line
, 0, 0 },
199 { ngx_string("Content-Encoding"),
200 ngx_http_upstream_process_header_line
,
201 offsetof(ngx_http_upstream_headers_in_t
, content_encoding
),
202 ngx_http_upstream_copy_content_encoding
, 0, 0 },
205 { ngx_null_string
, NULL
, 0, NULL
, 0, 0 }
209 static ngx_command_t ngx_http_upstream_commands
[] = {
211 { ngx_string("upstream"),
212 NGX_HTTP_MAIN_CONF
|NGX_CONF_BLOCK
|NGX_CONF_TAKE1
,
218 { ngx_string("server"),
219 NGX_HTTP_UPS_CONF
|NGX_CONF_1MORE
,
220 ngx_http_upstream_server
,
221 NGX_HTTP_SRV_CONF_OFFSET
,
229 static ngx_http_module_t ngx_http_upstream_module_ctx
= {
230 ngx_http_upstream_add_variables
, /* preconfiguration */
231 NULL
, /* postconfiguration */
233 ngx_http_upstream_create_main_conf
, /* create main configuration */
234 ngx_http_upstream_init_main_conf
, /* init main configuration */
236 NULL
, /* create server configuration */
237 NULL
, /* merge server configuration */
239 NULL
, /* create location configuration */
240 NULL
/* merge location configuration */
244 ngx_module_t ngx_http_upstream_module
= {
246 &ngx_http_upstream_module_ctx
, /* module context */
247 ngx_http_upstream_commands
, /* module directives */
248 NGX_HTTP_MODULE
, /* module type */
249 NULL
, /* init master */
250 NULL
, /* init module */
251 NULL
, /* init process */
252 NULL
, /* init thread */
253 NULL
, /* exit thread */
254 NULL
, /* exit process */
255 NULL
, /* exit master */
256 NGX_MODULE_V1_PADDING
260 static ngx_http_variable_t ngx_http_upstream_vars
[] = {
262 { ngx_string("upstream_addr"), NULL
,
263 ngx_http_upstream_addr_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
265 { ngx_string("upstream_status"), NULL
,
266 ngx_http_upstream_status_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
268 { ngx_string("upstream_response_time"), NULL
,
269 ngx_http_upstream_response_time_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
271 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
276 ngx_http_upstream_init(ngx_http_request_t
*r
)
279 ngx_http_cleanup_t
*cln
;
280 ngx_http_upstream_t
*u
;
281 ngx_http_core_loc_conf_t
*clcf
;
285 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
286 "http init upstream, client timer: %d", c
->read
->timer_set
);
288 if (c
->read
->timer_set
) {
289 ngx_del_timer(c
->read
);
294 if (!r
->post_action
&& !u
->conf
->ignore_client_abort
) {
295 r
->read_event_handler
= ngx_http_upstream_rd_check_broken_connection
;
296 r
->write_event_handler
= ngx_http_upstream_wr_check_broken_connection
;
299 if (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) {
301 if (!c
->write
->active
) {
302 if (ngx_add_event(c
->write
, NGX_WRITE_EVENT
, NGX_CLEAR_EVENT
)
305 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
311 if (r
->request_body
) {
312 u
->request_bufs
= r
->request_body
->bufs
;
315 if (u
->conf
->upstream
->peer
.init(r
, u
->conf
->upstream
) != NGX_OK
) {
316 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
320 if (u
->create_request(r
) != NGX_OK
) {
321 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
325 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
327 u
->output
.sendfile
= r
->connection
->sendfile
;
328 u
->output
.pool
= r
->pool
;
329 u
->output
.bufs
.num
= 1;
330 u
->output
.bufs
.size
= clcf
->client_body_buffer_size
;
331 u
->output
.output_filter
= ngx_chain_writer
;
332 u
->output
.filter_ctx
= &u
->writer
;
334 u
->writer
.pool
= r
->pool
;
336 if (r
->upstream_states
== NULL
) {
338 r
->upstream_states
= ngx_array_create(r
->pool
, 1,
339 sizeof(ngx_http_upstream_state_t
));
340 if (r
->upstream_states
== NULL
) {
341 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
347 u
->state
= ngx_array_push(r
->upstream_states
);
348 if (u
->state
== NULL
) {
349 ngx_http_upstream_finalize_request(r
, u
,
350 NGX_HTTP_INTERNAL_SERVER_ERROR
);
354 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
357 cln
= ngx_http_cleanup_add(r
, 0);
359 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
363 cln
->handler
= ngx_http_upstream_cleanup
;
365 u
->cleanup
= &cln
->handler
;
367 ngx_http_upstream_connect(r
, u
);
372 ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
)
374 ngx_http_upstream_check_broken_connection(r
, r
->connection
->read
);
379 ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
)
381 ngx_http_upstream_check_broken_connection(r
, r
->connection
->write
);
386 ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
393 ngx_http_upstream_t
*u
;
395 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, ev
->log
, 0,
396 "http upstream check client, write event:%d, \"%V\"",
403 ngx_http_upstream_finalize_request(r
, u
,
404 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
408 if (u
->peer
.connection
== NULL
) {
412 #if (NGX_HAVE_KQUEUE)
414 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
416 if (!ev
->pending_eof
) {
427 if (!u
->cachable
&& u
->peer
.connection
) {
428 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
429 "kevent() reported that client closed prematurely "
430 "connection, so upstream connection is closed too");
431 ngx_http_upstream_finalize_request(r
, u
,
432 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
436 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
437 "kevent() reported that client closed "
438 "prematurely connection");
440 if (u
->peer
.connection
== NULL
) {
441 ngx_http_upstream_finalize_request(r
, u
,
442 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
451 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
453 err
= ngx_socket_errno
;
455 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, ev
->log
, err
,
456 "http upstream recv(): %d", n
);
459 * we do not need to disable the write event because
460 * that event has NGX_USE_CLEAR_EVENT type
463 if (ev
->write
&& (n
>= 0 || err
== NGX_EAGAIN
)) {
467 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && ev
->active
) {
468 if (ngx_del_event(ev
, NGX_READ_EVENT
, 0) == NGX_ERROR
) {
469 ngx_http_upstream_finalize_request(r
, u
,
470 NGX_HTTP_INTERNAL_SERVER_ERROR
);
480 if (err
== NGX_EAGAIN
) {
486 } else { /* n == 0 */
493 if (!u
->cachable
&& u
->peer
.connection
) {
494 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
495 "client closed prematurely connection, "
496 "so upstream connection is closed too");
497 ngx_http_upstream_finalize_request(r
, u
,
498 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
502 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
503 "client closed prematurely connection");
505 if (u
->peer
.connection
== NULL
) {
506 ngx_http_upstream_finalize_request(r
, u
,
507 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
514 ngx_http_upstream_connect(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
520 r
->connection
->log
->action
= "connecting to upstream";
522 r
->connection
->single_connection
= 0;
524 if (u
->state
&& u
->state
->response_sec
) {
525 tp
= ngx_timeofday();
526 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
527 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
530 u
->state
= ngx_array_push(r
->upstream_states
);
531 if (u
->state
== NULL
) {
532 ngx_http_upstream_finalize_request(r
, u
,
533 NGX_HTTP_INTERNAL_SERVER_ERROR
);
537 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
539 tp
= ngx_timeofday();
540 u
->state
->response_sec
= tp
->sec
;
541 u
->state
->response_msec
= tp
->msec
;
543 rc
= ngx_event_connect_peer(&u
->peer
);
545 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
546 "http upstream connect: %i", rc
);
548 if (rc
== NGX_ERROR
) {
549 ngx_http_upstream_finalize_request(r
, u
,
550 NGX_HTTP_INTERNAL_SERVER_ERROR
);
554 u
->state
->peer
= u
->peer
.name
;
556 if (rc
== NGX_BUSY
) {
557 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0, "no live upstreams");
560 if (rc
== NGX_BUSY
|| rc
== NGX_DECLINED
) {
561 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
565 /* rc == NGX_OK || rc == NGX_AGAIN */
567 c
= u
->peer
.connection
;
571 c
->write
->handler
= ngx_http_upstream_send_request_handler
;
572 c
->read
->handler
= ngx_http_upstream_process_header
;
574 c
->sendfile
= r
->connection
->sendfile
;
577 c
->read
->log
= c
->write
->log
= c
->log
= r
->connection
->log
;
579 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
581 u
->writer
.out
= NULL
;
582 u
->writer
.last
= &u
->writer
.out
;
583 u
->writer
.connection
= c
;
586 if (u
->request_sent
) {
587 if (ngx_http_upstream_reinit(r
, u
) != NGX_OK
) {
588 ngx_http_upstream_finalize_request(r
, u
,
589 NGX_HTTP_INTERNAL_SERVER_ERROR
);
595 && r
->request_body
->buf
596 && r
->request_body
->temp_file
600 * the r->request_body->buf can be reused for one request only,
601 * the subrequests should allocate their own temporay bufs
604 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
605 if (u
->output
.free
== NULL
) {
606 ngx_http_upstream_finalize_request(r
, u
,
607 NGX_HTTP_INTERNAL_SERVER_ERROR
);
611 u
->output
.free
->buf
= r
->request_body
->buf
;
612 u
->output
.free
->next
= NULL
;
613 u
->output
.allocated
= 1;
615 r
->request_body
->buf
->pos
= r
->request_body
->buf
->start
;
616 r
->request_body
->buf
->last
= r
->request_body
->buf
->start
;
617 r
->request_body
->buf
->tag
= u
->output
.tag
;
622 if (rc
== NGX_AGAIN
) {
623 ngx_add_timer(c
->write
, u
->conf
->connect_timeout
);
629 if (u
->conf
->ssl
&& c
->ssl
== NULL
) {
630 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
636 ngx_http_upstream_send_request(r
, u
);
643 ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*r
,
644 ngx_http_upstream_t
*u
, ngx_connection_t
*c
)
648 if (ngx_ssl_create_connection(u
->conf
->ssl
, c
,
649 NGX_SSL_BUFFER
|NGX_SSL_CLIENT
)
652 ngx_http_upstream_finalize_request(r
, u
,
653 NGX_HTTP_INTERNAL_SERVER_ERROR
);
658 u
->output
.sendfile
= 0;
660 if (u
->peer
.set_session(&u
->peer
, u
->peer
.data
) != NGX_OK
) {
661 ngx_http_upstream_finalize_request(r
, u
,
662 NGX_HTTP_INTERNAL_SERVER_ERROR
);
666 r
->connection
->log
->action
= "SSL handshaking to upstream";
668 rc
= ngx_ssl_handshake(c
);
670 if (rc
== NGX_AGAIN
) {
671 c
->ssl
->handler
= ngx_http_upstream_ssl_handshake
;
675 ngx_http_upstream_ssl_handshake(c
);
680 ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
)
682 ngx_http_request_t
*r
;
683 ngx_http_upstream_t
*u
;
688 if (c
->ssl
->handshaked
) {
690 u
->peer
.save_session(&u
->peer
, u
->peer
.data
);
692 c
->write
->handler
= ngx_http_upstream_send_request_handler
;
693 c
->read
->handler
= ngx_http_upstream_process_header
;
695 ngx_http_upstream_send_request(r
, u
);
700 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
708 ngx_http_upstream_reinit(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
712 if (u
->reinit_request(r
) != NGX_OK
) {
716 ngx_memzero(&r
->upstream
->headers_in
,
717 sizeof(ngx_http_upstream_headers_in_t
));
719 if (ngx_list_init(&r
->upstream
->headers_in
.headers
, r
->pool
, 8,
720 sizeof(ngx_table_elt_t
))
726 /* reinit the request chain */
728 for (cl
= u
->request_bufs
; cl
; cl
= cl
->next
) {
729 cl
->buf
->pos
= cl
->buf
->start
;
730 cl
->buf
->file_pos
= 0;
733 /* reinit the subrequest's ngx_output_chain() context */
735 if (r
->request_body
&& r
->request_body
->temp_file
736 && r
!= r
->main
&& u
->output
.buf
)
738 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
739 if (u
->output
.free
== NULL
) {
743 u
->output
.free
->buf
= u
->output
.buf
;
744 u
->output
.free
->next
= NULL
;
746 u
->output
.buf
->pos
= u
->output
.buf
->start
;
747 u
->output
.buf
->last
= u
->output
.buf
->start
;
750 u
->output
.buf
= NULL
;
752 u
->output
.busy
= NULL
;
754 /* reinit u->buffer */
758 u
->buffer
.pos
= u
->buffer
.start
+ u
->cache
->ctx
.header_size
;
759 u
->buffer
.last
= u
->buffer
.pos
;
762 u
->buffer
.pos
= u
->buffer
.start
;
763 u
->buffer
.last
= u
->buffer
.start
;
767 u
->buffer
.pos
= u
->buffer
.start
;
768 u
->buffer
.last
= u
->buffer
.start
;
777 ngx_http_upstream_send_request(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
782 c
= u
->peer
.connection
;
784 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
785 "http upstream send request");
787 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
788 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
792 c
->log
->action
= "sending request to upstream";
794 rc
= ngx_output_chain(&u
->output
, u
->request_sent
? NULL
: u
->request_bufs
);
798 if (rc
== NGX_ERROR
) {
799 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
803 if (c
->write
->timer_set
) {
804 ngx_del_timer(c
->write
);
807 if (rc
== NGX_AGAIN
) {
808 ngx_add_timer(c
->write
, u
->conf
->send_timeout
);
810 if (ngx_handle_write_event(c
->write
, u
->conf
->send_lowat
) == NGX_ERROR
)
812 ngx_http_upstream_finalize_request(r
, u
,
813 NGX_HTTP_INTERNAL_SERVER_ERROR
);
822 if (c
->tcp_nopush
== NGX_TCP_NOPUSH_SET
) {
823 if (ngx_tcp_push(c
->fd
) == NGX_ERROR
) {
824 ngx_log_error(NGX_LOG_CRIT
, c
->log
, ngx_socket_errno
,
825 ngx_tcp_push_n
" failed");
826 ngx_http_upstream_finalize_request(r
, u
,
827 NGX_HTTP_INTERNAL_SERVER_ERROR
);
831 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
834 ngx_add_timer(c
->read
, u
->conf
->read_timeout
);
837 if (c
->read
->ready
) {
839 /* post aio operation */
843 * although we can post aio operation just in the end
844 * of ngx_http_upstream_connect() CHECK IT !!!
845 * it's better to do here because we postpone header buffer allocation
848 ngx_http_upstream_process_header(c
->read
);
853 c
->write
->handler
= ngx_http_upstream_dummy_handler
;
855 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
856 ngx_http_upstream_finalize_request(r
, u
,
857 NGX_HTTP_INTERNAL_SERVER_ERROR
);
864 ngx_http_upstream_send_request_handler(ngx_event_t
*wev
)
867 ngx_http_request_t
*r
;
868 ngx_http_upstream_t
*u
;
874 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
875 "http upstream send request handler");
878 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
884 if (u
->conf
->ssl
&& c
->ssl
== NULL
) {
885 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
891 if (u
->header_sent
) {
892 wev
->handler
= ngx_http_upstream_dummy_handler
;
894 (void) ngx_handle_write_event(wev
, 0);
899 ngx_http_upstream_send_request(r
, u
);
904 ngx_http_upstream_process_header(ngx_event_t
*rev
)
908 ngx_str_t
*uri
, args
;
910 ngx_list_part_t
*part
;
913 ngx_http_request_t
*r
;
914 ngx_http_upstream_t
*u
;
915 ngx_http_err_page_t
*err_page
;
916 ngx_http_core_loc_conf_t
*clcf
;
917 ngx_http_upstream_header_t
*hh
;
918 ngx_http_upstream_main_conf_t
*umcf
;
924 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
925 "http upstream process header");
927 c
->log
->action
= "reading response header from upstream";
930 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
934 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
935 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
939 if (u
->buffer
.start
== NULL
) {
940 u
->buffer
.start
= ngx_palloc(r
->pool
, u
->conf
->buffer_size
);
941 if (u
->buffer
.start
== NULL
) {
942 ngx_http_upstream_finalize_request(r
, u
,
943 NGX_HTTP_INTERNAL_SERVER_ERROR
);
947 u
->buffer
.pos
= u
->buffer
.start
;
948 u
->buffer
.last
= u
->buffer
.start
;
949 u
->buffer
.end
= u
->buffer
.start
+ u
->conf
->buffer_size
;
950 u
->buffer
.temporary
= 1;
952 u
->buffer
.tag
= u
->output
.tag
;
954 if (ngx_list_init(&r
->upstream
->headers_in
.headers
, r
->pool
, 8,
955 sizeof(ngx_table_elt_t
))
958 ngx_http_upstream_finalize_request(r
, u
,
959 NGX_HTTP_INTERNAL_SERVER_ERROR
);
965 u
->buffer
.pos
+= u
->cache
->ctx
.header_size
;
966 u
->buffer
.last
= u
->buffer
.pos
;
971 n
= u
->peer
.connection
->recv(u
->peer
.connection
, u
->buffer
.last
,
972 u
->buffer
.end
- u
->buffer
.last
);
974 if (n
== NGX_AGAIN
) {
976 ngx_add_timer(rev
, u
->read_timeout
);
979 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
980 ngx_http_upstream_finalize_request(r
, u
,
981 NGX_HTTP_INTERNAL_SERVER_ERROR
);
989 ngx_log_error(NGX_LOG_ERR
, rev
->log
, 0,
990 "upstream prematurely closed connection");
993 if (n
== NGX_ERROR
|| n
== 0) {
994 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1001 u
->valid_header_in
= 0;
1006 rc
= u
->process_header(r
);
1008 if (rc
== NGX_AGAIN
) {
1010 ngx_add_timer(rev
, u
->read_timeout
);
1013 if (u
->buffer
.pos
== u
->buffer
.end
) {
1014 ngx_log_error(NGX_LOG_ERR
, rev
->log
, 0,
1015 "upstream sent too big header");
1017 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1021 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1022 ngx_http_upstream_finalize_request(r
, u
,
1023 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1030 if (rc
== NGX_HTTP_UPSTREAM_INVALID_HEADER
) {
1031 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1035 if (rc
== NGX_ERROR
|| rc
== NGX_HTTP_INTERNAL_SERVER_ERROR
) {
1036 ngx_http_upstream_finalize_request(r
, u
,
1037 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1043 if (u
->headers_in
.status_n
>= NGX_HTTP_BAD_REQUEST
1044 && r
->subrequest_in_memory
)
1046 u
->buffer
.last
= u
->buffer
.pos
;
1049 if (u
->headers_in
.status_n
== NGX_HTTP_INTERNAL_SERVER_ERROR
) {
1051 if (u
->peer
.tries
> 1
1052 && (u
->conf
->next_upstream
& NGX_HTTP_UPSTREAM_FT_HTTP_500
))
1054 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_HTTP_500
);
1058 #if (NGX_HTTP_CACHE)
1060 if (u
->peer
.tries
== 0
1062 && (u
->conf
->use_stale
& NGX_HTTP_UPSTREAM_FT_HTTP_500
))
1064 ngx_http_upstream_finalize_request(r
, u
,
1065 ngx_http_send_cached_response(r
));
1072 if (u
->headers_in
.status_n
== NGX_HTTP_NOT_FOUND
) {
1074 if (u
->peer
.tries
> 1
1075 && u
->conf
->next_upstream
& NGX_HTTP_UPSTREAM_FT_HTTP_404
)
1077 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_HTTP_404
);
1081 if (u
->conf
->intercept_404
) {
1082 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_NOT_FOUND
);
1088 if (u
->headers_in
.status_n
>= NGX_HTTP_BAD_REQUEST
1089 && u
->conf
->intercept_errors
)
1091 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1093 if (clcf
->error_pages
) {
1095 err_page
= clcf
->error_pages
->elts
;
1096 for (i
= 0; i
< clcf
->error_pages
->nelts
; i
++) {
1097 if (err_page
[i
].status
== (ngx_int_t
) u
->headers_in
.status_n
) {
1099 if (u
->headers_in
.status_n
== NGX_HTTP_UNAUTHORIZED
) {
1101 r
->headers_out
.www_authenticate
=
1102 ngx_list_push(&r
->headers_out
.headers
);
1104 if (r
->headers_out
.www_authenticate
== NULL
) {
1105 ngx_http_upstream_finalize_request(r
, u
,
1106 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1110 *r
->headers_out
.www_authenticate
=
1111 *u
->headers_in
.www_authenticate
;
1114 ngx_http_upstream_finalize_request(r
, u
,
1115 u
->headers_in
.status_n
);
1122 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
1124 if (r
->upstream
->headers_in
.x_accel_redirect
) {
1126 ngx_http_upstream_finalize_request(r
, u
, NGX_DECLINED
);
1128 part
= &r
->upstream
->headers_in
.headers
.part
;
1131 for (i
= 0; /* void */; i
++) {
1133 if (i
>= part
->nelts
) {
1134 if (part
->next
== NULL
) {
1143 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1144 h
[i
].lowcase_key
, h
[i
].key
.len
);
1146 if (hh
&& hh
->redirect
) {
1147 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1148 ngx_http_finalize_request(r
,
1149 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1155 uri
= &r
->upstream
->headers_in
.x_accel_redirect
->value
;
1160 if (ngx_http_parse_unsafe_uri(r
, uri
, &args
, &flags
) != NGX_OK
) {
1161 ngx_http_finalize_request(r
, NGX_HTTP_NOT_FOUND
);
1165 if (flags
& NGX_HTTP_ZERO_IN_URI
) {
1169 if (r
->method
!= NGX_HTTP_HEAD
) {
1170 r
->method
= NGX_HTTP_GET
;
1173 ngx_http_internal_redirect(r
, uri
, &args
);
1177 part
= &r
->upstream
->headers_in
.headers
.part
;
1180 for (i
= 0; /* void */; i
++) {
1182 if (i
>= part
->nelts
) {
1183 if (part
->next
== NULL
) {
1192 if (ngx_hash_find(&u
->conf
->hide_headers_hash
, h
[i
].hash
,
1193 h
[i
].lowcase_key
, h
[i
].key
.len
))
1198 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1199 h
[i
].lowcase_key
, h
[i
].key
.len
);
1202 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1203 ngx_http_upstream_finalize_request(r
, u
,
1204 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1211 if (ngx_http_upstream_copy_header_line(r
, &h
[i
], 0) != NGX_OK
) {
1212 ngx_http_upstream_finalize_request(r
, u
,
1213 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1218 if (r
->headers_out
.server
&& r
->headers_out
.server
->value
.data
== NULL
) {
1219 r
->headers_out
.server
->hash
= 0;
1222 if (r
->headers_out
.date
&& r
->headers_out
.date
->value
.data
== NULL
) {
1223 r
->headers_out
.date
->hash
= 0;
1226 r
->headers_out
.status
= u
->headers_in
.status_n
;
1227 r
->headers_out
.status_line
= u
->headers_in
.status_line
;
1229 if (r
->headers_out
.content_length_n
!= -1) {
1230 u
->length
= (size_t) r
->headers_out
.content_length_n
;
1233 u
->length
= NGX_MAX_SIZE_T_VALUE
;
1236 if (!r
->subrequest_in_memory
) {
1237 ngx_http_upstream_send_response(r
, u
);
1241 /* subrequest content in memory */
1243 if (u
->input_filter
== NULL
) {
1244 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
1245 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
1246 u
->input_filter_ctx
= r
;
1249 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
1250 ngx_http_upstream_finalize_request(r
, u
,
1251 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1255 if (u
->buffer
.last
- u
->buffer
.pos
>= (ssize_t
) u
->length
) {
1256 if (u
->input_filter(u
->input_filter_ctx
, 0) == NGX_ERROR
) {
1257 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1261 ngx_http_upstream_finalize_request(r
, u
, 0);
1265 rev
->handler
= ngx_http_upstream_process_body_in_memory
;
1267 ngx_http_upstream_process_body_in_memory(rev
);
1272 ngx_http_upstream_test_connect(ngx_connection_t
*c
)
1277 #if (NGX_HAVE_KQUEUE)
1279 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1280 if (c
->write
->pending_eof
) {
1281 (void) ngx_connection_error(c
, c
->write
->kq_errno
,
1282 "kevent() reported that connect() failed");
1293 * BSDs and Linux return 0 and set a pending error in err
1294 * Solaris returns -1 and sets errno
1297 if (getsockopt(c
->fd
, SOL_SOCKET
, SO_ERROR
, (void *) &err
, &len
)
1304 (void) ngx_connection_error(c
, err
, "connect() failed");
1314 ngx_http_upstream_process_body_in_memory(ngx_event_t
*rev
)
1319 ngx_connection_t
*c
;
1320 ngx_http_request_t
*r
;
1321 ngx_http_upstream_t
*u
;
1327 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1328 "http upstream process body on memory");
1330 if (rev
->timedout
) {
1331 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
1332 ngx_http_upstream_finalize_request(r
, u
, NGX_ETIMEDOUT
);
1340 size
= b
->end
- b
->last
;
1343 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
1344 "upstream buffer is too small to read repsonse");
1345 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1349 n
= c
->recv(c
, b
->last
, size
);
1351 if (n
== NGX_AGAIN
) {
1355 if (n
== 0 || n
== NGX_ERROR
) {
1356 ngx_http_upstream_finalize_request(r
, u
, n
);
1360 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
1361 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1370 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1371 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1376 ngx_add_timer(rev
, u
->conf
->read_timeout
);
1378 } else if (rev
->timer_set
) {
1385 ngx_http_upstream_send_response(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1390 ngx_event_pipe_t
*p
;
1391 ngx_connection_t
*c
;
1392 ngx_pool_cleanup_t
*cl
;
1393 ngx_pool_cleanup_file_t
*clf
;
1394 ngx_http_core_loc_conf_t
*clcf
;
1396 rc
= ngx_http_send_header(r
);
1398 if (rc
== NGX_ERROR
|| rc
> NGX_OK
|| r
->post_action
|| r
->header_only
) {
1399 ngx_http_upstream_finalize_request(r
, u
, rc
);
1405 if (r
->request_body
&& r
->request_body
->temp_file
) {
1406 for (cl
= r
->pool
->cleanup
; cl
; cl
= cl
->next
) {
1407 if (cl
->handler
== ngx_pool_cleanup_file
) {
1410 if (clf
->fd
== r
->request_body
->temp_file
->file
.fd
) {
1413 r
->request_body
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
1422 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1424 if (!u
->buffering
) {
1426 if (u
->input_filter
== NULL
) {
1427 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
1428 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
1429 u
->input_filter_ctx
= r
;
1432 u
->peer
.connection
->read
->handler
=
1433 ngx_http_upstream_process_non_buffered_body
;
1434 r
->write_event_handler
=
1435 ngx_http_upstream_process_non_buffered_downstream
;
1439 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
1440 ngx_http_upstream_finalize_request(r
, u
, 0);
1444 if (clcf
->tcp_nodelay
&& c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
) {
1445 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
1449 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
1450 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
1452 ngx_connection_error(c
, ngx_socket_errno
,
1453 "setsockopt(TCP_NODELAY) failed");
1454 ngx_http_upstream_finalize_request(r
, u
, 0);
1458 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
1461 size
= u
->buffer
.last
- u
->buffer
.pos
;
1464 u
->buffer
.last
= u
->buffer
.pos
;
1466 if (u
->input_filter(u
->input_filter_ctx
, size
) == NGX_ERROR
) {
1467 ngx_http_upstream_finalize_request(r
, u
, 0);
1471 ngx_http_upstream_process_non_buffered_body(c
->write
);
1474 u
->buffer
.pos
= u
->buffer
.start
;
1475 u
->buffer
.last
= u
->buffer
.start
;
1477 if (ngx_http_send_special(r
, NGX_HTTP_FLUSH
) == NGX_ERROR
) {
1478 ngx_http_upstream_finalize_request(r
, u
, 0);
1486 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
1490 if (u
->cache
&& u
->cache
->ctx
.file
.fd
!= NGX_INVALID_FILE
) {
1491 if (ngx_close_file(u
->cache
->ctx
.file
.fd
) == NGX_FILE_ERROR
) {
1492 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
1493 ngx_close_file_n
" \"%s\" failed",
1494 u
->cache
->ctx
.file
.name
.data
);
1499 header
= (ngx_http_cache_header_t
*) u
->buffer
->start
;
1501 header
->expires
= u
->cache
->ctx
.expires
;
1502 header
->last_modified
= u
->cache
->ctx
.last_modified
;
1503 header
->date
= u
->cache
->ctx
.date
;
1504 header
->length
= r
->headers_out
.content_length_n
;
1505 u
->cache
->ctx
.length
= r
->headers_out
.content_length_n
;
1507 header
->key_len
= u
->cache
->ctx
.key0
.len
;
1508 ngx_memcpy(&header
->key
, u
->cache
->ctx
.key0
.data
, header
->key_len
);
1509 header
->key
[header
->key_len
] = LF
;
1516 p
->output_filter
= (ngx_event_pipe_output_filter_pt
) ngx_http_output_filter
;
1518 p
->tag
= u
->output
.tag
;
1519 p
->bufs
= u
->conf
->bufs
;
1520 p
->busy_size
= u
->conf
->busy_buffers_size
;
1521 p
->upstream
= u
->peer
.connection
;
1526 p
->cachable
= u
->cachable
;
1528 p
->temp_file
= ngx_pcalloc(r
->pool
, sizeof(ngx_temp_file_t
));
1529 if (p
->temp_file
== NULL
) {
1530 ngx_http_upstream_finalize_request(r
, u
, 0);
1534 p
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
1535 p
->temp_file
->file
.log
= c
->log
;
1536 p
->temp_file
->path
= u
->conf
->temp_path
;
1537 p
->temp_file
->pool
= r
->pool
;
1540 p
->temp_file
->persistent
= 1;
1542 p
->temp_file
->log_level
= NGX_LOG_WARN
;
1543 p
->temp_file
->warn
= "an upstream response is buffered "
1544 "to a temporary file";
1547 p
->max_temp_file_size
= u
->conf
->max_temp_file_size
;
1548 p
->temp_file_write_size
= u
->conf
->temp_file_write_size
;
1550 p
->preread_bufs
= ngx_alloc_chain_link(r
->pool
);
1551 if (p
->preread_bufs
== NULL
) {
1552 ngx_http_upstream_finalize_request(r
, u
, 0);
1555 p
->preread_bufs
->buf
= &u
->buffer
;
1556 p
->preread_bufs
->next
= NULL
;
1557 u
->buffer
.recycled
= 1;
1559 p
->preread_size
= u
->buffer
.last
- u
->buffer
.pos
;
1562 p
->buf_to_file
= ngx_calloc_buf(r
->pool
);
1563 if (p
->buf_to_file
== NULL
) {
1564 ngx_http_upstream_finalize_request(r
, u
, 0);
1567 p
->buf_to_file
->pos
= u
->buffer
.start
;
1568 p
->buf_to_file
->last
= u
->buffer
.pos
;
1569 p
->buf_to_file
->temporary
= 1;
1572 if (ngx_event_flags
& NGX_USE_AIO_EVENT
) {
1573 /* the posted aio operation may currupt a shadow buffer */
1577 /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
1581 * event_pipe would do u->buffer.last += p->preread_size
1582 * as though these bytes were read
1584 u
->buffer
.last
= u
->buffer
.pos
;
1586 if (u
->conf
->cyclic_temp_file
) {
1589 * we need to disable the use of sendfile() if we use cyclic temp file
1590 * because the writing a new data may interfere with sendfile()
1591 * that uses the same kernel file pages (at least on FreeBSD)
1594 p
->cyclic_temp_file
= 1;
1598 p
->cyclic_temp_file
= 0;
1601 p
->read_timeout
= u
->conf
->read_timeout
;
1602 p
->send_timeout
= clcf
->send_timeout
;
1603 p
->send_lowat
= clcf
->send_lowat
;
1605 u
->peer
.connection
->read
->handler
= ngx_http_upstream_process_body
;
1606 r
->write_event_handler
= ngx_http_upstream_process_downstream
;
1608 ngx_http_upstream_process_body(u
->peer
.connection
->read
);
1613 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
)
1615 ngx_http_upstream_process_non_buffered_body(r
->connection
->write
);
1620 ngx_http_upstream_process_non_buffered_body(ngx_event_t
*ev
)
1626 ngx_uint_t do_write
;
1627 ngx_connection_t
*c
, *downstream
, *upstream
;
1628 ngx_http_request_t
*r
;
1629 ngx_http_upstream_t
*u
;
1630 ngx_http_core_loc_conf_t
*clcf
;
1637 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1638 "http upstream process non buffered downstream");
1639 c
->log
->action
= "sending to client";
1642 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1643 "http upstream process non buffered upstream");
1644 c
->log
->action
= "reading upstream";
1650 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
1653 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
1656 ngx_http_upstream_finalize_request(r
, u
, 0);
1660 downstream
= r
->connection
;
1661 upstream
= u
->peer
.connection
;
1665 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1667 do_write
= ev
->write
|| u
->length
== 0;
1673 if (u
->out_bufs
|| u
->busy_bufs
) {
1674 rc
= ngx_http_output_filter(r
, u
->out_bufs
);
1676 if (downstream
->destroyed
) {
1680 if (rc
== NGX_ERROR
) {
1681 ngx_http_upstream_finalize_request(r
, u
, 0);
1685 ngx_chain_update_chains(&u
->free_bufs
, &u
->busy_bufs
,
1686 &u
->out_bufs
, u
->output
.tag
);
1689 if (u
->busy_bufs
== NULL
) {
1692 || upstream
->read
->eof
1693 || upstream
->read
->error
)
1695 ngx_http_upstream_finalize_request(r
, u
, 0);
1704 size
= b
->end
- b
->last
;
1706 if (size
> u
->length
) {
1710 if (size
&& upstream
->read
->ready
) {
1712 n
= upstream
->recv(upstream
, b
->last
, size
);
1714 if (n
== NGX_AGAIN
) {
1719 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
1720 ngx_http_upstream_finalize_request(r
, u
, 0);
1733 if (downstream
->data
== r
) {
1734 if (ngx_handle_write_event(downstream
->write
, clcf
->send_lowat
)
1737 ngx_http_upstream_finalize_request(r
, u
, 0);
1742 if (downstream
->write
->active
&& !downstream
->write
->ready
) {
1743 ngx_add_timer(downstream
->write
, clcf
->send_timeout
);
1745 } else if (downstream
->write
->timer_set
) {
1746 ngx_del_timer(downstream
->write
);
1749 if (ngx_handle_read_event(upstream
->read
, 0) == NGX_ERROR
) {
1750 ngx_http_upstream_finalize_request(r
, u
, 0);
1754 if (upstream
->read
->active
&& !upstream
->read
->ready
) {
1755 ngx_add_timer(upstream
->read
, u
->conf
->read_timeout
);
1757 } else if (upstream
->read
->timer_set
) {
1758 ngx_del_timer(upstream
->read
);
1764 ngx_http_upstream_non_buffered_filter_init(void *data
)
1771 ngx_http_upstream_non_buffered_filter(void *data
, ssize_t bytes
)
1773 ngx_http_request_t
*r
= data
;
1776 ngx_chain_t
*cl
, **ll
;
1777 ngx_http_upstream_t
*u
;
1781 for (cl
= u
->out_bufs
, ll
= &u
->out_bufs
; cl
; cl
= cl
->next
) {
1785 cl
= ngx_chain_get_free_buf(r
->pool
, &u
->free_bufs
);
1793 cl
->buf
->memory
= 1;
1797 cl
->buf
->pos
= b
->last
;
1799 cl
->buf
->last
= b
->last
;
1801 if (u
->length
== NGX_MAX_SIZE_T_VALUE
) {
1812 ngx_http_upstream_process_downstream(ngx_http_request_t
*r
)
1814 ngx_http_upstream_process_body(r
->connection
->write
);
1819 ngx_http_upstream_process_body(ngx_event_t
*ev
)
1821 ngx_event_pipe_t
*p
;
1822 ngx_connection_t
*c
, *downstream
;
1823 ngx_http_log_ctx_t
*ctx
;
1824 ngx_http_request_t
*r
;
1825 ngx_http_upstream_t
*u
;
1830 downstream
= r
->connection
;
1833 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1834 "http upstream process downstream");
1835 c
->log
->action
= "sending to client";
1838 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1839 "http upstream process upstream");
1840 c
->log
->action
= "reading upstream";
1843 ctx
->current_request
= r
;
1856 ngx_add_timer(ev
, p
->send_timeout
);
1858 if (ngx_handle_write_event(ev
, p
->send_lowat
) == NGX_ERROR
)
1860 ngx_http_upstream_finalize_request(r
, u
, 0);
1867 if (ngx_event_pipe(p
, ev
->write
) == NGX_ABORT
) {
1869 if (downstream
->destroyed
) {
1873 ngx_http_upstream_finalize_request(r
, u
, 0);
1878 p
->downstream_error
= 1;
1880 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
1884 p
->upstream_error
= 1;
1885 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
1889 if (ev
->write
&& ev
->delayed
) {
1890 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1891 "http downstream delayed");
1893 if (ngx_handle_write_event(ev
, p
->send_lowat
) == NGX_ERROR
) {
1900 if (ngx_event_pipe(p
, ev
->write
) == NGX_ABORT
) {
1902 if (downstream
->destroyed
) {
1906 ngx_http_upstream_finalize_request(r
, u
, 0);
1911 if (u
->peer
.connection
) {
1913 #if (NGX_HTTP_FILE_CACHE)
1915 if (p
->upstream_done
&& u
->cachable
) {
1916 if (ngx_http_cache_update(r
) == NGX_ERROR
) {
1917 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
1918 ngx_http_upstream_finalize_request(r
, u
, 0);
1922 } else if (p
->upstream_eof
&& u
->cachable
) {
1924 /* TODO: check length & update cache */
1926 if (ngx_http_cache_update(r
) == NGX_ERROR
) {
1927 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
1928 ngx_http_upstream_finalize_request(r
, u
, 0);
1935 if (p
->upstream_done
|| p
->upstream_eof
|| p
->upstream_error
) {
1936 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1937 "http upstream exit: %p", p
->out
);
1939 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
1941 ngx_http_upstream_finalize_request(r
, u
, 0);
1946 if (p
->downstream_error
) {
1947 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1948 "http upstream downstream error");
1950 if (!u
->cachable
&& u
->peer
.connection
) {
1951 ngx_http_upstream_finalize_request(r
, u
, 0);
1958 ngx_http_upstream_dummy_handler(ngx_event_t
*wev
)
1960 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1961 "http upstream dummy handler");
1966 ngx_http_upstream_next(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
,
1969 ngx_uint_t status
, state
;
1971 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1972 "http next upstream, %xi", ft_type
);
1975 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
1978 if (ft_type
== NGX_HTTP_UPSTREAM_FT_HTTP_404
) {
1979 state
= NGX_PEER_NEXT
;
1981 state
= NGX_PEER_FAILED
;
1984 u
->peer
.free(&u
->peer
, u
->peer
.data
, state
);
1986 if (ft_type
== NGX_HTTP_UPSTREAM_FT_TIMEOUT
) {
1987 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, NGX_ETIMEDOUT
,
1988 "upstream timed out");
1991 if (u
->peer
.cached
&& ft_type
== NGX_HTTP_UPSTREAM_FT_ERROR
) {
1997 case NGX_HTTP_UPSTREAM_FT_TIMEOUT
:
1998 status
= NGX_HTTP_GATEWAY_TIME_OUT
;
2001 case NGX_HTTP_UPSTREAM_FT_HTTP_500
:
2002 status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
2005 case NGX_HTTP_UPSTREAM_FT_HTTP_404
:
2006 status
= NGX_HTTP_NOT_FOUND
;
2010 * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
2015 status
= NGX_HTTP_BAD_GATEWAY
;
2019 if (r
->connection
->error
) {
2020 ngx_http_upstream_finalize_request(r
, u
,
2021 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
2026 u
->state
->status
= status
;
2028 if (u
->peer
.tries
== 0 || !(u
->conf
->next_upstream
& ft_type
)) {
2030 #if (NGX_HTTP_CACHE)
2032 if (u
->stale
&& (u
->conf
->use_stale
& ft_type
)) {
2033 ngx_http_upstream_finalize_request(r
, u
,
2034 ngx_http_send_cached_response(r
));
2040 ngx_http_upstream_finalize_request(r
, u
, status
);
2045 if (u
->peer
.connection
) {
2046 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2047 "close http upstream connection: %d",
2048 u
->peer
.connection
->fd
);
2051 if (u
->peer
.connection
->ssl
) {
2052 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
2053 u
->peer
.connection
->ssl
->no_send_shutdown
= 1;
2055 (void) ngx_ssl_shutdown(u
->peer
.connection
);
2059 ngx_close_connection(u
->peer
.connection
);
2063 if (u
->conf
->busy_lock
&& !u
->busy_locked
) {
2064 ngx_http_upstream_busy_lock(p
);
2069 ngx_http_upstream_connect(r
, u
);
2074 ngx_http_upstream_cleanup(void *data
)
2076 ngx_http_request_t
*r
= data
;
2078 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2079 "cleanup http upstream request: \"%V\"", &r
->uri
);
2081 ngx_http_upstream_finalize_request(r
, r
->upstream
, NGX_DONE
);
2086 ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
2087 ngx_http_upstream_t
*u
, ngx_int_t rc
)
2091 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2092 "finalize http upstream request: %i", rc
);
2096 if (u
->state
->response_sec
) {
2097 tp
= ngx_timeofday();
2098 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
2099 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
2102 u
->finalize_request(r
, rc
);
2104 u
->peer
.free(&u
->peer
, u
->peer
.data
, 0);
2106 if (u
->peer
.connection
) {
2110 /* TODO: do not shutdown persistent connection */
2112 if (u
->peer
.connection
->ssl
) {
2115 * We send the "close notify" shutdown alert to the upstream only
2116 * and do not wait its "close notify" shutdown alert.
2117 * It is acceptable according to the TLS standard.
2120 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
2122 (void) ngx_ssl_shutdown(u
->peer
.connection
);
2126 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2127 "close http upstream connection: %d",
2128 u
->peer
.connection
->fd
);
2130 ngx_close_connection(u
->peer
.connection
);
2133 u
->peer
.connection
= NULL
;
2135 if (u
->header_sent
&& (rc
== NGX_ERROR
|| rc
>= NGX_HTTP_SPECIAL_RESPONSE
))
2140 if (u
->pipe
&& u
->pipe
->temp_file
) {
2141 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2142 "http upstream temp fd: %d",
2143 u
->pipe
->temp_file
->file
.fd
);
2148 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2149 "http upstream cache fd: %d",
2150 u
->cache
->ctx
.file
.fd
);
2154 if (rc
== NGX_DECLINED
) {
2158 r
->connection
->log
->action
= "sending to client";
2162 if (!r
->post_action
) {
2163 rc
= ngx_http_send_special(r
, NGX_HTTP_LAST
);
2173 ngx_http_finalize_request(r
, rc
);
2178 ngx_http_upstream_process_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2181 ngx_table_elt_t
**ph
;
2183 ph
= (ngx_table_elt_t
**) ((char *) &r
->upstream
->headers_in
+ offset
);
2194 ngx_http_upstream_process_multi_header_lines(ngx_http_request_t
*r
,
2195 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2198 ngx_table_elt_t
**ph
;
2200 pa
= (ngx_array_t
*) ((char *) &r
->upstream
->headers_in
+ offset
);
2202 if (pa
->elts
== NULL
) {
2203 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
2209 ph
= ngx_array_push(pa
);
2221 ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2229 ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2234 r
->upstream
->headers_in
.x_accel_limit_rate
= h
;
2236 n
= ngx_atoi(h
->value
.data
, h
->value
.len
);
2238 if (n
!= NGX_ERROR
) {
2239 r
->limit_rate
= (size_t) n
;
2247 ngx_http_upstream_process_buffering(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2252 if (r
->upstream
->conf
->change_buffering
) {
2254 if (h
->value
.len
== 2) {
2255 c0
= ngx_tolower(h
->value
.data
[0]);
2256 c1
= ngx_tolower(h
->value
.data
[1]);
2258 if (c0
== 'n' && c1
== 'o') {
2259 r
->upstream
->buffering
= 0;
2262 } else if (h
->value
.len
== 3) {
2263 c0
= ngx_tolower(h
->value
.data
[0]);
2264 c1
= ngx_tolower(h
->value
.data
[1]);
2265 c2
= ngx_tolower(h
->value
.data
[2]);
2267 if (c0
== 'y' && c1
== 'e' && c2
== 's') {
2268 r
->upstream
->buffering
= 1;
2278 ngx_http_upstream_process_charset(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2281 r
->headers_out
.override_charset
= &h
->value
;
2288 ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2291 ngx_table_elt_t
*ho
, **ph
;
2293 ho
= ngx_list_push(&r
->headers_out
.headers
);
2301 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_out
+ offset
);
2310 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
2311 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2314 ngx_table_elt_t
*ho
, **ph
;
2316 pa
= (ngx_array_t
*) ((char *) &r
->headers_out
+ offset
);
2318 if (pa
->elts
== NULL
) {
2319 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
2325 ph
= ngx_array_push(pa
);
2330 ho
= ngx_list_push(&r
->headers_out
.headers
);
2343 ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2348 r
->headers_out
.content_type_len
= h
->value
.len
;
2349 r
->headers_out
.content_type
= h
->value
;
2351 for (p
= h
->value
.data
; *p
; p
++) {
2359 while (*++p
== ' ') { /* void */ }
2361 if (ngx_strncasecmp(p
, (u_char
*) "charset=", 8) != 0) {
2367 r
->headers_out
.content_type_len
= last
- h
->value
.data
;
2369 r
->headers_out
.charset
.len
= h
->value
.data
+ h
->value
.len
- p
;
2370 r
->headers_out
.charset
.data
= p
;
2380 ngx_http_upstream_copy_content_length(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2383 ngx_table_elt_t
*ho
;
2385 ho
= ngx_list_push(&r
->headers_out
.headers
);
2392 r
->headers_out
.content_length
= ho
;
2393 r
->headers_out
.content_length_n
= ngx_atoof(h
->value
.data
, h
->value
.len
);
2400 ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2404 ngx_table_elt_t
*ho
;
2406 ho
= ngx_list_push(&r
->headers_out
.headers
);
2413 if (r
->upstream
->rewrite_redirect
) {
2414 rc
= r
->upstream
->rewrite_redirect(r
, ho
, 0);
2416 if (rc
== NGX_DECLINED
) {
2421 r
->headers_out
.location
= ho
;
2423 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2424 "rewritten location: \"%V\"", &ho
->value
);
2431 * we do not set r->headers_out.location here to avoid the handling
2432 * the local redirects without a host name by ngx_http_header_filter()
2440 ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2445 ngx_table_elt_t
*ho
;
2447 ho
= ngx_list_push(&r
->headers_out
.headers
);
2454 if (r
->upstream
->rewrite_redirect
) {
2456 p
= (u_char
*) ngx_strstr(ho
->value
.data
, "url=");
2459 rc
= r
->upstream
->rewrite_redirect(r
, ho
, p
+ 4 - ho
->value
.data
);
2465 if (rc
== NGX_DECLINED
) {
2471 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2472 "rewritten refresh: \"%V\"", &ho
->value
);
2486 ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
2487 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2489 ngx_table_elt_t
*ho
;
2491 ho
= ngx_list_push(&r
->headers_out
.headers
);
2498 r
->headers_out
.content_encoding
= ho
;
2507 ngx_http_upstream_add_variables(ngx_conf_t
*cf
)
2509 ngx_http_variable_t
*var
, *v
;
2511 for (v
= ngx_http_upstream_vars
; v
->name
.len
; v
++) {
2512 var
= ngx_http_add_variable(cf
, &v
->name
, v
->flags
);
2517 var
->get_handler
= v
->get_handler
;
2518 var
->data
= v
->data
;
2526 ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
2527 ngx_http_variable_value_t
*v
, uintptr_t data
)
2532 ngx_http_upstream_state_t
*state
;
2538 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2544 state
= r
->upstream_states
->elts
;
2546 for (i
= 0; i
< r
->upstream_states
->nelts
; i
++) {
2547 if (state
[i
].peer
) {
2548 len
+= state
[i
].peer
->len
+ 2;
2555 p
= ngx_palloc(r
->pool
, len
);
2565 if (state
[i
].peer
) {
2566 p
= ngx_cpymem(p
, state
[i
].peer
->data
, state
[i
].peer
->len
);
2569 if (++i
== r
->upstream_states
->nelts
) {
2573 if (state
[i
].peer
) {
2582 if (++i
== r
->upstream_states
->nelts
) {
2590 v
->len
= p
- v
->data
;
2597 ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
2598 ngx_http_variable_value_t
*v
, uintptr_t data
)
2603 ngx_http_upstream_state_t
*state
;
2609 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2614 len
= r
->upstream_states
->nelts
* (3 + 2);
2616 p
= ngx_palloc(r
->pool
, len
);
2624 state
= r
->upstream_states
->elts
;
2627 if (state
[i
].status
) {
2628 p
= ngx_sprintf(p
, "%ui", state
[i
].status
);
2634 if (++i
== r
->upstream_states
->nelts
) {
2638 if (state
[i
].peer
) {
2647 if (++i
== r
->upstream_states
->nelts
) {
2655 v
->len
= p
- v
->data
;
2662 ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
2663 ngx_http_variable_value_t
*v
, uintptr_t data
)
2669 ngx_http_upstream_state_t
*state
;
2675 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2680 len
= r
->upstream_states
->nelts
* (NGX_TIME_T_LEN
+ 4 + 2);
2682 p
= ngx_palloc(r
->pool
, len
);
2690 state
= r
->upstream_states
->elts
;
2693 if (state
[i
].status
) {
2694 ms
= state
[i
].response_sec
* 1000 + state
[i
].response_msec
;
2695 ms
= (ms
>= 0) ? ms
: 0;
2696 p
= ngx_sprintf(p
, "%d.%03d", ms
/ 1000, ms
% 1000);
2702 if (++i
== r
->upstream_states
->nelts
) {
2706 if (state
[i
].peer
) {
2715 if (++i
== r
->upstream_states
->nelts
) {
2723 v
->len
= p
- v
->data
;
2730 ngx_http_upstream_header_variable(ngx_http_request_t
*r
,
2731 ngx_http_variable_value_t
*v
, uintptr_t data
)
2733 if (r
->upstream
== NULL
) {
2738 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
2739 &r
->upstream
->headers_in
.headers
.part
,
2740 sizeof("upstream_http_") - 1);
2745 ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
)
2753 ngx_http_module_t
*module
;
2754 ngx_http_conf_ctx_t
*ctx
, *http_ctx
;
2755 ngx_http_upstream_srv_conf_t
*uscf
;
2757 ngx_memzero(&u
, sizeof(ngx_url_t
));
2759 value
= cf
->args
->elts
;
2763 uscf
= ngx_http_upstream_add(cf
, &u
, NGX_HTTP_UPSTREAM_CREATE
2764 |NGX_HTTP_UPSTREAM_WEIGHT
2765 |NGX_HTTP_UPSTREAM_MAX_FAILS
2766 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
2767 |NGX_HTTP_UPSTREAM_DOWN
2768 |NGX_HTTP_UPSTREAM_BACKUP
);
2770 return NGX_CONF_ERROR
;
2774 ctx
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_conf_ctx_t
));
2776 return NGX_CONF_ERROR
;
2780 ctx
->main_conf
= http_ctx
->main_conf
;
2782 /* the upstream{}'s srv_conf */
2784 ctx
->srv_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
2785 if (ctx
->srv_conf
== NULL
) {
2786 return NGX_CONF_ERROR
;
2789 ctx
->srv_conf
[ngx_http_upstream_module
.ctx_index
] = uscf
;
2791 uscf
->srv_conf
= ctx
->srv_conf
;
2794 /* the upstream{}'s loc_conf */
2796 ctx
->loc_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
2797 if (ctx
->loc_conf
== NULL
) {
2798 return NGX_CONF_ERROR
;
2801 for (m
= 0; ngx_modules
[m
]; m
++) {
2802 if (ngx_modules
[m
]->type
!= NGX_HTTP_MODULE
) {
2806 module
= ngx_modules
[m
]->ctx
;
2808 if (module
->create_srv_conf
) {
2809 mconf
= module
->create_srv_conf(cf
);
2810 if (mconf
== NULL
) {
2811 return NGX_CONF_ERROR
;
2814 ctx
->srv_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
2817 if (module
->create_loc_conf
) {
2818 mconf
= module
->create_loc_conf(cf
);
2819 if (mconf
== NULL
) {
2820 return NGX_CONF_ERROR
;
2823 ctx
->loc_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
2828 /* parse inside upstream{} */
2832 cf
->cmd_type
= NGX_HTTP_UPS_CONF
;
2834 rv
= ngx_conf_parse(cf
, NULL
);
2838 if (rv
!= NGX_CONF_OK
) {
2842 if (uscf
->servers
== NULL
) {
2843 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2844 "no servers are inside upstream");
2845 return NGX_CONF_ERROR
;
2853 ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2855 ngx_http_upstream_srv_conf_t
*uscf
= conf
;
2857 time_t fail_timeout
;
2858 ngx_str_t
*value
, s
;
2860 ngx_int_t weight
, max_fails
;
2862 ngx_http_upstream_server_t
*us
;
2864 if (uscf
->servers
== NULL
) {
2865 uscf
->servers
= ngx_array_create(cf
->pool
, 4,
2866 sizeof(ngx_http_upstream_server_t
));
2867 if (uscf
->servers
== NULL
) {
2868 return NGX_CONF_ERROR
;
2872 us
= ngx_array_push(uscf
->servers
);
2874 return NGX_CONF_ERROR
;
2877 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
2879 value
= cf
->args
->elts
;
2881 ngx_memzero(&u
, sizeof(ngx_url_t
));
2884 u
.default_port
= 80;
2886 if (ngx_parse_url(cf
, &u
) != NGX_OK
) {
2888 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2889 "%s in upstream \"%V\"", u
.err
, &u
.url
);
2892 return NGX_CONF_ERROR
;
2899 for (i
= 2; i
< cf
->args
->nelts
; i
++) {
2901 if (ngx_strncmp(value
[i
].data
, "weight=", 7) == 0) {
2903 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_WEIGHT
)) {
2907 weight
= ngx_atoi(&value
[i
].data
[7], value
[i
].len
- 7);
2909 if (weight
== NGX_ERROR
|| weight
== 0) {
2916 if (ngx_strncmp(value
[i
].data
, "max_fails=", 10) == 0) {
2918 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_MAX_FAILS
)) {
2922 max_fails
= ngx_atoi(&value
[i
].data
[10], value
[i
].len
- 10);
2924 if (max_fails
== NGX_ERROR
) {
2931 if (ngx_strncmp(value
[i
].data
, "fail_timeout=", 13) == 0) {
2933 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
)) {
2937 s
.len
= value
[i
].len
- 13;
2938 s
.data
= &value
[i
].data
[13];
2940 fail_timeout
= ngx_parse_time(&s
, 1);
2942 if (fail_timeout
< 0) {
2949 if (ngx_strncmp(value
[i
].data
, "down", 4) == 0) {
2951 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_DOWN
)) {
2963 us
->addrs
= u
.addrs
;
2964 us
->naddrs
= u
.naddrs
;
2965 us
->weight
= weight
;
2966 us
->max_fails
= max_fails
;
2967 us
->fail_timeout
= fail_timeout
;
2973 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2974 "invalid parameter \"%V\"", &value
[i
]);
2976 return NGX_CONF_ERROR
;
2980 ngx_http_upstream_srv_conf_t
*
2981 ngx_http_upstream_add(ngx_conf_t
*cf
, ngx_url_t
*u
, ngx_uint_t flags
)
2984 ngx_http_upstream_server_t
*us
;
2985 ngx_http_upstream_srv_conf_t
*uscf
, **uscfp
;
2986 ngx_http_upstream_main_conf_t
*umcf
;
2988 if (!(flags
& NGX_HTTP_UPSTREAM_CREATE
)) {
2990 if (ngx_parse_url(cf
, u
) != NGX_OK
) {
2992 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2993 "%s in upstream \"%V\"", u
->err
, &u
->url
);
3000 umcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_upstream_module
);
3002 uscfp
= umcf
->upstreams
.elts
;
3004 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
3006 if (uscfp
[i
]->host
.len
!= u
->host
.len
3007 || ngx_strncasecmp(uscfp
[i
]->host
.data
, u
->host
.data
, u
->host
.len
)
3013 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
)
3014 && (uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
))
3016 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3017 "duplicate upstream \"%V\"", &u
->host
);
3021 if ((uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
) && u
->port
) {
3022 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
3023 "upstream \"%V\" may not have port %d",
3028 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
) && uscfp
[i
]->port
) {
3029 ngx_log_error(NGX_LOG_WARN
, cf
->log
, 0,
3030 "upstream \"%V\" may not have port %d in %s:%ui",
3031 &u
->host
, uscfp
[i
]->port
,
3032 uscfp
[i
]->file_name
.data
, uscfp
[i
]->line
);
3036 if (uscfp
[i
]->port
!= u
->port
) {
3043 uscf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_srv_conf_t
));
3048 uscf
->flags
= flags
;
3049 uscf
->host
= u
->host
;
3050 uscf
->file_name
= cf
->conf_file
->file
.name
;
3051 uscf
->line
= cf
->conf_file
->line
;
3052 uscf
->port
= u
->port
;
3053 uscf
->default_port
= u
->default_port
;
3055 if (u
->naddrs
== 1) {
3056 uscf
->servers
= ngx_array_create(cf
->pool
, 1,
3057 sizeof(ngx_http_upstream_server_t
));
3058 if (uscf
->servers
== NULL
) {
3059 return NGX_CONF_ERROR
;
3062 us
= ngx_array_push(uscf
->servers
);
3064 return NGX_CONF_ERROR
;
3067 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
3069 us
->addrs
= u
->addrs
;
3070 us
->naddrs
= u
->naddrs
;
3073 uscfp
= ngx_array_push(&umcf
->upstreams
);
3074 if (uscfp
== NULL
) {
3085 ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
)
3087 ngx_http_upstream_main_conf_t
*umcf
;
3089 umcf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_main_conf_t
));
3094 if (ngx_array_init(&umcf
->upstreams
, cf
->pool
, 4,
3095 sizeof(ngx_http_upstream_srv_conf_t
*))
3098 return NGX_CONF_ERROR
;
3106 ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
)
3108 ngx_http_upstream_main_conf_t
*umcf
= conf
;
3111 ngx_array_t headers_in
;
3113 ngx_hash_init_t hash
;
3114 ngx_http_upstream_init_pt init
;
3115 ngx_http_upstream_header_t
*header
;
3116 ngx_http_upstream_srv_conf_t
**uscfp
;
3118 uscfp
= umcf
->upstreams
.elts
;
3120 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
3122 init
= uscfp
[i
]->peer
.init_upstream
? uscfp
[i
]->peer
.init_upstream
:
3123 ngx_http_upstream_init_round_robin
;
3125 if (init(cf
, uscfp
[i
]) != NGX_OK
) {
3126 return NGX_CONF_ERROR
;
3131 /* upstream_headers_in_hash */
3133 if (ngx_array_init(&headers_in
, cf
->temp_pool
, 32, sizeof(ngx_hash_key_t
))
3136 return NGX_CONF_ERROR
;
3139 for (header
= ngx_http_upstream_headers_in
; header
->name
.len
; header
++) {
3140 hk
= ngx_array_push(&headers_in
);
3142 return NGX_CONF_ERROR
;
3145 hk
->key
= header
->name
;
3146 hk
->key_hash
= ngx_hash_key_lc(header
->name
.data
, header
->name
.len
);
3150 hash
.hash
= &umcf
->headers_in_hash
;
3151 hash
.key
= ngx_hash_key_lc
;
3152 hash
.max_size
= 512;
3153 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
3154 hash
.name
= "upstream_headers_in_hash";
3155 hash
.pool
= cf
->pool
;
3156 hash
.temp_pool
= NULL
;
3158 if (ngx_hash_init(&hash
, headers_in
.elts
, headers_in
.nelts
) != NGX_OK
) {
3159 return NGX_CONF_ERROR
;