3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t
*ctx
);
13 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
);
14 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
);
15 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
17 static void ngx_http_upstream_connect(ngx_http_request_t
*r
,
18 ngx_http_upstream_t
*u
);
19 static ngx_int_t
ngx_http_upstream_reinit(ngx_http_request_t
*r
,
20 ngx_http_upstream_t
*u
);
21 static void ngx_http_upstream_send_request(ngx_http_request_t
*r
,
22 ngx_http_upstream_t
*u
);
23 static void ngx_http_upstream_send_request_handler(ngx_event_t
*wev
);
24 static void ngx_http_upstream_process_header(ngx_event_t
*rev
);
25 static ngx_int_t
ngx_http_upstream_test_connect(ngx_connection_t
*c
);
26 static void ngx_http_upstream_process_body_in_memory(ngx_event_t
*rev
);
27 static void ngx_http_upstream_send_response(ngx_http_request_t
*r
,
28 ngx_http_upstream_t
*u
);
30 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
);
31 static void ngx_http_upstream_process_non_buffered_body(ngx_event_t
*ev
);
32 static ngx_int_t
ngx_http_upstream_non_buffered_filter_init(void *data
);
33 static ngx_int_t
ngx_http_upstream_non_buffered_filter(void *data
,
35 static void ngx_http_upstream_process_downstream(ngx_http_request_t
*r
);
36 static void ngx_http_upstream_process_body(ngx_event_t
*ev
);
37 static void ngx_http_upstream_store(ngx_http_request_t
*r
,
38 ngx_http_upstream_t
*u
);
39 static void ngx_http_upstream_dummy_handler(ngx_event_t
*wev
);
40 static void ngx_http_upstream_next(ngx_http_request_t
*r
,
41 ngx_http_upstream_t
*u
, ngx_uint_t ft_type
);
42 static void ngx_http_upstream_cleanup(void *data
);
43 static void ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
44 ngx_http_upstream_t
*u
, ngx_int_t rc
);
46 static ngx_int_t
ngx_http_upstream_process_header_line(ngx_http_request_t
*r
,
47 ngx_table_elt_t
*h
, ngx_uint_t offset
);
49 ngx_http_upstream_process_multi_header_lines(ngx_http_request_t
*r
,
50 ngx_table_elt_t
*h
, ngx_uint_t offset
);
51 static ngx_int_t
ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
,
52 ngx_table_elt_t
*h
, ngx_uint_t offset
);
53 static ngx_int_t
ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
,
54 ngx_table_elt_t
*h
, ngx_uint_t offset
);
55 static ngx_int_t
ngx_http_upstream_process_buffering(ngx_http_request_t
*r
,
56 ngx_table_elt_t
*h
, ngx_uint_t offset
);
57 static ngx_int_t
ngx_http_upstream_process_charset(ngx_http_request_t
*r
,
58 ngx_table_elt_t
*h
, ngx_uint_t offset
);
59 static ngx_int_t
ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
,
60 ngx_table_elt_t
*h
, ngx_uint_t offset
);
62 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
63 ngx_table_elt_t
*h
, ngx_uint_t offset
);
64 static ngx_int_t
ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
,
65 ngx_table_elt_t
*h
, ngx_uint_t offset
);
66 static ngx_int_t
ngx_http_upstream_copy_content_length(ngx_http_request_t
*r
,
67 ngx_table_elt_t
*h
, ngx_uint_t offset
);
68 static ngx_int_t
ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
,
69 ngx_table_elt_t
*h
, ngx_uint_t offset
);
70 static ngx_int_t
ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
,
71 ngx_table_elt_t
*h
, ngx_uint_t offset
);
73 static ngx_int_t
ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
74 ngx_table_elt_t
*h
, ngx_uint_t offset
);
77 static ngx_int_t
ngx_http_upstream_add_variables(ngx_conf_t
*cf
);
78 static ngx_int_t
ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
79 ngx_http_variable_value_t
*v
, uintptr_t data
);
80 static ngx_int_t
ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
81 ngx_http_variable_value_t
*v
, uintptr_t data
);
82 static ngx_int_t
ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
83 ngx_http_variable_value_t
*v
, uintptr_t data
);
85 static char *ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
);
86 static char *ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
89 static void *ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
);
90 static char *ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
);
93 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*,
94 ngx_http_upstream_t
*u
, ngx_connection_t
*c
);
95 static void ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
);
99 ngx_http_upstream_header_t ngx_http_upstream_headers_in
[] = {
101 { ngx_string("Status"),
102 ngx_http_upstream_process_header_line
,
103 offsetof(ngx_http_upstream_headers_in_t
, status
),
104 ngx_http_upstream_copy_header_line
, 0, 0 },
106 { ngx_string("Content-Type"),
107 ngx_http_upstream_process_header_line
,
108 offsetof(ngx_http_upstream_headers_in_t
, content_type
),
109 ngx_http_upstream_copy_content_type
, 0, 1 },
111 { ngx_string("Content-Length"),
112 ngx_http_upstream_process_header_line
,
113 offsetof(ngx_http_upstream_headers_in_t
, content_length
),
114 ngx_http_upstream_copy_content_length
, 0, 0 },
116 { ngx_string("Date"),
117 ngx_http_upstream_process_header_line
,
118 offsetof(ngx_http_upstream_headers_in_t
, date
),
119 ngx_http_upstream_copy_header_line
,
120 offsetof(ngx_http_headers_out_t
, date
), 0 },
122 { ngx_string("Last-Modified"),
123 ngx_http_upstream_process_header_line
,
124 offsetof(ngx_http_upstream_headers_in_t
, last_modified
),
125 ngx_http_upstream_copy_header_line
,
126 offsetof(ngx_http_headers_out_t
, last_modified
), 0 },
128 { ngx_string("Server"),
129 ngx_http_upstream_process_header_line
,
130 offsetof(ngx_http_upstream_headers_in_t
, server
),
131 ngx_http_upstream_copy_header_line
,
132 offsetof(ngx_http_headers_out_t
, server
), 0 },
134 { ngx_string("WWW-Authenticate"),
135 ngx_http_upstream_process_header_line
,
136 offsetof(ngx_http_upstream_headers_in_t
, www_authenticate
),
137 ngx_http_upstream_copy_header_line
, 0, 0 },
139 { ngx_string("Location"),
140 ngx_http_upstream_process_header_line
,
141 offsetof(ngx_http_upstream_headers_in_t
, location
),
142 ngx_http_upstream_rewrite_location
, 0, 0 },
144 { ngx_string("Refresh"),
145 ngx_http_upstream_ignore_header_line
, 0,
146 ngx_http_upstream_rewrite_refresh
, 0, 0 },
148 { ngx_string("Set-Cookie"),
149 ngx_http_upstream_ignore_header_line
, 0,
150 ngx_http_upstream_copy_header_line
, 0, 1 },
152 { ngx_string("Content-Disposition"),
153 ngx_http_upstream_ignore_header_line
, 0,
154 ngx_http_upstream_copy_header_line
, 0, 1 },
156 { ngx_string("Cache-Control"),
157 ngx_http_upstream_process_multi_header_lines
,
158 offsetof(ngx_http_upstream_headers_in_t
, cache_control
),
159 ngx_http_upstream_copy_multi_header_lines
,
160 offsetof(ngx_http_headers_out_t
, cache_control
), 1 },
162 { ngx_string("Expires"),
163 ngx_http_upstream_process_header_line
,
164 offsetof(ngx_http_upstream_headers_in_t
, expires
),
165 ngx_http_upstream_copy_header_line
,
166 offsetof(ngx_http_headers_out_t
, expires
), 1 },
168 { ngx_string("Accept-Ranges"),
169 ngx_http_upstream_process_header_line
,
170 offsetof(ngx_http_upstream_headers_in_t
, accept_ranges
),
171 ngx_http_upstream_copy_header_line
,
172 offsetof(ngx_http_headers_out_t
, accept_ranges
), 1 },
174 { ngx_string("Connection"),
175 ngx_http_upstream_ignore_header_line
, 0,
176 ngx_http_upstream_ignore_header_line
, 0, 0 },
178 { ngx_string("Keep-Alive"),
179 ngx_http_upstream_ignore_header_line
, 0,
180 ngx_http_upstream_ignore_header_line
, 0, 0 },
182 { ngx_string("X-Powered-By"),
183 ngx_http_upstream_ignore_header_line
, 0,
184 ngx_http_upstream_copy_header_line
, 0, 0 },
186 { ngx_string("X-Accel-Expires"),
187 ngx_http_upstream_process_header_line
,
188 offsetof(ngx_http_upstream_headers_in_t
, x_accel_expires
),
189 ngx_http_upstream_copy_header_line
, 0, 0 },
191 { ngx_string("X-Accel-Redirect"),
192 ngx_http_upstream_process_header_line
,
193 offsetof(ngx_http_upstream_headers_in_t
, x_accel_redirect
),
194 ngx_http_upstream_ignore_header_line
, 0, 0 },
196 { ngx_string("X-Accel-Limit-Rate"),
197 ngx_http_upstream_process_limit_rate
, 0,
198 ngx_http_upstream_ignore_header_line
, 0, 0 },
200 { ngx_string("X-Accel-Buffering"),
201 ngx_http_upstream_process_buffering
, 0,
202 ngx_http_upstream_ignore_header_line
, 0, 0 },
204 { ngx_string("X-Accel-Charset"),
205 ngx_http_upstream_process_charset
, 0,
206 ngx_http_upstream_ignore_header_line
, 0, 0 },
209 { ngx_string("Content-Encoding"),
210 ngx_http_upstream_process_header_line
,
211 offsetof(ngx_http_upstream_headers_in_t
, content_encoding
),
212 ngx_http_upstream_copy_content_encoding
, 0, 0 },
215 { ngx_null_string
, NULL
, 0, NULL
, 0, 0 }
219 static ngx_command_t ngx_http_upstream_commands
[] = {
221 { ngx_string("upstream"),
222 NGX_HTTP_MAIN_CONF
|NGX_CONF_BLOCK
|NGX_CONF_TAKE1
,
228 { ngx_string("server"),
229 NGX_HTTP_UPS_CONF
|NGX_CONF_1MORE
,
230 ngx_http_upstream_server
,
231 NGX_HTTP_SRV_CONF_OFFSET
,
239 static ngx_http_module_t ngx_http_upstream_module_ctx
= {
240 ngx_http_upstream_add_variables
, /* preconfiguration */
241 NULL
, /* postconfiguration */
243 ngx_http_upstream_create_main_conf
, /* create main configuration */
244 ngx_http_upstream_init_main_conf
, /* init main configuration */
246 NULL
, /* create server configuration */
247 NULL
, /* merge server configuration */
249 NULL
, /* create location configuration */
250 NULL
/* merge location configuration */
254 ngx_module_t ngx_http_upstream_module
= {
256 &ngx_http_upstream_module_ctx
, /* module context */
257 ngx_http_upstream_commands
, /* module directives */
258 NGX_HTTP_MODULE
, /* module type */
259 NULL
, /* init master */
260 NULL
, /* init module */
261 NULL
, /* init process */
262 NULL
, /* init thread */
263 NULL
, /* exit thread */
264 NULL
, /* exit process */
265 NULL
, /* exit master */
266 NGX_MODULE_V1_PADDING
270 static ngx_http_variable_t ngx_http_upstream_vars
[] = {
272 { ngx_string("upstream_addr"), NULL
,
273 ngx_http_upstream_addr_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
275 { ngx_string("upstream_status"), NULL
,
276 ngx_http_upstream_status_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
278 { ngx_string("upstream_response_time"), NULL
,
279 ngx_http_upstream_response_time_variable
, 0, NGX_HTTP_VAR_NOHASH
, 0 },
281 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
286 ngx_http_upstream_init(ngx_http_request_t
*r
)
291 ngx_resolver_ctx_t
*ctx
, temp
;
292 ngx_http_cleanup_t
*cln
;
293 ngx_http_upstream_t
*u
;
294 ngx_http_core_loc_conf_t
*clcf
;
295 ngx_http_upstream_srv_conf_t
*uscf
, **uscfp
;
296 ngx_http_upstream_main_conf_t
*umcf
;
300 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
301 "http init upstream, client timer: %d", c
->read
->timer_set
);
303 if (c
->read
->timer_set
) {
304 ngx_del_timer(c
->read
);
309 if (!r
->post_action
&& !u
->conf
->ignore_client_abort
) {
310 r
->read_event_handler
= ngx_http_upstream_rd_check_broken_connection
;
311 r
->write_event_handler
= ngx_http_upstream_wr_check_broken_connection
;
314 if (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) {
316 if (!c
->write
->active
) {
317 if (ngx_add_event(c
->write
, NGX_WRITE_EVENT
, NGX_CLEAR_EVENT
)
320 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
326 if (r
->request_body
) {
327 u
->request_bufs
= r
->request_body
->bufs
;
330 if (u
->create_request(r
) != NGX_OK
) {
331 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
335 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
337 u
->output
.pool
= r
->pool
;
338 u
->output
.bufs
.num
= 1;
339 u
->output
.bufs
.size
= clcf
->client_body_buffer_size
;
340 u
->output
.output_filter
= ngx_chain_writer
;
341 u
->output
.filter_ctx
= &u
->writer
;
343 u
->writer
.pool
= r
->pool
;
345 if (r
->upstream_states
== NULL
) {
347 r
->upstream_states
= ngx_array_create(r
->pool
, 1,
348 sizeof(ngx_http_upstream_state_t
));
349 if (r
->upstream_states
== NULL
) {
350 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
356 u
->state
= ngx_array_push(r
->upstream_states
);
357 if (u
->state
== NULL
) {
358 ngx_http_upstream_finalize_request(r
, u
,
359 NGX_HTTP_INTERNAL_SERVER_ERROR
);
363 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
366 cln
= ngx_http_cleanup_add(r
, 0);
368 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
372 cln
->handler
= ngx_http_upstream_cleanup
;
374 u
->cleanup
= &cln
->handler
;
376 u
->store
= (u
->conf
->store
|| u
->conf
->store_lengths
);
378 if (u
->resolved
== NULL
) {
380 uscf
= u
->conf
->upstream
;
384 host
= &u
->resolved
->host
;
386 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
388 uscfp
= umcf
->upstreams
.elts
;
390 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
394 if (uscf
->host
.len
== host
->len
395 && ((uscf
->port
== 0 && u
->resolved
->default_port
)
396 || uscf
->port
== u
->resolved
->port
)
397 && ngx_memcmp(uscf
->host
.data
, host
->data
, host
->len
) == 0)
405 ctx
= ngx_resolve_start(clcf
->resolver
, &temp
);
407 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
411 if (ctx
== NGX_NO_RESOLVER
) {
412 ngx_log_error(NGX_LOG_ERR
, c
->log
, 0,
413 "no resolver defined to resolve %V", host
);
415 ngx_http_finalize_request(r
, NGX_HTTP_BAD_GATEWAY
);
420 ctx
->type
= NGX_RESOLVE_A
;
421 ctx
->handler
= ngx_http_upstream_resolve_handler
;
423 ctx
->timeout
= clcf
->resolver_timeout
;
425 u
->resolved
->ctx
= ctx
;
427 if (ngx_resolve_name(ctx
) != NGX_OK
) {
428 u
->resolved
->ctx
= NULL
;
429 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
438 if (uscf
->peer
.init(r
, uscf
) != NGX_OK
) {
439 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
443 ngx_http_upstream_connect(r
, u
);
448 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t
*ctx
)
450 ngx_http_request_t
*r
;
451 ngx_http_upstream_resolved_t
*ur
;
455 r
->upstream
->resolved
->ctx
= NULL
;
458 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
459 "%V could not be resolved (%i: %s)",
460 &ctx
->name
, ctx
->state
,
461 ngx_resolver_strerror(ctx
->state
));
463 ngx_resolve_name_done(ctx
);
464 ngx_http_finalize_request(r
, NGX_HTTP_BAD_GATEWAY
);
468 ur
= r
->upstream
->resolved
;
469 ur
->naddrs
= ctx
->naddrs
;
470 ur
->addrs
= ctx
->addrs
;
477 for (i
= 0; i
< ctx
->naddrs
; i
++) {
478 addr
= ntohl(ur
->addrs
[i
]);
480 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
481 "name was resolved to %ud.%ud.%ud.%ud",
482 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
483 (addr
>> 8) & 0xff, addr
& 0xff);
488 if (ngx_http_upstream_create_round_robin_peer(r
, ur
) != NGX_OK
) {
489 ngx_resolve_name_done(ctx
);
490 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
494 ngx_resolve_name_done(ctx
);
496 ngx_http_upstream_connect(r
, r
->upstream
);
501 ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t
*r
)
503 ngx_http_upstream_check_broken_connection(r
, r
->connection
->read
);
508 ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t
*r
)
510 ngx_http_upstream_check_broken_connection(r
, r
->connection
->write
);
515 ngx_http_upstream_check_broken_connection(ngx_http_request_t
*r
,
522 ngx_http_upstream_t
*u
;
524 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, ev
->log
, 0,
525 "http upstream check client, write event:%d, \"%V\"",
532 ngx_http_upstream_finalize_request(r
, u
,
533 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
537 if (u
->peer
.connection
== NULL
) {
541 #if (NGX_HAVE_KQUEUE)
543 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
545 if (!ev
->pending_eof
) {
556 if (!u
->cacheable
&& !u
->store
&& u
->peer
.connection
) {
557 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
558 "kevent() reported that client closed prematurely "
559 "connection, so upstream connection is closed too");
560 ngx_http_upstream_finalize_request(r
, u
,
561 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
565 ngx_log_error(NGX_LOG_INFO
, ev
->log
, ev
->kq_errno
,
566 "kevent() reported that client closed "
567 "prematurely connection");
569 if (u
->peer
.connection
== NULL
) {
570 ngx_http_upstream_finalize_request(r
, u
,
571 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
580 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
582 err
= ngx_socket_errno
;
584 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, ev
->log
, err
,
585 "http upstream recv(): %d", n
);
588 * we do not need to disable the write event because
589 * that event has NGX_USE_CLEAR_EVENT type
592 if (ev
->write
&& (n
>= 0 || err
== NGX_EAGAIN
)) {
596 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && ev
->active
) {
597 if (ngx_del_event(ev
, NGX_READ_EVENT
, 0) == NGX_ERROR
) {
598 ngx_http_upstream_finalize_request(r
, u
,
599 NGX_HTTP_INTERNAL_SERVER_ERROR
);
609 if (err
== NGX_EAGAIN
) {
615 } else { /* n == 0 */
622 if (!u
->cacheable
&& !u
->store
&& u
->peer
.connection
) {
623 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
624 "client closed prematurely connection, "
625 "so upstream connection is closed too");
626 ngx_http_upstream_finalize_request(r
, u
,
627 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
631 ngx_log_error(NGX_LOG_INFO
, ev
->log
, err
,
632 "client closed prematurely connection");
634 if (u
->peer
.connection
== NULL
) {
635 ngx_http_upstream_finalize_request(r
, u
,
636 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
643 ngx_http_upstream_connect(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
649 r
->connection
->log
->action
= "connecting to upstream";
651 r
->connection
->single_connection
= 0;
653 if (u
->state
&& u
->state
->response_sec
) {
654 tp
= ngx_timeofday();
655 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
656 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
659 u
->state
= ngx_array_push(r
->upstream_states
);
660 if (u
->state
== NULL
) {
661 ngx_http_upstream_finalize_request(r
, u
,
662 NGX_HTTP_INTERNAL_SERVER_ERROR
);
666 ngx_memzero(u
->state
, sizeof(ngx_http_upstream_state_t
));
668 tp
= ngx_timeofday();
669 u
->state
->response_sec
= tp
->sec
;
670 u
->state
->response_msec
= tp
->msec
;
672 rc
= ngx_event_connect_peer(&u
->peer
);
674 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
675 "http upstream connect: %i", rc
);
677 if (rc
== NGX_ERROR
) {
678 ngx_http_upstream_finalize_request(r
, u
,
679 NGX_HTTP_INTERNAL_SERVER_ERROR
);
683 u
->state
->peer
= u
->peer
.name
;
685 if (rc
== NGX_BUSY
) {
686 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0, "no live upstreams");
687 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_NOLIVE
);
691 if (rc
== NGX_DECLINED
) {
692 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
696 /* rc == NGX_OK || rc == NGX_AGAIN */
698 c
= u
->peer
.connection
;
702 c
->write
->handler
= ngx_http_upstream_send_request_handler
;
703 c
->read
->handler
= ngx_http_upstream_process_header
;
705 c
->sendfile
&= r
->connection
->sendfile
;
706 u
->output
.sendfile
= c
->sendfile
;
709 c
->read
->log
= c
->write
->log
= c
->log
= r
->connection
->log
;
711 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
713 u
->writer
.out
= NULL
;
714 u
->writer
.last
= &u
->writer
.out
;
715 u
->writer
.connection
= c
;
718 if (u
->request_sent
) {
719 if (ngx_http_upstream_reinit(r
, u
) != NGX_OK
) {
720 ngx_http_upstream_finalize_request(r
, u
,
721 NGX_HTTP_INTERNAL_SERVER_ERROR
);
727 && r
->request_body
->buf
728 && r
->request_body
->temp_file
732 * the r->request_body->buf can be reused for one request only,
733 * the subrequests should allocate their own temporay bufs
736 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
737 if (u
->output
.free
== NULL
) {
738 ngx_http_upstream_finalize_request(r
, u
,
739 NGX_HTTP_INTERNAL_SERVER_ERROR
);
743 u
->output
.free
->buf
= r
->request_body
->buf
;
744 u
->output
.free
->next
= NULL
;
745 u
->output
.allocated
= 1;
747 r
->request_body
->buf
->pos
= r
->request_body
->buf
->start
;
748 r
->request_body
->buf
->last
= r
->request_body
->buf
->start
;
749 r
->request_body
->buf
->tag
= u
->output
.tag
;
754 if (rc
== NGX_AGAIN
) {
755 ngx_add_timer(c
->write
, u
->conf
->connect_timeout
);
761 if (u
->ssl
&& c
->ssl
== NULL
) {
762 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
768 ngx_http_upstream_send_request(r
, u
);
775 ngx_http_upstream_ssl_init_connection(ngx_http_request_t
*r
,
776 ngx_http_upstream_t
*u
, ngx_connection_t
*c
)
780 if (ngx_ssl_create_connection(u
->conf
->ssl
, c
,
781 NGX_SSL_BUFFER
|NGX_SSL_CLIENT
)
784 ngx_http_upstream_finalize_request(r
, u
,
785 NGX_HTTP_INTERNAL_SERVER_ERROR
);
790 u
->output
.sendfile
= 0;
792 if (u
->peer
.set_session(&u
->peer
, u
->peer
.data
) != NGX_OK
) {
793 ngx_http_upstream_finalize_request(r
, u
,
794 NGX_HTTP_INTERNAL_SERVER_ERROR
);
798 r
->connection
->log
->action
= "SSL handshaking to upstream";
800 rc
= ngx_ssl_handshake(c
);
802 if (rc
== NGX_AGAIN
) {
803 c
->ssl
->handler
= ngx_http_upstream_ssl_handshake
;
807 ngx_http_upstream_ssl_handshake(c
);
812 ngx_http_upstream_ssl_handshake(ngx_connection_t
*c
)
814 ngx_http_request_t
*r
;
815 ngx_http_upstream_t
*u
;
820 if (c
->ssl
->handshaked
) {
822 u
->peer
.save_session(&u
->peer
, u
->peer
.data
);
824 c
->write
->handler
= ngx_http_upstream_send_request_handler
;
825 c
->read
->handler
= ngx_http_upstream_process_header
;
827 ngx_http_upstream_send_request(r
, u
);
832 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
840 ngx_http_upstream_reinit(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
844 if (u
->reinit_request(r
) != NGX_OK
) {
848 ngx_memzero(&u
->headers_in
, sizeof(ngx_http_upstream_headers_in_t
));
850 if (ngx_list_init(&u
->headers_in
.headers
, r
->pool
, 8,
851 sizeof(ngx_table_elt_t
))
857 /* reinit the request chain */
859 for (cl
= u
->request_bufs
; cl
; cl
= cl
->next
) {
860 cl
->buf
->pos
= cl
->buf
->start
;
861 cl
->buf
->file_pos
= 0;
864 /* reinit the subrequest's ngx_output_chain() context */
866 if (r
->request_body
&& r
->request_body
->temp_file
867 && r
!= r
->main
&& u
->output
.buf
)
869 u
->output
.free
= ngx_alloc_chain_link(r
->pool
);
870 if (u
->output
.free
== NULL
) {
874 u
->output
.free
->buf
= u
->output
.buf
;
875 u
->output
.free
->next
= NULL
;
877 u
->output
.buf
->pos
= u
->output
.buf
->start
;
878 u
->output
.buf
->last
= u
->output
.buf
->start
;
881 u
->output
.buf
= NULL
;
883 u
->output
.busy
= NULL
;
885 /* reinit u->buffer */
889 u
->buffer
.pos
= u
->buffer
.start
+ u
->cache
->ctx
.header_size
;
890 u
->buffer
.last
= u
->buffer
.pos
;
893 u
->buffer
.pos
= u
->buffer
.start
;
894 u
->buffer
.last
= u
->buffer
.start
;
898 u
->buffer
.pos
= u
->buffer
.start
;
899 u
->buffer
.last
= u
->buffer
.start
;
908 ngx_http_upstream_send_request(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
913 c
= u
->peer
.connection
;
915 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
916 "http upstream send request");
918 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
919 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
923 c
->log
->action
= "sending request to upstream";
925 rc
= ngx_output_chain(&u
->output
, u
->request_sent
? NULL
: u
->request_bufs
);
929 if (rc
== NGX_ERROR
) {
930 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
934 if (c
->write
->timer_set
) {
935 ngx_del_timer(c
->write
);
938 if (rc
== NGX_AGAIN
) {
939 ngx_add_timer(c
->write
, u
->conf
->send_timeout
);
941 if (ngx_handle_write_event(c
->write
, u
->conf
->send_lowat
) == NGX_ERROR
)
943 ngx_http_upstream_finalize_request(r
, u
,
944 NGX_HTTP_INTERNAL_SERVER_ERROR
);
953 if (c
->tcp_nopush
== NGX_TCP_NOPUSH_SET
) {
954 if (ngx_tcp_push(c
->fd
) == NGX_ERROR
) {
955 ngx_log_error(NGX_LOG_CRIT
, c
->log
, ngx_socket_errno
,
956 ngx_tcp_push_n
" failed");
957 ngx_http_upstream_finalize_request(r
, u
,
958 NGX_HTTP_INTERNAL_SERVER_ERROR
);
962 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
965 ngx_add_timer(c
->read
, u
->conf
->read_timeout
);
968 if (c
->read
->ready
) {
970 /* post aio operation */
974 * although we can post aio operation just in the end
975 * of ngx_http_upstream_connect() CHECK IT !!!
976 * it's better to do here because we postpone header buffer allocation
979 ngx_http_upstream_process_header(c
->read
);
984 c
->write
->handler
= ngx_http_upstream_dummy_handler
;
986 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
987 ngx_http_upstream_finalize_request(r
, u
,
988 NGX_HTTP_INTERNAL_SERVER_ERROR
);
995 ngx_http_upstream_send_request_handler(ngx_event_t
*wev
)
998 ngx_http_request_t
*r
;
999 ngx_http_upstream_t
*u
;
1005 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1006 "http upstream send request handler");
1008 if (wev
->timedout
) {
1009 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
1015 if (u
->ssl
&& c
->ssl
== NULL
) {
1016 ngx_http_upstream_ssl_init_connection(r
, u
, c
);
1022 if (u
->header_sent
) {
1023 wev
->handler
= ngx_http_upstream_dummy_handler
;
1025 (void) ngx_handle_write_event(wev
, 0);
1030 ngx_http_upstream_send_request(r
, u
);
1035 ngx_http_upstream_process_header(ngx_event_t
*rev
)
1039 ngx_str_t
*uri
, args
;
1040 ngx_uint_t i
, flags
;
1041 ngx_list_part_t
*part
;
1043 ngx_connection_t
*c
;
1044 ngx_http_request_t
*r
;
1045 ngx_http_upstream_t
*u
;
1046 ngx_http_err_page_t
*err_page
;
1047 ngx_http_core_loc_conf_t
*clcf
;
1048 ngx_http_upstream_header_t
*hh
;
1049 ngx_http_upstream_main_conf_t
*umcf
;
1055 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
1056 "http upstream process header");
1058 c
->log
->action
= "reading response header from upstream";
1060 if (rev
->timedout
) {
1061 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_TIMEOUT
);
1065 if (!u
->request_sent
&& ngx_http_upstream_test_connect(c
) != NGX_OK
) {
1066 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1070 if (u
->buffer
.start
== NULL
) {
1071 u
->buffer
.start
= ngx_palloc(r
->pool
, u
->conf
->buffer_size
);
1072 if (u
->buffer
.start
== NULL
) {
1073 ngx_http_upstream_finalize_request(r
, u
,
1074 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1078 u
->buffer
.pos
= u
->buffer
.start
;
1079 u
->buffer
.last
= u
->buffer
.start
;
1080 u
->buffer
.end
= u
->buffer
.start
+ u
->conf
->buffer_size
;
1081 u
->buffer
.temporary
= 1;
1083 u
->buffer
.tag
= u
->output
.tag
;
1085 if (ngx_list_init(&u
->headers_in
.headers
, r
->pool
, 8,
1086 sizeof(ngx_table_elt_t
))
1089 ngx_http_upstream_finalize_request(r
, u
,
1090 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1096 u
->buffer
.pos
+= u
->cache
->ctx
.header_size
;
1097 u
->buffer
.last
= u
->buffer
.pos
;
1102 n
= c
->recv(c
, u
->buffer
.last
, u
->buffer
.end
- u
->buffer
.last
);
1104 if (n
== NGX_AGAIN
) {
1106 ngx_add_timer(rev
, u
->read_timeout
);
1109 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1110 ngx_http_upstream_finalize_request(r
, u
,
1111 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1119 ngx_log_error(NGX_LOG_ERR
, rev
->log
, 0,
1120 "upstream prematurely closed connection");
1123 if (n
== NGX_ERROR
|| n
== 0) {
1124 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_ERROR
);
1128 u
->buffer
.last
+= n
;
1131 u
->valid_header_in
= 0;
1136 rc
= u
->process_header(r
);
1138 if (rc
== NGX_AGAIN
) {
1140 ngx_add_timer(rev
, u
->read_timeout
);
1143 if (u
->buffer
.pos
== u
->buffer
.end
) {
1144 ngx_log_error(NGX_LOG_ERR
, rev
->log
, 0,
1145 "upstream sent too big header");
1147 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1151 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1152 ngx_http_upstream_finalize_request(r
, u
,
1153 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1160 if (rc
== NGX_HTTP_UPSTREAM_INVALID_HEADER
) {
1161 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
);
1165 if (rc
== NGX_ERROR
) {
1166 ngx_http_upstream_finalize_request(r
, u
,
1167 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1173 if (u
->headers_in
.status_n
>= NGX_HTTP_BAD_REQUEST
1174 && r
->subrequest_in_memory
)
1176 u
->buffer
.last
= u
->buffer
.pos
;
1179 if (u
->headers_in
.status_n
== NGX_HTTP_INTERNAL_SERVER_ERROR
) {
1181 if (u
->peer
.tries
> 1
1182 && (u
->conf
->next_upstream
& NGX_HTTP_UPSTREAM_FT_HTTP_500
))
1184 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_HTTP_500
);
1188 #if (NGX_HTTP_CACHE)
1190 if (u
->peer
.tries
== 0
1192 && (u
->conf
->use_stale
& NGX_HTTP_UPSTREAM_FT_HTTP_500
))
1194 ngx_http_upstream_finalize_request(r
, u
,
1195 ngx_http_send_cached_response(r
));
1202 if (u
->headers_in
.status_n
== NGX_HTTP_NOT_FOUND
) {
1204 if (u
->peer
.tries
> 1
1205 && u
->conf
->next_upstream
& NGX_HTTP_UPSTREAM_FT_HTTP_404
)
1207 ngx_http_upstream_next(r
, u
, NGX_HTTP_UPSTREAM_FT_HTTP_404
);
1211 if (u
->conf
->intercept_404
) {
1212 ngx_http_upstream_finalize_request(r
, u
, NGX_HTTP_NOT_FOUND
);
1218 if (u
->headers_in
.status_n
>= NGX_HTTP_BAD_REQUEST
1219 && u
->conf
->intercept_errors
)
1221 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1223 if (clcf
->error_pages
) {
1225 err_page
= clcf
->error_pages
->elts
;
1226 for (i
= 0; i
< clcf
->error_pages
->nelts
; i
++) {
1227 if (err_page
[i
].status
== (ngx_int_t
) u
->headers_in
.status_n
) {
1229 if (u
->headers_in
.status_n
== NGX_HTTP_UNAUTHORIZED
) {
1231 r
->headers_out
.www_authenticate
=
1232 ngx_list_push(&r
->headers_out
.headers
);
1234 if (r
->headers_out
.www_authenticate
== NULL
) {
1235 ngx_http_upstream_finalize_request(r
, u
,
1236 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1240 *r
->headers_out
.www_authenticate
=
1241 *u
->headers_in
.www_authenticate
;
1244 ngx_http_upstream_finalize_request(r
, u
,
1245 u
->headers_in
.status_n
);
1252 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
1254 if (u
->headers_in
.x_accel_redirect
) {
1256 ngx_http_upstream_finalize_request(r
, u
, NGX_DECLINED
);
1258 part
= &u
->headers_in
.headers
.part
;
1261 for (i
= 0; /* void */; i
++) {
1263 if (i
>= part
->nelts
) {
1264 if (part
->next
== NULL
) {
1273 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1274 h
[i
].lowcase_key
, h
[i
].key
.len
);
1276 if (hh
&& hh
->redirect
) {
1277 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1278 ngx_http_finalize_request(r
,
1279 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1285 uri
= &u
->headers_in
.x_accel_redirect
->value
;
1290 if (ngx_http_parse_unsafe_uri(r
, uri
, &args
, &flags
) != NGX_OK
) {
1291 ngx_http_finalize_request(r
, NGX_HTTP_NOT_FOUND
);
1295 if (flags
& NGX_HTTP_ZERO_IN_URI
) {
1299 if (r
->method
!= NGX_HTTP_HEAD
) {
1300 r
->method
= NGX_HTTP_GET
;
1303 ngx_http_internal_redirect(r
, uri
, &args
);
1307 part
= &u
->headers_in
.headers
.part
;
1310 for (i
= 0; /* void */; i
++) {
1312 if (i
>= part
->nelts
) {
1313 if (part
->next
== NULL
) {
1322 if (ngx_hash_find(&u
->conf
->hide_headers_hash
, h
[i
].hash
,
1323 h
[i
].lowcase_key
, h
[i
].key
.len
))
1328 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
[i
].hash
,
1329 h
[i
].lowcase_key
, h
[i
].key
.len
);
1332 if (hh
->copy_handler(r
, &h
[i
], hh
->conf
) != NGX_OK
) {
1333 ngx_http_upstream_finalize_request(r
, u
,
1334 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1341 if (ngx_http_upstream_copy_header_line(r
, &h
[i
], 0) != NGX_OK
) {
1342 ngx_http_upstream_finalize_request(r
, u
,
1343 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1348 if (r
->headers_out
.server
&& r
->headers_out
.server
->value
.data
== NULL
) {
1349 r
->headers_out
.server
->hash
= 0;
1352 if (r
->headers_out
.date
&& r
->headers_out
.date
->value
.data
== NULL
) {
1353 r
->headers_out
.date
->hash
= 0;
1356 r
->headers_out
.status
= u
->headers_in
.status_n
;
1357 r
->headers_out
.status_line
= u
->headers_in
.status_line
;
1359 u
->headers_in
.content_length_n
= r
->headers_out
.content_length_n
;
1361 if (r
->headers_out
.content_length_n
!= -1) {
1362 u
->length
= (size_t) r
->headers_out
.content_length_n
;
1365 u
->length
= NGX_MAX_SIZE_T_VALUE
;
1368 if (!r
->subrequest_in_memory
) {
1369 ngx_http_upstream_send_response(r
, u
);
1373 /* subrequest content in memory */
1375 if (u
->input_filter
== NULL
) {
1376 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
1377 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
1378 u
->input_filter_ctx
= r
;
1381 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
1382 ngx_http_upstream_finalize_request(r
, u
,
1383 NGX_HTTP_INTERNAL_SERVER_ERROR
);
1387 if (u
->buffer
.last
- u
->buffer
.pos
>= (ssize_t
) u
->length
) {
1388 if (u
->input_filter(u
->input_filter_ctx
, 0) == NGX_ERROR
) {
1389 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1393 ngx_http_upstream_finalize_request(r
, u
, 0);
1397 rev
->handler
= ngx_http_upstream_process_body_in_memory
;
1399 ngx_http_upstream_process_body_in_memory(rev
);
1404 ngx_http_upstream_test_connect(ngx_connection_t
*c
)
1409 #if (NGX_HAVE_KQUEUE)
1411 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1412 if (c
->write
->pending_eof
) {
1413 c
->log
->action
= "connecting to upstream";
1414 (void) ngx_connection_error(c
, c
->write
->kq_errno
,
1415 "kevent() reported that connect() failed");
1426 * BSDs and Linux return 0 and set a pending error in err
1427 * Solaris returns -1 and sets errno
1430 if (getsockopt(c
->fd
, SOL_SOCKET
, SO_ERROR
, (void *) &err
, &len
)
1437 c
->log
->action
= "connecting to upstream";
1438 (void) ngx_connection_error(c
, err
, "connect() failed");
1448 ngx_http_upstream_process_body_in_memory(ngx_event_t
*rev
)
1453 ngx_connection_t
*c
;
1454 ngx_http_request_t
*r
;
1455 ngx_http_upstream_t
*u
;
1461 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1462 "http upstream process body on memory");
1464 if (rev
->timedout
) {
1465 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
1466 ngx_http_upstream_finalize_request(r
, u
, NGX_ETIMEDOUT
);
1474 size
= b
->end
- b
->last
;
1477 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
1478 "upstream buffer is too small to read repsonse");
1479 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1483 n
= c
->recv(c
, b
->last
, size
);
1485 if (n
== NGX_AGAIN
) {
1489 if (n
== 0 || n
== NGX_ERROR
) {
1490 ngx_http_upstream_finalize_request(r
, u
, n
);
1494 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
1495 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1504 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1505 ngx_http_upstream_finalize_request(r
, u
, NGX_ERROR
);
1510 ngx_add_timer(rev
, u
->conf
->read_timeout
);
1512 } else if (rev
->timer_set
) {
1519 ngx_http_upstream_send_response(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
1524 ngx_event_pipe_t
*p
;
1525 ngx_connection_t
*c
;
1526 ngx_pool_cleanup_t
*cl
;
1527 ngx_pool_cleanup_file_t
*clf
;
1528 ngx_http_core_loc_conf_t
*clcf
;
1530 rc
= ngx_http_send_header(r
);
1532 if (rc
== NGX_ERROR
|| rc
> NGX_OK
|| r
->post_action
|| r
->header_only
) {
1533 ngx_http_upstream_finalize_request(r
, u
, rc
);
1539 if (r
->request_body
&& r
->request_body
->temp_file
) {
1540 for (cl
= r
->pool
->cleanup
; cl
; cl
= cl
->next
) {
1541 if (cl
->handler
== ngx_pool_cleanup_file
) {
1544 if (clf
->fd
== r
->request_body
->temp_file
->file
.fd
) {
1547 r
->request_body
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
1556 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1558 if (!u
->buffering
) {
1560 if (u
->input_filter
== NULL
) {
1561 u
->input_filter_init
= ngx_http_upstream_non_buffered_filter_init
;
1562 u
->input_filter
= ngx_http_upstream_non_buffered_filter
;
1563 u
->input_filter_ctx
= r
;
1566 u
->peer
.connection
->read
->handler
=
1567 ngx_http_upstream_process_non_buffered_body
;
1568 r
->write_event_handler
=
1569 ngx_http_upstream_process_non_buffered_downstream
;
1573 if (u
->input_filter_init(u
->input_filter_ctx
) == NGX_ERROR
) {
1574 ngx_http_upstream_finalize_request(r
, u
, 0);
1578 if (clcf
->tcp_nodelay
&& c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
) {
1579 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
1583 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
1584 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
1586 ngx_connection_error(c
, ngx_socket_errno
,
1587 "setsockopt(TCP_NODELAY) failed");
1588 ngx_http_upstream_finalize_request(r
, u
, 0);
1592 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
1595 size
= u
->buffer
.last
- u
->buffer
.pos
;
1598 u
->buffer
.last
= u
->buffer
.pos
;
1600 if (u
->input_filter(u
->input_filter_ctx
, size
) == NGX_ERROR
) {
1601 ngx_http_upstream_finalize_request(r
, u
, 0);
1605 ngx_http_upstream_process_non_buffered_body(c
->write
);
1608 u
->buffer
.pos
= u
->buffer
.start
;
1609 u
->buffer
.last
= u
->buffer
.start
;
1611 if (ngx_http_send_special(r
, NGX_HTTP_FLUSH
) == NGX_ERROR
) {
1612 ngx_http_upstream_finalize_request(r
, u
, 0);
1616 if (u
->peer
.connection
->read
->ready
) {
1617 ngx_http_upstream_process_non_buffered_body(
1618 u
->peer
.connection
->read
);
1625 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
1629 if (u
->cache
&& u
->cache
->ctx
.file
.fd
!= NGX_INVALID_FILE
) {
1630 if (ngx_close_file(u
->cache
->ctx
.file
.fd
) == NGX_FILE_ERROR
) {
1631 ngx_log_error(NGX_LOG_ALERT
, c
->log
, ngx_errno
,
1632 ngx_close_file_n
" \"%s\" failed",
1633 u
->cache
->ctx
.file
.name
.data
);
1638 header
= (ngx_http_cache_header_t
*) u
->buffer
->start
;
1640 header
->expires
= u
->cache
->ctx
.expires
;
1641 header
->last_modified
= u
->cache
->ctx
.last_modified
;
1642 header
->date
= u
->cache
->ctx
.date
;
1643 header
->length
= r
->headers_out
.content_length_n
;
1644 u
->cache
->ctx
.length
= r
->headers_out
.content_length_n
;
1646 header
->key_len
= u
->cache
->ctx
.key0
.len
;
1647 ngx_memcpy(&header
->key
, u
->cache
->ctx
.key0
.data
, header
->key_len
);
1648 header
->key
[header
->key_len
] = LF
;
1655 p
->output_filter
= (ngx_event_pipe_output_filter_pt
) ngx_http_output_filter
;
1657 p
->tag
= u
->output
.tag
;
1658 p
->bufs
= u
->conf
->bufs
;
1659 p
->busy_size
= u
->conf
->busy_buffers_size
;
1660 p
->upstream
= u
->peer
.connection
;
1665 p
->cacheable
= u
->cacheable
|| u
->store
;
1667 p
->temp_file
= ngx_pcalloc(r
->pool
, sizeof(ngx_temp_file_t
));
1668 if (p
->temp_file
== NULL
) {
1669 ngx_http_upstream_finalize_request(r
, u
, 0);
1673 p
->temp_file
->file
.fd
= NGX_INVALID_FILE
;
1674 p
->temp_file
->file
.log
= c
->log
;
1675 p
->temp_file
->path
= u
->conf
->temp_path
;
1676 p
->temp_file
->pool
= r
->pool
;
1678 if (u
->cacheable
|| u
->store
) {
1679 p
->temp_file
->persistent
= 1;
1682 p
->temp_file
->log_level
= NGX_LOG_WARN
;
1683 p
->temp_file
->warn
= "an upstream response is buffered "
1684 "to a temporary file";
1687 p
->max_temp_file_size
= u
->conf
->max_temp_file_size
;
1688 p
->temp_file_write_size
= u
->conf
->temp_file_write_size
;
1690 p
->preread_bufs
= ngx_alloc_chain_link(r
->pool
);
1691 if (p
->preread_bufs
== NULL
) {
1692 ngx_http_upstream_finalize_request(r
, u
, 0);
1696 p
->preread_bufs
->buf
= &u
->buffer
;
1697 p
->preread_bufs
->next
= NULL
;
1698 u
->buffer
.recycled
= 1;
1700 p
->preread_size
= u
->buffer
.last
- u
->buffer
.pos
;
1704 p
->buf_to_file
= ngx_calloc_buf(r
->pool
);
1705 if (p
->buf_to_file
== NULL
) {
1706 ngx_http_upstream_finalize_request(r
, u
, 0);
1710 p
->buf_to_file
->pos
= u
->buffer
.start
;
1711 p
->buf_to_file
->last
= u
->buffer
.pos
;
1712 p
->buf_to_file
->temporary
= 1;
1715 if (ngx_event_flags
& NGX_USE_AIO_EVENT
) {
1716 /* the posted aio operation may currupt a shadow buffer */
1720 /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
1724 * event_pipe would do u->buffer.last += p->preread_size
1725 * as though these bytes were read
1727 u
->buffer
.last
= u
->buffer
.pos
;
1729 if (u
->conf
->cyclic_temp_file
) {
1732 * we need to disable the use of sendfile() if we use cyclic temp file
1733 * because the writing a new data may interfere with sendfile()
1734 * that uses the same kernel file pages (at least on FreeBSD)
1737 p
->cyclic_temp_file
= 1;
1741 p
->cyclic_temp_file
= 0;
1744 p
->read_timeout
= u
->conf
->read_timeout
;
1745 p
->send_timeout
= clcf
->send_timeout
;
1746 p
->send_lowat
= clcf
->send_lowat
;
1748 u
->peer
.connection
->read
->handler
= ngx_http_upstream_process_body
;
1749 r
->write_event_handler
= ngx_http_upstream_process_downstream
;
1751 ngx_http_upstream_process_body(u
->peer
.connection
->read
);
1756 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t
*r
)
1758 ngx_http_upstream_process_non_buffered_body(r
->connection
->write
);
1763 ngx_http_upstream_process_non_buffered_body(ngx_event_t
*ev
)
1769 ngx_uint_t do_write
;
1770 ngx_connection_t
*c
, *downstream
, *upstream
;
1771 ngx_http_request_t
*r
;
1772 ngx_http_upstream_t
*u
;
1773 ngx_http_core_loc_conf_t
*clcf
;
1780 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1781 "http upstream process non buffered downstream");
1782 c
->log
->action
= "sending to client";
1785 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1786 "http upstream process non buffered upstream");
1787 c
->log
->action
= "reading upstream";
1793 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
1796 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
1799 ngx_http_upstream_finalize_request(r
, u
, 0);
1803 downstream
= r
->connection
;
1804 upstream
= u
->peer
.connection
;
1808 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1810 do_write
= ev
->write
|| u
->length
== 0;
1816 if (u
->out_bufs
|| u
->busy_bufs
) {
1817 rc
= ngx_http_output_filter(r
, u
->out_bufs
);
1819 if (downstream
->destroyed
) {
1823 if (rc
== NGX_ERROR
) {
1824 ngx_http_upstream_finalize_request(r
, u
, 0);
1828 ngx_chain_update_chains(&u
->free_bufs
, &u
->busy_bufs
,
1829 &u
->out_bufs
, u
->output
.tag
);
1832 if (u
->busy_bufs
== NULL
) {
1835 || upstream
->read
->eof
1836 || upstream
->read
->error
)
1838 ngx_http_upstream_finalize_request(r
, u
, 0);
1847 size
= b
->end
- b
->last
;
1849 if (size
> u
->length
) {
1853 if (size
&& upstream
->read
->ready
) {
1855 n
= upstream
->recv(upstream
, b
->last
, size
);
1857 if (n
== NGX_AGAIN
) {
1862 if (u
->input_filter(u
->input_filter_ctx
, n
) == NGX_ERROR
) {
1863 ngx_http_upstream_finalize_request(r
, u
, 0);
1876 if (downstream
->data
== r
) {
1877 if (ngx_handle_write_event(downstream
->write
, clcf
->send_lowat
)
1880 ngx_http_upstream_finalize_request(r
, u
, 0);
1885 if (downstream
->write
->active
&& !downstream
->write
->ready
) {
1886 ngx_add_timer(downstream
->write
, clcf
->send_timeout
);
1888 } else if (downstream
->write
->timer_set
) {
1889 ngx_del_timer(downstream
->write
);
1892 if (ngx_handle_read_event(upstream
->read
, 0) == NGX_ERROR
) {
1893 ngx_http_upstream_finalize_request(r
, u
, 0);
1897 if (upstream
->read
->active
&& !upstream
->read
->ready
) {
1898 ngx_add_timer(upstream
->read
, u
->conf
->read_timeout
);
1900 } else if (upstream
->read
->timer_set
) {
1901 ngx_del_timer(upstream
->read
);
1907 ngx_http_upstream_non_buffered_filter_init(void *data
)
1914 ngx_http_upstream_non_buffered_filter(void *data
, ssize_t bytes
)
1916 ngx_http_request_t
*r
= data
;
1919 ngx_chain_t
*cl
, **ll
;
1920 ngx_http_upstream_t
*u
;
1924 for (cl
= u
->out_bufs
, ll
= &u
->out_bufs
; cl
; cl
= cl
->next
) {
1928 cl
= ngx_chain_get_free_buf(r
->pool
, &u
->free_bufs
);
1936 cl
->buf
->memory
= 1;
1940 cl
->buf
->pos
= b
->last
;
1942 cl
->buf
->last
= b
->last
;
1943 cl
->buf
->tag
= u
->output
.tag
;
1945 if (u
->length
== NGX_MAX_SIZE_T_VALUE
) {
1956 ngx_http_upstream_process_downstream(ngx_http_request_t
*r
)
1958 ngx_http_upstream_process_body(r
->connection
->write
);
1963 ngx_http_upstream_process_body(ngx_event_t
*ev
)
1965 ngx_temp_file_t
*tf
;
1966 ngx_event_pipe_t
*p
;
1967 ngx_connection_t
*c
, *downstream
;
1968 ngx_http_log_ctx_t
*ctx
;
1969 ngx_http_request_t
*r
;
1970 ngx_http_upstream_t
*u
;
1975 downstream
= r
->connection
;
1978 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1979 "http upstream process downstream");
1980 c
->log
->action
= "sending to client";
1983 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1984 "http upstream process upstream");
1985 c
->log
->action
= "reading upstream";
1988 ctx
->current_request
= r
;
2001 ngx_add_timer(ev
, p
->send_timeout
);
2003 if (ngx_handle_write_event(ev
, p
->send_lowat
) == NGX_ERROR
)
2005 ngx_http_upstream_finalize_request(r
, u
, 0);
2012 if (ngx_event_pipe(p
, ev
->write
) == NGX_ABORT
) {
2014 if (downstream
->destroyed
) {
2018 ngx_http_upstream_finalize_request(r
, u
, 0);
2023 p
->downstream_error
= 1;
2025 ngx_connection_error(c
, NGX_ETIMEDOUT
, "client timed out");
2029 p
->upstream_error
= 1;
2030 ngx_connection_error(c
, NGX_ETIMEDOUT
, "upstream timed out");
2034 if (ev
->write
&& ev
->delayed
) {
2035 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2036 "http downstream delayed");
2038 if (ngx_handle_write_event(ev
, p
->send_lowat
) == NGX_ERROR
) {
2045 if (ngx_event_pipe(p
, ev
->write
) == NGX_ABORT
) {
2047 if (downstream
->destroyed
) {
2051 ngx_http_upstream_finalize_request(r
, u
, 0);
2056 if (u
->peer
.connection
) {
2060 tf
= u
->pipe
->temp_file
;
2063 && u
->headers_in
.status_n
== NGX_HTTP_OK
2064 && (u
->headers_in
.content_length_n
== -1
2065 || (u
->headers_in
.content_length_n
== tf
->offset
)))
2067 ngx_http_upstream_store(r
, u
);
2069 } else if ((p
->upstream_error
2071 && u
->headers_in
.status_n
!= NGX_HTTP_OK
))
2072 && tf
->file
.fd
!= NGX_INVALID_FILE
)
2074 if (ngx_delete_file(tf
->file
.name
.data
) == NGX_FILE_ERROR
) {
2076 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, ngx_errno
,
2077 ngx_delete_file_n
" \"%s\" failed",
2078 u
->pipe
->temp_file
->file
.name
.data
);
2083 #if (NGX_HTTP_FILE_CACHE)
2085 if (p
->upstream_done
&& u
->cacheable
) {
2086 if (ngx_http_cache_update(r
) == NGX_ERROR
) {
2087 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
2088 ngx_http_upstream_finalize_request(r
, u
, 0);
2092 } else if (p
->upstream_eof
&& u
->cacheable
) {
2094 /* TODO: check length & update cache */
2096 if (ngx_http_cache_update(r
) == NGX_ERROR
) {
2097 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
2098 ngx_http_upstream_finalize_request(r
, u
, 0);
2105 if (p
->upstream_done
|| p
->upstream_eof
|| p
->upstream_error
) {
2106 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2107 "http upstream exit: %p", p
->out
);
2109 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
2111 ngx_http_upstream_finalize_request(r
, u
, 0);
2116 if (p
->downstream_error
) {
2117 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2118 "http upstream downstream error");
2120 if (!u
->cacheable
&& u
->peer
.connection
) {
2121 ngx_http_upstream_finalize_request(r
, u
, 0);
2128 ngx_http_upstream_store(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
)
2133 ngx_temp_file_t
*tf
;
2134 ngx_ext_rename_file_t ext
;
2136 tf
= u
->pipe
->temp_file
;
2138 if (tf
->file
.fd
== NGX_INVALID_FILE
) {
2140 /* create file for empty 200 response */
2142 tf
= ngx_pcalloc(r
->pool
, sizeof(ngx_temp_file_t
));
2147 tf
->file
.fd
= NGX_INVALID_FILE
;
2148 tf
->file
.log
= r
->connection
->log
;
2149 tf
->path
= u
->conf
->temp_path
;
2153 if (ngx_create_temp_file(&tf
->file
, tf
->path
, tf
->pool
,
2154 tf
->persistent
, tf
->clean
, tf
->access
)
2160 u
->pipe
->temp_file
= tf
;
2163 ext
.access
= u
->conf
->store_access
;
2165 ext
.create_path
= 1;
2166 ext
.delete_file
= 1;
2167 ext
.log
= r
->connection
->log
;
2169 if (u
->headers_in
.last_modified
) {
2171 lm
= ngx_http_parse_time(u
->headers_in
.last_modified
->value
.data
,
2172 u
->headers_in
.last_modified
->value
.len
);
2174 if (lm
!= NGX_ERROR
) {
2176 ext
.fd
= tf
->file
.fd
;
2180 if (u
->conf
->store_lengths
== NULL
) {
2182 ngx_http_map_uri_to_path(r
, &path
, &root
, 0);
2185 if (ngx_http_script_run(r
, &path
, u
->conf
->store_lengths
->elts
, 0,
2186 u
->conf
->store_values
->elts
)
2193 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2194 "upstream stores \"%s\" to \"%s\"",
2195 tf
->file
.name
.data
, path
.data
);
2197 (void) ngx_ext_rename_file(&tf
->file
.name
, &path
, &ext
);
2202 ngx_http_upstream_dummy_handler(ngx_event_t
*wev
)
2204 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
2205 "http upstream dummy handler");
2210 ngx_http_upstream_next(ngx_http_request_t
*r
, ngx_http_upstream_t
*u
,
2213 ngx_uint_t status
, state
;
2215 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2216 "http next upstream, %xi", ft_type
);
2219 ngx_http_busy_unlock(u
->conf
->busy_lock
, &u
->busy_lock
);
2222 if (ft_type
== NGX_HTTP_UPSTREAM_FT_HTTP_404
) {
2223 state
= NGX_PEER_NEXT
;
2225 state
= NGX_PEER_FAILED
;
2228 if (ft_type
!= NGX_HTTP_UPSTREAM_FT_NOLIVE
) {
2229 u
->peer
.free(&u
->peer
, u
->peer
.data
, state
);
2232 if (ft_type
== NGX_HTTP_UPSTREAM_FT_TIMEOUT
) {
2233 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, NGX_ETIMEDOUT
,
2234 "upstream timed out");
2237 if (u
->peer
.cached
&& ft_type
== NGX_HTTP_UPSTREAM_FT_ERROR
) {
2243 case NGX_HTTP_UPSTREAM_FT_TIMEOUT
:
2244 status
= NGX_HTTP_GATEWAY_TIME_OUT
;
2247 case NGX_HTTP_UPSTREAM_FT_HTTP_500
:
2248 status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
2251 case NGX_HTTP_UPSTREAM_FT_HTTP_404
:
2252 status
= NGX_HTTP_NOT_FOUND
;
2256 * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
2261 status
= NGX_HTTP_BAD_GATEWAY
;
2265 if (r
->connection
->error
) {
2266 ngx_http_upstream_finalize_request(r
, u
,
2267 NGX_HTTP_CLIENT_CLOSED_REQUEST
);
2272 u
->state
->status
= status
;
2274 if (u
->peer
.tries
== 0 || !(u
->conf
->next_upstream
& ft_type
)) {
2276 #if (NGX_HTTP_CACHE)
2278 if (u
->stale
&& (u
->conf
->use_stale
& ft_type
)) {
2279 ngx_http_upstream_finalize_request(r
, u
,
2280 ngx_http_send_cached_response(r
));
2286 ngx_http_upstream_finalize_request(r
, u
, status
);
2291 if (u
->peer
.connection
) {
2292 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2293 "close http upstream connection: %d",
2294 u
->peer
.connection
->fd
);
2297 if (u
->peer
.connection
->ssl
) {
2298 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
2299 u
->peer
.connection
->ssl
->no_send_shutdown
= 1;
2301 (void) ngx_ssl_shutdown(u
->peer
.connection
);
2305 ngx_close_connection(u
->peer
.connection
);
2309 if (u
->conf
->busy_lock
&& !u
->busy_locked
) {
2310 ngx_http_upstream_busy_lock(p
);
2315 ngx_http_upstream_connect(r
, u
);
2320 ngx_http_upstream_cleanup(void *data
)
2322 ngx_http_request_t
*r
= data
;
2324 ngx_http_upstream_t
*u
;
2326 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2327 "cleanup http upstream request: \"%V\"", &r
->uri
);
2331 if (u
->resolved
&& u
->resolved
->ctx
) {
2332 ngx_resolve_name_done(u
->resolved
->ctx
);
2335 ngx_http_upstream_finalize_request(r
, u
, NGX_DONE
);
2340 ngx_http_upstream_finalize_request(ngx_http_request_t
*r
,
2341 ngx_http_upstream_t
*u
, ngx_int_t rc
)
2345 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2346 "finalize http upstream request: %i", rc
);
2350 if (u
->state
&& u
->state
->response_sec
) {
2351 tp
= ngx_timeofday();
2352 u
->state
->response_sec
= tp
->sec
- u
->state
->response_sec
;
2353 u
->state
->response_msec
= tp
->msec
- u
->state
->response_msec
;
2356 u
->finalize_request(r
, rc
);
2359 u
->peer
.free(&u
->peer
, u
->peer
.data
, 0);
2362 if (u
->peer
.connection
) {
2366 /* TODO: do not shutdown persistent connection */
2368 if (u
->peer
.connection
->ssl
) {
2371 * We send the "close notify" shutdown alert to the upstream only
2372 * and do not wait its "close notify" shutdown alert.
2373 * It is acceptable according to the TLS standard.
2376 u
->peer
.connection
->ssl
->no_wait_shutdown
= 1;
2378 (void) ngx_ssl_shutdown(u
->peer
.connection
);
2382 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2383 "close http upstream connection: %d",
2384 u
->peer
.connection
->fd
);
2386 ngx_close_connection(u
->peer
.connection
);
2389 u
->peer
.connection
= NULL
;
2391 if (u
->header_sent
&& (rc
== NGX_ERROR
|| rc
>= NGX_HTTP_SPECIAL_RESPONSE
))
2396 if (u
->pipe
&& u
->pipe
->temp_file
) {
2397 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2398 "http upstream temp fd: %d",
2399 u
->pipe
->temp_file
->file
.fd
);
2404 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2405 "http upstream cache fd: %d",
2406 u
->cache
->ctx
.file
.fd
);
2410 if (rc
== NGX_DECLINED
) {
2414 r
->connection
->log
->action
= "sending to client";
2418 if (!r
->post_action
) {
2419 rc
= ngx_http_send_special(r
, NGX_HTTP_LAST
);
2429 ngx_http_finalize_request(r
, rc
);
2434 ngx_http_upstream_process_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2437 ngx_table_elt_t
**ph
;
2439 ph
= (ngx_table_elt_t
**) ((char *) &r
->upstream
->headers_in
+ offset
);
2450 ngx_http_upstream_process_multi_header_lines(ngx_http_request_t
*r
,
2451 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2454 ngx_table_elt_t
**ph
;
2456 pa
= (ngx_array_t
*) ((char *) &r
->upstream
->headers_in
+ offset
);
2458 if (pa
->elts
== NULL
) {
2459 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
2465 ph
= ngx_array_push(pa
);
2477 ngx_http_upstream_ignore_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2485 ngx_http_upstream_process_limit_rate(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2490 r
->upstream
->headers_in
.x_accel_limit_rate
= h
;
2492 n
= ngx_atoi(h
->value
.data
, h
->value
.len
);
2494 if (n
!= NGX_ERROR
) {
2495 r
->limit_rate
= (size_t) n
;
2503 ngx_http_upstream_process_buffering(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2508 if (r
->upstream
->conf
->change_buffering
) {
2510 if (h
->value
.len
== 2) {
2511 c0
= ngx_tolower(h
->value
.data
[0]);
2512 c1
= ngx_tolower(h
->value
.data
[1]);
2514 if (c0
== 'n' && c1
== 'o') {
2515 r
->upstream
->buffering
= 0;
2518 } else if (h
->value
.len
== 3) {
2519 c0
= ngx_tolower(h
->value
.data
[0]);
2520 c1
= ngx_tolower(h
->value
.data
[1]);
2521 c2
= ngx_tolower(h
->value
.data
[2]);
2523 if (c0
== 'y' && c1
== 'e' && c2
== 's') {
2524 r
->upstream
->buffering
= 1;
2534 ngx_http_upstream_process_charset(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2537 r
->headers_out
.override_charset
= &h
->value
;
2544 ngx_http_upstream_copy_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2547 ngx_table_elt_t
*ho
, **ph
;
2549 ho
= ngx_list_push(&r
->headers_out
.headers
);
2557 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_out
+ offset
);
2566 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t
*r
,
2567 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2570 ngx_table_elt_t
*ho
, **ph
;
2572 pa
= (ngx_array_t
*) ((char *) &r
->headers_out
+ offset
);
2574 if (pa
->elts
== NULL
) {
2575 if (ngx_array_init(pa
, r
->pool
, 2, sizeof(ngx_table_elt_t
*)) != NGX_OK
)
2581 ph
= ngx_array_push(pa
);
2586 ho
= ngx_list_push(&r
->headers_out
.headers
);
2599 ngx_http_upstream_copy_content_type(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2604 r
->headers_out
.content_type_len
= h
->value
.len
;
2605 r
->headers_out
.content_type
= h
->value
;
2607 for (p
= h
->value
.data
; *p
; p
++) {
2615 while (*++p
== ' ') { /* void */ }
2621 if (ngx_strncasecmp(p
, (u_char
*) "charset=", 8) != 0) {
2627 r
->headers_out
.content_type_len
= last
- h
->value
.data
;
2629 r
->headers_out
.charset
.len
= h
->value
.data
+ h
->value
.len
- p
;
2630 r
->headers_out
.charset
.data
= p
;
2640 ngx_http_upstream_copy_content_length(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2643 ngx_table_elt_t
*ho
;
2645 ho
= ngx_list_push(&r
->headers_out
.headers
);
2652 r
->headers_out
.content_length
= ho
;
2653 r
->headers_out
.content_length_n
= ngx_atoof(h
->value
.data
, h
->value
.len
);
2660 ngx_http_upstream_rewrite_location(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2664 ngx_table_elt_t
*ho
;
2666 ho
= ngx_list_push(&r
->headers_out
.headers
);
2673 if (r
->upstream
->rewrite_redirect
) {
2674 rc
= r
->upstream
->rewrite_redirect(r
, ho
, 0);
2676 if (rc
== NGX_DECLINED
) {
2681 r
->headers_out
.location
= ho
;
2683 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2684 "rewritten location: \"%V\"", &ho
->value
);
2690 if (ho
->value
.data
[0] != '/') {
2691 r
->headers_out
.location
= ho
;
2695 * we do not set r->headers_out.location here to avoid the handling
2696 * the local redirects without a host name by ngx_http_header_filter()
2704 ngx_http_upstream_rewrite_refresh(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
2709 ngx_table_elt_t
*ho
;
2711 ho
= ngx_list_push(&r
->headers_out
.headers
);
2718 if (r
->upstream
->rewrite_redirect
) {
2720 p
= ngx_strcasestrn(ho
->value
.data
, "url=", 4 - 1);
2723 rc
= r
->upstream
->rewrite_redirect(r
, ho
, p
+ 4 - ho
->value
.data
);
2729 if (rc
== NGX_DECLINED
) {
2734 r
->headers_out
.refresh
= ho
;
2736 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2737 "rewritten refresh: \"%V\"", &ho
->value
);
2743 r
->headers_out
.refresh
= ho
;
2752 ngx_http_upstream_copy_content_encoding(ngx_http_request_t
*r
,
2753 ngx_table_elt_t
*h
, ngx_uint_t offset
)
2755 ngx_table_elt_t
*ho
;
2757 ho
= ngx_list_push(&r
->headers_out
.headers
);
2764 r
->headers_out
.content_encoding
= ho
;
2773 ngx_http_upstream_add_variables(ngx_conf_t
*cf
)
2775 ngx_http_variable_t
*var
, *v
;
2777 for (v
= ngx_http_upstream_vars
; v
->name
.len
; v
++) {
2778 var
= ngx_http_add_variable(cf
, &v
->name
, v
->flags
);
2783 var
->get_handler
= v
->get_handler
;
2784 var
->data
= v
->data
;
2792 ngx_http_upstream_addr_variable(ngx_http_request_t
*r
,
2793 ngx_http_variable_value_t
*v
, uintptr_t data
)
2798 ngx_http_upstream_state_t
*state
;
2801 v
->no_cacheable
= 0;
2804 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2810 state
= r
->upstream_states
->elts
;
2812 for (i
= 0; i
< r
->upstream_states
->nelts
; i
++) {
2813 if (state
[i
].peer
) {
2814 len
+= state
[i
].peer
->len
+ 2;
2821 p
= ngx_pnalloc(r
->pool
, len
);
2831 if (state
[i
].peer
) {
2832 p
= ngx_cpymem(p
, state
[i
].peer
->data
, state
[i
].peer
->len
);
2835 if (++i
== r
->upstream_states
->nelts
) {
2839 if (state
[i
].peer
) {
2848 if (++i
== r
->upstream_states
->nelts
) {
2856 v
->len
= p
- v
->data
;
2863 ngx_http_upstream_status_variable(ngx_http_request_t
*r
,
2864 ngx_http_variable_value_t
*v
, uintptr_t data
)
2869 ngx_http_upstream_state_t
*state
;
2872 v
->no_cacheable
= 0;
2875 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2880 len
= r
->upstream_states
->nelts
* (3 + 2);
2882 p
= ngx_pnalloc(r
->pool
, len
);
2890 state
= r
->upstream_states
->elts
;
2893 if (state
[i
].status
) {
2894 p
= ngx_sprintf(p
, "%ui", state
[i
].status
);
2900 if (++i
== r
->upstream_states
->nelts
) {
2904 if (state
[i
].peer
) {
2913 if (++i
== r
->upstream_states
->nelts
) {
2921 v
->len
= p
- v
->data
;
2928 ngx_http_upstream_response_time_variable(ngx_http_request_t
*r
,
2929 ngx_http_variable_value_t
*v
, uintptr_t data
)
2935 ngx_http_upstream_state_t
*state
;
2938 v
->no_cacheable
= 0;
2941 if (r
->upstream_states
== NULL
|| r
->upstream_states
->nelts
== 0) {
2946 len
= r
->upstream_states
->nelts
* (NGX_TIME_T_LEN
+ 4 + 2);
2948 p
= ngx_pnalloc(r
->pool
, len
);
2956 state
= r
->upstream_states
->elts
;
2959 if (state
[i
].status
) {
2960 ms
= (ngx_msec_int_t
)
2961 (state
[i
].response_sec
* 1000 + state
[i
].response_msec
);
2962 ms
= (ms
>= 0) ? ms
: 0;
2963 p
= ngx_sprintf(p
, "%d.%03d", ms
/ 1000, ms
% 1000);
2969 if (++i
== r
->upstream_states
->nelts
) {
2973 if (state
[i
].peer
) {
2982 if (++i
== r
->upstream_states
->nelts
) {
2990 v
->len
= p
- v
->data
;
2997 ngx_http_upstream_header_variable(ngx_http_request_t
*r
,
2998 ngx_http_variable_value_t
*v
, uintptr_t data
)
3000 if (r
->upstream
== NULL
) {
3005 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
3006 &r
->upstream
->headers_in
.headers
.part
,
3007 sizeof("upstream_http_") - 1);
3012 ngx_http_upstream(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *dummy
)
3020 ngx_http_module_t
*module
;
3021 ngx_http_conf_ctx_t
*ctx
, *http_ctx
;
3022 ngx_http_upstream_srv_conf_t
*uscf
;
3024 ngx_memzero(&u
, sizeof(ngx_url_t
));
3026 value
= cf
->args
->elts
;
3030 uscf
= ngx_http_upstream_add(cf
, &u
, NGX_HTTP_UPSTREAM_CREATE
3031 |NGX_HTTP_UPSTREAM_WEIGHT
3032 |NGX_HTTP_UPSTREAM_MAX_FAILS
3033 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
3034 |NGX_HTTP_UPSTREAM_DOWN
3035 |NGX_HTTP_UPSTREAM_BACKUP
);
3037 return NGX_CONF_ERROR
;
3041 ctx
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_conf_ctx_t
));
3043 return NGX_CONF_ERROR
;
3047 ctx
->main_conf
= http_ctx
->main_conf
;
3049 /* the upstream{}'s srv_conf */
3051 ctx
->srv_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
3052 if (ctx
->srv_conf
== NULL
) {
3053 return NGX_CONF_ERROR
;
3056 ctx
->srv_conf
[ngx_http_upstream_module
.ctx_index
] = uscf
;
3058 uscf
->srv_conf
= ctx
->srv_conf
;
3061 /* the upstream{}'s loc_conf */
3063 ctx
->loc_conf
= ngx_pcalloc(cf
->pool
, sizeof(void *) * ngx_http_max_module
);
3064 if (ctx
->loc_conf
== NULL
) {
3065 return NGX_CONF_ERROR
;
3068 for (m
= 0; ngx_modules
[m
]; m
++) {
3069 if (ngx_modules
[m
]->type
!= NGX_HTTP_MODULE
) {
3073 module
= ngx_modules
[m
]->ctx
;
3075 if (module
->create_srv_conf
) {
3076 mconf
= module
->create_srv_conf(cf
);
3077 if (mconf
== NULL
) {
3078 return NGX_CONF_ERROR
;
3081 ctx
->srv_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
3084 if (module
->create_loc_conf
) {
3085 mconf
= module
->create_loc_conf(cf
);
3086 if (mconf
== NULL
) {
3087 return NGX_CONF_ERROR
;
3090 ctx
->loc_conf
[ngx_modules
[m
]->ctx_index
] = mconf
;
3095 /* parse inside upstream{} */
3099 cf
->cmd_type
= NGX_HTTP_UPS_CONF
;
3101 rv
= ngx_conf_parse(cf
, NULL
);
3105 if (rv
!= NGX_CONF_OK
) {
3109 if (uscf
->servers
== NULL
) {
3110 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3111 "no servers are inside upstream");
3112 return NGX_CONF_ERROR
;
3120 ngx_http_upstream_server(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
3122 ngx_http_upstream_srv_conf_t
*uscf
= conf
;
3124 time_t fail_timeout
;
3125 ngx_str_t
*value
, s
;
3127 ngx_int_t weight
, max_fails
;
3129 ngx_http_upstream_server_t
*us
;
3131 if (uscf
->servers
== NULL
) {
3132 uscf
->servers
= ngx_array_create(cf
->pool
, 4,
3133 sizeof(ngx_http_upstream_server_t
));
3134 if (uscf
->servers
== NULL
) {
3135 return NGX_CONF_ERROR
;
3139 us
= ngx_array_push(uscf
->servers
);
3141 return NGX_CONF_ERROR
;
3144 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
3146 value
= cf
->args
->elts
;
3148 ngx_memzero(&u
, sizeof(ngx_url_t
));
3151 u
.default_port
= 80;
3153 if (ngx_parse_url(cf
->pool
, &u
) != NGX_OK
) {
3155 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3156 "%s in upstream \"%V\"", u
.err
, &u
.url
);
3159 return NGX_CONF_ERROR
;
3166 for (i
= 2; i
< cf
->args
->nelts
; i
++) {
3168 if (ngx_strncmp(value
[i
].data
, "weight=", 7) == 0) {
3170 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_WEIGHT
)) {
3174 weight
= ngx_atoi(&value
[i
].data
[7], value
[i
].len
- 7);
3176 if (weight
== NGX_ERROR
|| weight
== 0) {
3183 if (ngx_strncmp(value
[i
].data
, "max_fails=", 10) == 0) {
3185 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_MAX_FAILS
)) {
3189 max_fails
= ngx_atoi(&value
[i
].data
[10], value
[i
].len
- 10);
3191 if (max_fails
== NGX_ERROR
) {
3198 if (ngx_strncmp(value
[i
].data
, "fail_timeout=", 13) == 0) {
3200 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
)) {
3204 s
.len
= value
[i
].len
- 13;
3205 s
.data
= &value
[i
].data
[13];
3207 fail_timeout
= ngx_parse_time(&s
, 1);
3209 if (fail_timeout
== NGX_ERROR
) {
3216 if (ngx_strncmp(value
[i
].data
, "backup", 6) == 0) {
3218 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_BACKUP
)) {
3227 if (ngx_strncmp(value
[i
].data
, "down", 4) == 0) {
3229 if (!(uscf
->flags
& NGX_HTTP_UPSTREAM_DOWN
)) {
3241 us
->addrs
= u
.addrs
;
3242 us
->naddrs
= u
.naddrs
;
3243 us
->weight
= weight
;
3244 us
->max_fails
= max_fails
;
3245 us
->fail_timeout
= fail_timeout
;
3251 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3252 "invalid parameter \"%V\"", &value
[i
]);
3254 return NGX_CONF_ERROR
;
3258 ngx_http_upstream_srv_conf_t
*
3259 ngx_http_upstream_add(ngx_conf_t
*cf
, ngx_url_t
*u
, ngx_uint_t flags
)
3262 ngx_http_upstream_server_t
*us
;
3263 ngx_http_upstream_srv_conf_t
*uscf
, **uscfp
;
3264 ngx_http_upstream_main_conf_t
*umcf
;
3266 if (!(flags
& NGX_HTTP_UPSTREAM_CREATE
)) {
3268 if (ngx_parse_url(cf
->pool
, u
) != NGX_OK
) {
3270 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3271 "%s in upstream \"%V\"", u
->err
, &u
->url
);
3278 umcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_upstream_module
);
3280 uscfp
= umcf
->upstreams
.elts
;
3282 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
3284 if (uscfp
[i
]->host
.len
!= u
->host
.len
3285 || ngx_strncasecmp(uscfp
[i
]->host
.data
, u
->host
.data
, u
->host
.len
)
3291 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
)
3292 && (uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
))
3294 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3295 "duplicate upstream \"%V\"", &u
->host
);
3299 if ((uscfp
[i
]->flags
& NGX_HTTP_UPSTREAM_CREATE
) && u
->port
) {
3300 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
3301 "upstream \"%V\" may not have port %d",
3306 if ((flags
& NGX_HTTP_UPSTREAM_CREATE
) && uscfp
[i
]->port
) {
3307 ngx_log_error(NGX_LOG_WARN
, cf
->log
, 0,
3308 "upstream \"%V\" may not have port %d in %s:%ui",
3309 &u
->host
, uscfp
[i
]->port
,
3310 uscfp
[i
]->file_name
, uscfp
[i
]->line
);
3314 if (uscfp
[i
]->port
!= u
->port
) {
3318 if (uscfp
[i
]->default_port
&& u
->default_port
3319 && uscfp
[i
]->default_port
!= u
->default_port
)
3327 uscf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_srv_conf_t
));
3332 uscf
->flags
= flags
;
3333 uscf
->host
= u
->host
;
3334 uscf
->file_name
= cf
->conf_file
->file
.name
.data
;
3335 uscf
->line
= cf
->conf_file
->line
;
3336 uscf
->port
= u
->port
;
3337 uscf
->default_port
= u
->default_port
;
3339 if (u
->naddrs
== 1) {
3340 uscf
->servers
= ngx_array_create(cf
->pool
, 1,
3341 sizeof(ngx_http_upstream_server_t
));
3342 if (uscf
->servers
== NULL
) {
3343 return NGX_CONF_ERROR
;
3346 us
= ngx_array_push(uscf
->servers
);
3348 return NGX_CONF_ERROR
;
3351 ngx_memzero(us
, sizeof(ngx_http_upstream_server_t
));
3353 us
->addrs
= u
->addrs
;
3354 us
->naddrs
= u
->naddrs
;
3357 uscfp
= ngx_array_push(&umcf
->upstreams
);
3358 if (uscfp
== NULL
) {
3369 ngx_http_upstream_hide_headers_hash(ngx_conf_t
*cf
,
3370 ngx_http_upstream_conf_t
*conf
, ngx_http_upstream_conf_t
*prev
,
3371 ngx_str_t
*default_hide_headers
, ngx_hash_init_t
*hash
)
3375 ngx_array_t hide_headers
;
3378 if (conf
->hide_headers
== NGX_CONF_UNSET_PTR
3379 && conf
->pass_headers
== NGX_CONF_UNSET_PTR
)
3381 conf
->hide_headers_hash
= prev
->hide_headers_hash
;
3383 if (conf
->hide_headers_hash
.buckets
) {
3387 conf
->hide_headers
= prev
->hide_headers
;
3388 conf
->pass_headers
= prev
->pass_headers
;
3391 if (conf
->hide_headers
== NGX_CONF_UNSET_PTR
) {
3392 conf
->hide_headers
= prev
->hide_headers
;
3395 if (conf
->pass_headers
== NGX_CONF_UNSET_PTR
) {
3396 conf
->pass_headers
= prev
->pass_headers
;
3400 if (ngx_array_init(&hide_headers
, cf
->temp_pool
, 4, sizeof(ngx_hash_key_t
))
3406 for (h
= default_hide_headers
; h
->len
; h
++) {
3407 hk
= ngx_array_push(&hide_headers
);
3413 hk
->key_hash
= ngx_hash_key_lc(h
->data
, h
->len
);
3414 hk
->value
= (void *) 1;
3417 if (conf
->hide_headers
!= NGX_CONF_UNSET_PTR
) {
3419 h
= conf
->hide_headers
->elts
;
3421 for (i
= 0; i
< conf
->hide_headers
->nelts
; i
++) {
3423 hk
= hide_headers
.elts
;
3425 for (j
= 0; j
< hide_headers
.nelts
; j
++) {
3426 if (ngx_strcasecmp(h
[i
].data
, hk
[j
].key
.data
) == 0) {
3431 hk
= ngx_array_push(&hide_headers
);
3437 hk
->key_hash
= ngx_hash_key_lc(h
[i
].data
, h
[i
].len
);
3438 hk
->value
= (void *) 1;
3446 if (conf
->pass_headers
!= NGX_CONF_UNSET_PTR
) {
3448 h
= conf
->pass_headers
->elts
;
3449 hk
= hide_headers
.elts
;
3451 for (i
= 0; i
< conf
->pass_headers
->nelts
; i
++) {
3452 for (j
= 0; j
< hide_headers
.nelts
; j
++) {
3454 if (hk
[j
].key
.data
== NULL
) {
3458 if (ngx_strcasecmp(h
[i
].data
, hk
[j
].key
.data
) == 0) {
3459 hk
[j
].key
.data
= NULL
;
3466 hash
->hash
= &conf
->hide_headers_hash
;
3467 hash
->key
= ngx_hash_key_lc
;
3468 hash
->pool
= cf
->pool
;
3469 hash
->temp_pool
= NULL
;
3471 return ngx_hash_init(hash
, hide_headers
.elts
, hide_headers
.nelts
);
3476 ngx_http_upstream_create_main_conf(ngx_conf_t
*cf
)
3478 ngx_http_upstream_main_conf_t
*umcf
;
3480 umcf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_upstream_main_conf_t
));
3485 if (ngx_array_init(&umcf
->upstreams
, cf
->pool
, 4,
3486 sizeof(ngx_http_upstream_srv_conf_t
*))
3489 return NGX_CONF_ERROR
;
3497 ngx_http_upstream_init_main_conf(ngx_conf_t
*cf
, void *conf
)
3499 ngx_http_upstream_main_conf_t
*umcf
= conf
;
3502 ngx_array_t headers_in
;
3504 ngx_hash_init_t hash
;
3505 ngx_http_upstream_init_pt init
;
3506 ngx_http_upstream_header_t
*header
;
3507 ngx_http_upstream_srv_conf_t
**uscfp
;
3509 uscfp
= umcf
->upstreams
.elts
;
3511 for (i
= 0; i
< umcf
->upstreams
.nelts
; i
++) {
3513 init
= uscfp
[i
]->peer
.init_upstream
? uscfp
[i
]->peer
.init_upstream
:
3514 ngx_http_upstream_init_round_robin
;
3516 if (init(cf
, uscfp
[i
]) != NGX_OK
) {
3517 return NGX_CONF_ERROR
;
3522 /* upstream_headers_in_hash */
3524 if (ngx_array_init(&headers_in
, cf
->temp_pool
, 32, sizeof(ngx_hash_key_t
))
3527 return NGX_CONF_ERROR
;
3530 for (header
= ngx_http_upstream_headers_in
; header
->name
.len
; header
++) {
3531 hk
= ngx_array_push(&headers_in
);
3533 return NGX_CONF_ERROR
;
3536 hk
->key
= header
->name
;
3537 hk
->key_hash
= ngx_hash_key_lc(header
->name
.data
, header
->name
.len
);
3541 hash
.hash
= &umcf
->headers_in_hash
;
3542 hash
.key
= ngx_hash_key_lc
;
3543 hash
.max_size
= 512;
3544 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
3545 hash
.name
= "upstream_headers_in_hash";
3546 hash
.pool
= cf
->pool
;
3547 hash
.temp_pool
= NULL
;
3549 if (ngx_hash_init(&hash
, headers_in
.elts
, headers_in
.nelts
) != NGX_OK
) {
3550 return NGX_CONF_ERROR
;