Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_upstream.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 #if (NGX_HTTP_CACHE)
14 static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
16 static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
18 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
19  ngx_http_variable_value_t *v, uintptr_t data);
20 #endif
21 
22 static void ngx_http_upstream_init_request(ngx_http_request_t *r);
23 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
24 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
25 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
26 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
27  ngx_event_t *ev);
28 static void ngx_http_upstream_connect(ngx_http_request_t *r,
30 static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
32 static void ngx_http_upstream_send_request(ngx_http_request_t *r,
34 static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
36 static void ngx_http_upstream_process_header(ngx_http_request_t *r,
38 static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
40 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
42 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
43 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
45 static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
47 static void ngx_http_upstream_send_response(ngx_http_request_t *r,
49 static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
51 static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
52 static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
53 static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
55 static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
57 static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
58  ngx_uint_t from_upstream, ngx_uint_t do_write);
59 static void
60  ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
61 static void
62  ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
64 static void
65  ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
66  ngx_uint_t do_write);
67 static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
68 static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
69  ssize_t bytes);
70 static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
71 static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
73 static void ngx_http_upstream_process_request(ngx_http_request_t *r);
74 static void ngx_http_upstream_store(ngx_http_request_t *r,
76 static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
78 static void ngx_http_upstream_next(ngx_http_request_t *r,
79  ngx_http_upstream_t *u, ngx_uint_t ft_type);
80 static void ngx_http_upstream_cleanup(void *data);
81 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
83 
84 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
85  ngx_table_elt_t *h, ngx_uint_t offset);
86 static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
87  ngx_table_elt_t *h, ngx_uint_t offset);
88 static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
89  ngx_table_elt_t *h, ngx_uint_t offset);
90 static ngx_int_t
91  ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
92  ngx_table_elt_t *h, ngx_uint_t offset);
93 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
94  ngx_table_elt_t *h, ngx_uint_t offset);
95 static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
96  ngx_table_elt_t *h, ngx_uint_t offset);
97 static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
98  ngx_table_elt_t *h, ngx_uint_t offset);
99 static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
100  ngx_table_elt_t *h, ngx_uint_t offset);
101 static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
102  ngx_table_elt_t *h, ngx_uint_t offset);
103 static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
104  ngx_table_elt_t *h, ngx_uint_t offset);
105 static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
106  ngx_table_elt_t *h, ngx_uint_t offset);
107 static ngx_int_t
108  ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
109  ngx_table_elt_t *h, ngx_uint_t offset);
110 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
111  ngx_table_elt_t *h, ngx_uint_t offset);
112 static ngx_int_t
113  ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
114  ngx_table_elt_t *h, ngx_uint_t offset);
115 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
116  ngx_table_elt_t *h, ngx_uint_t offset);
117 static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
118  ngx_table_elt_t *h, ngx_uint_t offset);
119 static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
120  ngx_table_elt_t *h, ngx_uint_t offset);
121 static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
122  ngx_table_elt_t *h, ngx_uint_t offset);
123 static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
124  ngx_table_elt_t *h, ngx_uint_t offset);
125 static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
126  ngx_table_elt_t *h, ngx_uint_t offset);
127 
128 #if (NGX_HTTP_GZIP)
129 static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
130  ngx_table_elt_t *h, ngx_uint_t offset);
131 #endif
132 
133 static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
134 static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
135  ngx_http_variable_value_t *v, uintptr_t data);
136 static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
137  ngx_http_variable_value_t *v, uintptr_t data);
138 static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
139  ngx_http_variable_value_t *v, uintptr_t data);
140 static ngx_int_t ngx_http_upstream_response_length_variable(
141  ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
142 
143 static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
144 static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
145  void *conf);
146 
147 static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
149 
150 static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
151 static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
152 
153 #if (NGX_HTTP_SSL)
154 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
156 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
157 #endif
158 
159 
161 
162  { ngx_string("Status"),
163  ngx_http_upstream_process_header_line,
164  offsetof(ngx_http_upstream_headers_in_t, status),
165  ngx_http_upstream_copy_header_line, 0, 0 },
166 
167  { ngx_string("Content-Type"),
168  ngx_http_upstream_process_header_line,
169  offsetof(ngx_http_upstream_headers_in_t, content_type),
170  ngx_http_upstream_copy_content_type, 0, 1 },
171 
172  { ngx_string("Content-Length"),
173  ngx_http_upstream_process_content_length,
174  offsetof(ngx_http_upstream_headers_in_t, content_length),
175  ngx_http_upstream_ignore_header_line, 0, 0 },
176 
177  { ngx_string("Date"),
178  ngx_http_upstream_process_header_line,
180  ngx_http_upstream_copy_header_line,
181  offsetof(ngx_http_headers_out_t, date), 0 },
182 
183  { ngx_string("Last-Modified"),
184  ngx_http_upstream_process_header_line,
185  offsetof(ngx_http_upstream_headers_in_t, last_modified),
186  ngx_http_upstream_copy_last_modified, 0, 0 },
187 
188  { ngx_string("ETag"),
189  ngx_http_upstream_process_header_line,
190  offsetof(ngx_http_upstream_headers_in_t, etag),
191  ngx_http_upstream_copy_header_line,
192  offsetof(ngx_http_headers_out_t, etag), 0 },
193 
194  { ngx_string("Server"),
195  ngx_http_upstream_process_header_line,
196  offsetof(ngx_http_upstream_headers_in_t, server),
197  ngx_http_upstream_copy_header_line,
198  offsetof(ngx_http_headers_out_t, server), 0 },
199 
200  { ngx_string("WWW-Authenticate"),
201  ngx_http_upstream_process_header_line,
202  offsetof(ngx_http_upstream_headers_in_t, www_authenticate),
203  ngx_http_upstream_copy_header_line, 0, 0 },
204 
205  { ngx_string("Location"),
206  ngx_http_upstream_process_header_line,
207  offsetof(ngx_http_upstream_headers_in_t, location),
208  ngx_http_upstream_rewrite_location, 0, 0 },
209 
210  { ngx_string("Refresh"),
211  ngx_http_upstream_ignore_header_line, 0,
212  ngx_http_upstream_rewrite_refresh, 0, 0 },
213 
214  { ngx_string("Set-Cookie"),
215  ngx_http_upstream_process_set_cookie, 0,
216  ngx_http_upstream_rewrite_set_cookie, 0, 1 },
217 
218  { ngx_string("Content-Disposition"),
219  ngx_http_upstream_ignore_header_line, 0,
220  ngx_http_upstream_copy_header_line, 0, 1 },
221 
222  { ngx_string("Cache-Control"),
223  ngx_http_upstream_process_cache_control, 0,
224  ngx_http_upstream_copy_multi_header_lines,
225  offsetof(ngx_http_headers_out_t, cache_control), 1 },
226 
227  { ngx_string("Expires"),
228  ngx_http_upstream_process_expires, 0,
229  ngx_http_upstream_copy_header_line,
230  offsetof(ngx_http_headers_out_t, expires), 1 },
231 
232  { ngx_string("Accept-Ranges"),
233  ngx_http_upstream_process_header_line,
234  offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
235  ngx_http_upstream_copy_allow_ranges,
236  offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
237 
238  { ngx_string("Connection"),
239  ngx_http_upstream_process_connection, 0,
240  ngx_http_upstream_ignore_header_line, 0, 0 },
241 
242  { ngx_string("Keep-Alive"),
243  ngx_http_upstream_ignore_header_line, 0,
244  ngx_http_upstream_ignore_header_line, 0, 0 },
245 
246  { ngx_string("X-Powered-By"),
247  ngx_http_upstream_ignore_header_line, 0,
248  ngx_http_upstream_copy_header_line, 0, 0 },
249 
250  { ngx_string("X-Accel-Expires"),
251  ngx_http_upstream_process_accel_expires, 0,
252  ngx_http_upstream_copy_header_line, 0, 0 },
253 
254  { ngx_string("X-Accel-Redirect"),
255  ngx_http_upstream_process_header_line,
256  offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect),
257  ngx_http_upstream_copy_header_line, 0, 0 },
258 
259  { ngx_string("X-Accel-Limit-Rate"),
260  ngx_http_upstream_process_limit_rate, 0,
261  ngx_http_upstream_copy_header_line, 0, 0 },
262 
263  { ngx_string("X-Accel-Buffering"),
264  ngx_http_upstream_process_buffering, 0,
265  ngx_http_upstream_copy_header_line, 0, 0 },
266 
267  { ngx_string("X-Accel-Charset"),
268  ngx_http_upstream_process_charset, 0,
269  ngx_http_upstream_copy_header_line, 0, 0 },
270 
271  { ngx_string("Transfer-Encoding"),
272  ngx_http_upstream_process_transfer_encoding, 0,
273  ngx_http_upstream_ignore_header_line, 0, 0 },
274 
275 #if (NGX_HTTP_GZIP)
276  { ngx_string("Content-Encoding"),
277  ngx_http_upstream_process_header_line,
278  offsetof(ngx_http_upstream_headers_in_t, content_encoding),
279  ngx_http_upstream_copy_content_encoding, 0, 0 },
280 #endif
281 
282  { ngx_null_string, NULL, 0, NULL, 0, 0 }
283 };
284 
285 
286 static ngx_command_t ngx_http_upstream_commands[] = {
287 
288  { ngx_string("upstream"),
290  ngx_http_upstream,
291  0,
292  0,
293  NULL },
294 
295  { ngx_string("server"),
297  ngx_http_upstream_server,
299  0,
300  NULL },
301 
303 };
304 
305 
306 static ngx_http_module_t ngx_http_upstream_module_ctx = {
307  ngx_http_upstream_add_variables, /* preconfiguration */
308  NULL, /* postconfiguration */
309 
310  ngx_http_upstream_create_main_conf, /* create main configuration */
311  ngx_http_upstream_init_main_conf, /* init main configuration */
312 
313  NULL, /* create server configuration */
314  NULL, /* merge server configuration */
315 
316  NULL, /* create location configuration */
317  NULL /* merge location configuration */
318 };
319 
320 
323  &ngx_http_upstream_module_ctx, /* module context */
324  ngx_http_upstream_commands, /* module directives */
325  NGX_HTTP_MODULE, /* module type */
326  NULL, /* init master */
327  NULL, /* init module */
328  NULL, /* init process */
329  NULL, /* init thread */
330  NULL, /* exit thread */
331  NULL, /* exit process */
332  NULL, /* exit master */
334 };
335 
336 
337 static ngx_http_variable_t ngx_http_upstream_vars[] = {
338 
339  { ngx_string("upstream_addr"), NULL,
340  ngx_http_upstream_addr_variable, 0,
342 
343  { ngx_string("upstream_status"), NULL,
344  ngx_http_upstream_status_variable, 0,
346 
347  { ngx_string("upstream_response_time"), NULL,
348  ngx_http_upstream_response_time_variable, 0,
350 
351  { ngx_string("upstream_response_length"), NULL,
352  ngx_http_upstream_response_length_variable, 0,
354 
355 #if (NGX_HTTP_CACHE)
356 
357  { ngx_string("upstream_cache_status"), NULL,
358  ngx_http_upstream_cache_status, 0,
360 
361 #endif
362 
363  { ngx_null_string, NULL, NULL, 0, 0, 0 }
364 };
365 
366 
367 static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = {
373  { 0, 0 }
374 };
375 
376 
378  { ngx_string("GET"), NGX_HTTP_GET},
379  { ngx_string("HEAD"), NGX_HTTP_HEAD },
380  { ngx_string("POST"), NGX_HTTP_POST },
381  { ngx_null_string, 0 }
382 };
383 
384 
386  { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
387  { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
388  { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
389  { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
390  { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
392  { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
393  { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
394  { ngx_null_string, 0 }
395 };
396 
397 
398 ngx_int_t
400 {
402 
403  u = r->upstream;
404 
405  if (u && u->cleanup) {
406  r->main->count++;
407  ngx_http_upstream_cleanup(r);
408  }
409 
410  u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
411  if (u == NULL) {
412  return NGX_ERROR;
413  }
414 
415  r->upstream = u;
416 
417  u->peer.log = r->connection->log;
419 #if (NGX_THREADS)
420  u->peer.lock = &r->connection->lock;
421 #endif
422 
423 #if (NGX_HTTP_CACHE)
424  r->cache = NULL;
425 #endif
426 
428 
429  return NGX_OK;
430 }
431 
432 
433 void
435 {
436  ngx_connection_t *c;
437 
438  c = r->connection;
439 
441  "http init upstream, client timer: %d", c->read->timer_set);
442 
443 #if (NGX_HTTP_SPDY)
444  if (r->spdy_stream) {
445  ngx_http_upstream_init_request(r);
446  return;
447  }
448 #endif
449 
450  if (c->read->timer_set) {
451  ngx_del_timer(c->read);
452  }
453 
455 
456  if (!c->write->active) {
458  == NGX_ERROR)
459  {
461  return;
462  }
463  }
464  }
465 
466  ngx_http_upstream_init_request(r);
467 }
468 
469 
470 static void
471 ngx_http_upstream_init_request(ngx_http_request_t *r)
472 {
473  ngx_str_t *host;
474  ngx_uint_t i;
475  ngx_resolver_ctx_t *ctx, temp;
476  ngx_http_cleanup_t *cln;
479  ngx_http_upstream_srv_conf_t *uscf, **uscfp;
481 
482  if (r->aio) {
483  return;
484  }
485 
486  u = r->upstream;
487 
488 #if (NGX_HTTP_CACHE)
489 
490  if (u->conf->cache) {
491  ngx_int_t rc;
492 
493  rc = ngx_http_upstream_cache(r, u);
494 
495  if (rc == NGX_BUSY) {
496  r->write_event_handler = ngx_http_upstream_init_request;
497  return;
498  }
499 
501 
502  if (rc == NGX_DONE) {
503  return;
504  }
505 
506  if (rc != NGX_DECLINED) {
508  return;
509  }
510  }
511 
512 #endif
513 
514  u->store = (u->conf->store || u->conf->store_lengths);
515 
516  if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
517  r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
518  r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
519  }
520 
521  if (r->request_body) {
522  u->request_bufs = r->request_body->bufs;
523  }
524 
525  if (u->create_request(r) != NGX_OK) {
527  return;
528  }
529 
530  u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);
531 
533 
535  u->output.pool = r->pool;
536  u->output.bufs.num = 1;
539  u->output.filter_ctx = &u->writer;
540 
541  u->writer.pool = r->pool;
542 
543  if (r->upstream_states == NULL) {
544 
546  sizeof(ngx_http_upstream_state_t));
547  if (r->upstream_states == NULL) {
549  return;
550  }
551 
552  } else {
553 
555  if (u->state == NULL) {
556  ngx_http_upstream_finalize_request(r, u,
558  return;
559  }
560 
562  }
563 
564  cln = ngx_http_cleanup_add(r, 0);
565  if (cln == NULL) {
567  return;
568  }
569 
570  cln->handler = ngx_http_upstream_cleanup;
571  cln->data = r;
572  u->cleanup = &cln->handler;
573 
574  if (u->resolved == NULL) {
575 
576  uscf = u->conf->upstream;
577 
578  } else {
579 
580  if (u->resolved->sockaddr) {
581 
583  != NGX_OK)
584  {
585  ngx_http_upstream_finalize_request(r, u,
587  return;
588  }
589 
590  ngx_http_upstream_connect(r, u);
591 
592  return;
593  }
594 
595  host = &u->resolved->host;
596 
597  umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
598 
599  uscfp = umcf->upstreams.elts;
600 
601  for (i = 0; i < umcf->upstreams.nelts; i++) {
602 
603  uscf = uscfp[i];
604 
605  if (uscf->host.len == host->len
606  && ((uscf->port == 0 && u->resolved->no_port)
607  || uscf->port == u->resolved->port)
608  && ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
609  {
610  goto found;
611  }
612  }
613 
614  if (u->resolved->port == 0) {
616  "no port in upstream \"%V\"", host);
617  ngx_http_upstream_finalize_request(r, u,
619  return;
620  }
621 
622  temp.name = *host;
623 
624  ctx = ngx_resolve_start(clcf->resolver, &temp);
625  if (ctx == NULL) {
626  ngx_http_upstream_finalize_request(r, u,
628  return;
629  }
630 
631  if (ctx == NGX_NO_RESOLVER) {
633  "no resolver defined to resolve %V", host);
634 
635  ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
636  return;
637  }
638 
639  ctx->name = *host;
640  ctx->type = NGX_RESOLVE_A;
641  ctx->handler = ngx_http_upstream_resolve_handler;
642  ctx->data = r;
643  ctx->timeout = clcf->resolver_timeout;
644 
645  u->resolved->ctx = ctx;
646 
647  if (ngx_resolve_name(ctx) != NGX_OK) {
648  u->resolved->ctx = NULL;
649  ngx_http_upstream_finalize_request(r, u,
651  return;
652  }
653 
654  return;
655  }
656 
657 found:
658 
659  if (uscf == NULL) {
661  "no upstream configuration");
662  ngx_http_upstream_finalize_request(r, u,
664  return;
665  }
666 
667  if (uscf->peer.init(r, uscf) != NGX_OK) {
668  ngx_http_upstream_finalize_request(r, u,
670  return;
671  }
672 
673  ngx_http_upstream_connect(r, u);
674 }
675 
676 
677 #if (NGX_HTTP_CACHE)
678 
679 static ngx_int_t
680 ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
681 {
682  ngx_int_t rc;
683  ngx_http_cache_t *c;
684 
685  c = r->cache;
686 
687  if (c == NULL) {
688 
689  if (!(r->method & u->conf->cache_methods)) {
690  return NGX_DECLINED;
691  }
692 
693  if (r->method & NGX_HTTP_HEAD) {
695  }
696 
697  if (ngx_http_file_cache_new(r) != NGX_OK) {
698  return NGX_ERROR;
699  }
700 
701  if (u->create_key(r) != NGX_OK) {
702  return NGX_ERROR;
703  }
704 
705  /* TODO: add keys */
706 
708 
709  if (r->cache->header_start + 256 >= u->conf->buffer_size) {
711  "%V_buffer_size %uz is not enough for cache key, "
712  "it should increased at least to %uz",
713  &u->conf->module, u->conf->buffer_size,
714  ngx_align(r->cache->header_start + 256, 1024));
715 
716  r->cache = NULL;
717  return NGX_DECLINED;
718  }
719 
720  u->cacheable = 1;
721 
722  switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
723 
724  case NGX_ERROR:
725  return NGX_ERROR;
726 
727  case NGX_DECLINED:
728  u->cache_status = NGX_HTTP_CACHE_BYPASS;
729  return NGX_DECLINED;
730 
731  default: /* NGX_OK */
732  break;
733  }
734 
735  c = r->cache;
736 
737  c->min_uses = u->conf->cache_min_uses;
738  c->body_start = u->conf->buffer_size;
739  c->file_cache = u->conf->cache->data;
740 
741  c->lock = u->conf->cache_lock;
742  c->lock_timeout = u->conf->cache_lock_timeout;
743 
744  u->cache_status = NGX_HTTP_CACHE_MISS;
745  }
746 
747  rc = ngx_http_file_cache_open(r);
748 
750  "http upstream cache: %i", rc);
751 
752  switch (rc) {
753 
755 
756  if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
757  u->cache_status = rc;
758  rc = NGX_OK;
759 
760  } else {
762  }
763 
764  break;
765 
766  case NGX_OK:
767  u->cache_status = NGX_HTTP_CACHE_HIT;
768  }
769 
770  switch (rc) {
771 
772  case NGX_OK:
773 
774  rc = ngx_http_upstream_cache_send(r, u);
775 
777  return rc;
778  }
779 
780  break;
781 
783 
784  c->valid_sec = 0;
785  u->buffer.start = NULL;
786  u->cache_status = NGX_HTTP_CACHE_EXPIRED;
787 
788  break;
789 
790  case NGX_DECLINED:
791 
792  if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
793  u->buffer.start = NULL;
794 
795  } else {
796  u->buffer.pos = u->buffer.start + c->header_start;
797  u->buffer.last = u->buffer.pos;
798  }
799 
800  break;
801 
803 
804  u->cacheable = 0;
805 
806  break;
807 
808  case NGX_AGAIN:
809 
810  return NGX_BUSY;
811 
812  case NGX_ERROR:
813 
814  return NGX_ERROR;
815 
816  default:
817 
818  /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
819 
820  u->cache_status = NGX_HTTP_CACHE_HIT;
821 
822  return rc;
823  }
824 
825  r->cached = 0;
826 
827  return NGX_DECLINED;
828 }
829 
830 
831 static ngx_int_t
832 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
833 {
834  ngx_int_t rc;
835  ngx_http_cache_t *c;
836 
837  r->cached = 1;
838  c = r->cache;
839 
840  if (c->header_start == c->body_start) {
842  return ngx_http_cache_send(r);
843  }
844 
845  /* TODO: cache stack */
846 
847  u->buffer = *c->buf;
848  u->buffer.pos += c->header_start;
849 
852 
853  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
854  sizeof(ngx_table_elt_t))
855  != NGX_OK)
856  {
857  return NGX_ERROR;
858  }
859 
860  rc = u->process_header(r);
861 
862  if (rc == NGX_OK) {
863 
864  if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
865  return NGX_DONE;
866  }
867 
868  return ngx_http_cache_send(r);
869  }
870 
871  if (rc == NGX_ERROR) {
872  return NGX_ERROR;
873  }
874 
875  /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
876 
877  /* TODO: delete file */
878 
879  return rc;
880 }
881 
882 #endif
883 
884 
885 static void
886 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
887 {
888  ngx_connection_t *c;
892 
893  r = ctx->data;
894  c = r->connection;
895 
896  u = r->upstream;
897  ur = u->resolved;
898 
899  if (ctx->state) {
901  "%V could not be resolved (%i: %s)",
902  &ctx->name, ctx->state,
904 
905  ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
906  goto failed;
907  }
908 
909  ur->naddrs = ctx->naddrs;
910  ur->addrs = ctx->addrs;
911 
912 #if (NGX_DEBUG)
913  {
914  in_addr_t addr;
915  ngx_uint_t i;
916 
917  for (i = 0; i < ctx->naddrs; i++) {
918  addr = ntohl(ur->addrs[i]);
919 
921  "name was resolved to %ud.%ud.%ud.%ud",
922  (addr >> 24) & 0xff, (addr >> 16) & 0xff,
923  (addr >> 8) & 0xff, addr & 0xff);
924  }
925  }
926 #endif
927 
929  ngx_http_upstream_finalize_request(r, u,
931  goto failed;
932  }
933 
935  ur->ctx = NULL;
936 
937  ngx_http_upstream_connect(r, u);
938 
939 failed:
940 
942 }
943 
944 
945 static void
946 ngx_http_upstream_handler(ngx_event_t *ev)
947 {
948  ngx_connection_t *c;
950  ngx_http_log_ctx_t *ctx;
952 
953  c = ev->data;
954  r = c->data;
955 
956  u = r->upstream;
957  c = r->connection;
958 
959  ctx = c->log->data;
960  ctx->current_request = r;
961 
963  "http upstream request: \"%V?%V\"", &r->uri, &r->args);
964 
965  if (ev->write) {
966  u->write_event_handler(r, u);
967 
968  } else {
969  u->read_event_handler(r, u);
970  }
971 
973 }
974 
975 
976 static void
977 ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
978 {
979  ngx_http_upstream_check_broken_connection(r, r->connection->read);
980 }
981 
982 
983 static void
984 ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
985 {
986  ngx_http_upstream_check_broken_connection(r, r->connection->write);
987 }
988 
989 
990 static void
991 ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
992  ngx_event_t *ev)
993 {
994  int n;
995  char buf[1];
996  ngx_err_t err;
997  ngx_int_t event;
998  ngx_connection_t *c;
1000 
1002  "http upstream check client, write event:%d, \"%V\"",
1003  ev->write, &r->uri);
1004 
1005  c = r->connection;
1006  u = r->upstream;
1007 
1008  if (c->error) {
1009  if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
1010 
1011  event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
1012 
1013  if (ngx_del_event(ev, event, 0) != NGX_OK) {
1014  ngx_http_upstream_finalize_request(r, u,
1016  return;
1017  }
1018  }
1019 
1020  if (!u->cacheable) {
1021  ngx_http_upstream_finalize_request(r, u,
1023  }
1024 
1025  return;
1026  }
1027 
1028 #if (NGX_HTTP_SPDY)
1029  if (r->spdy_stream) {
1030  return;
1031  }
1032 #endif
1033 
1034 #if (NGX_HAVE_KQUEUE)
1035 
1037 
1038  if (!ev->pending_eof) {
1039  return;
1040  }
1041 
1042  ev->eof = 1;
1043  c->error = 1;
1044 
1045  if (ev->kq_errno) {
1046  ev->error = 1;
1047  }
1048 
1049  if (!u->cacheable && u->peer.connection) {
1050  ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
1051  "kevent() reported that client prematurely closed "
1052  "connection, so upstream connection is closed too");
1053  ngx_http_upstream_finalize_request(r, u,
1055  return;
1056  }
1057 
1058  ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
1059  "kevent() reported that client prematurely closed "
1060  "connection");
1061 
1062  if (u->peer.connection == NULL) {
1063  ngx_http_upstream_finalize_request(r, u,
1065  }
1066 
1067  return;
1068  }
1069 
1070 #endif
1071 
1072  n = recv(c->fd, buf, 1, MSG_PEEK);
1073 
1074  err = ngx_socket_errno;
1075 
1077  "http upstream recv(): %d", n);
1078 
1079  if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
1080  return;
1081  }
1082 
1083  if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
1084 
1085  event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
1086 
1087  if (ngx_del_event(ev, event, 0) != NGX_OK) {
1088  ngx_http_upstream_finalize_request(r, u,
1090  return;
1091  }
1092  }
1093 
1094  if (n > 0) {
1095  return;
1096  }
1097 
1098  if (n == -1) {
1099  if (err == NGX_EAGAIN) {
1100  return;
1101  }
1102 
1103  ev->error = 1;
1104 
1105  } else { /* n == 0 */
1106  err = 0;
1107  }
1108 
1109  ev->eof = 1;
1110  c->error = 1;
1111 
1112  if (!u->cacheable && u->peer.connection) {
1113  ngx_log_error(NGX_LOG_INFO, ev->log, err,
1114  "client prematurely closed connection, "
1115  "so upstream connection is closed too");
1116  ngx_http_upstream_finalize_request(r, u,
1118  return;
1119  }
1120 
1121  ngx_log_error(NGX_LOG_INFO, ev->log, err,
1122  "client prematurely closed connection");
1123 
1124  if (u->peer.connection == NULL) {
1125  ngx_http_upstream_finalize_request(r, u,
1127  }
1128 }
1129 
1130 
1131 static void
1132 ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1133 {
1134  ngx_int_t rc;
1135  ngx_time_t *tp;
1136  ngx_connection_t *c;
1137 
1138  r->connection->log->action = "connecting to upstream";
1139 
1140  if (u->state && u->state->response_sec) {
1141  tp = ngx_timeofday();
1142  u->state->response_sec = tp->sec - u->state->response_sec;
1143  u->state->response_msec = tp->msec - u->state->response_msec;
1144  }
1145 
1147  if (u->state == NULL) {
1148  ngx_http_upstream_finalize_request(r, u,
1150  return;
1151  }
1152 
1154 
1155  tp = ngx_timeofday();
1156  u->state->response_sec = tp->sec;
1157  u->state->response_msec = tp->msec;
1158 
1159  rc = ngx_event_connect_peer(&u->peer);
1160 
1162  "http upstream connect: %i", rc);
1163 
1164  if (rc == NGX_ERROR) {
1165  ngx_http_upstream_finalize_request(r, u,
1167  return;
1168  }
1169 
1170  u->state->peer = u->peer.name;
1171 
1172  if (rc == NGX_BUSY) {
1173  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
1174  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
1175  return;
1176  }
1177 
1178  if (rc == NGX_DECLINED) {
1179  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1180  return;
1181  }
1182 
1183  /* rc == NGX_OK || rc == NGX_AGAIN */
1184 
1185  c = u->peer.connection;
1186 
1187  c->data = r;
1188 
1189  c->write->handler = ngx_http_upstream_handler;
1190  c->read->handler = ngx_http_upstream_handler;
1191 
1192  u->write_event_handler = ngx_http_upstream_send_request_handler;
1193  u->read_event_handler = ngx_http_upstream_process_header;
1194 
1195  c->sendfile &= r->connection->sendfile;
1196  u->output.sendfile = c->sendfile;
1197 
1198  if (c->pool == NULL) {
1199 
1200  /* we need separate pool here to be able to cache SSL connections */
1201 
1202  c->pool = ngx_create_pool(128, r->connection->log);
1203  if (c->pool == NULL) {
1204  ngx_http_upstream_finalize_request(r, u,
1206  return;
1207  }
1208  }
1209 
1210  c->log = r->connection->log;
1211  c->pool->log = c->log;
1212  c->read->log = c->log;
1213  c->write->log = c->log;
1214 
1215  /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
1216 
1217  u->writer.out = NULL;
1218  u->writer.last = &u->writer.out;
1219  u->writer.connection = c;
1220  u->writer.limit = 0;
1221 
1222  if (u->request_sent) {
1223  if (ngx_http_upstream_reinit(r, u) != NGX_OK) {
1224  ngx_http_upstream_finalize_request(r, u,
1226  return;
1227  }
1228  }
1229 
1230  if (r->request_body
1231  && r->request_body->buf
1232  && r->request_body->temp_file
1233  && r == r->main)
1234  {
1235  /*
1236  * the r->request_body->buf can be reused for one request only,
1237  * the subrequests should allocate their own temporary bufs
1238  */
1239 
1241  if (u->output.free == NULL) {
1242  ngx_http_upstream_finalize_request(r, u,
1244  return;
1245  }
1246 
1247  u->output.free->buf = r->request_body->buf;
1248  u->output.free->next = NULL;
1249  u->output.allocated = 1;
1250 
1251  r->request_body->buf->pos = r->request_body->buf->start;
1252  r->request_body->buf->last = r->request_body->buf->start;
1253  r->request_body->buf->tag = u->output.tag;
1254  }
1255 
1256  u->request_sent = 0;
1257 
1258  if (rc == NGX_AGAIN) {
1260  return;
1261  }
1262 
1263 #if (NGX_HTTP_SSL)
1264 
1265  if (u->ssl && c->ssl == NULL) {
1266  ngx_http_upstream_ssl_init_connection(r, u, c);
1267  return;
1268  }
1269 
1270 #endif
1271 
1272  ngx_http_upstream_send_request(r, u);
1273 }
1274 
1275 
1276 #if (NGX_HTTP_SSL)
1277 
1278 static void
1279 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1281 {
1282  ngx_int_t rc;
1283 
1284  if (ngx_ssl_create_connection(u->conf->ssl, c,
1286  != NGX_OK)
1287  {
1288  ngx_http_upstream_finalize_request(r, u,
1290  return;
1291  }
1292 
1293  c->sendfile = 0;
1294  u->output.sendfile = 0;
1295 
1296  if (u->conf->ssl_session_reuse) {
1297  if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
1298  ngx_http_upstream_finalize_request(r, u,
1300  return;
1301  }
1302  }
1303 
1304  r->connection->log->action = "SSL handshaking to upstream";
1305 
1306  rc = ngx_ssl_handshake(c);
1307 
1308  if (rc == NGX_AGAIN) {
1309  c->ssl->handler = ngx_http_upstream_ssl_handshake;
1310  return;
1311  }
1312 
1313  ngx_http_upstream_ssl_handshake(c);
1314 }
1315 
1316 
1317 static void
1318 ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1319 {
1320  ngx_http_request_t *r;
1322 
1323  r = c->data;
1324  u = r->upstream;
1325 
1326  if (c->ssl->handshaked) {
1327 
1328  if (u->conf->ssl_session_reuse) {
1329  u->peer.save_session(&u->peer, u->peer.data);
1330  }
1331 
1332  c->write->handler = ngx_http_upstream_handler;
1333  c->read->handler = ngx_http_upstream_handler;
1334 
1335  ngx_http_upstream_send_request(r, u);
1336 
1337  return;
1338  }
1339 
1340  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1341 
1342 }
1343 
1344 #endif
1345 
1346 
1347 static ngx_int_t
1348 ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1349 {
1350  ngx_chain_t *cl;
1351 
1352  if (u->reinit_request(r) != NGX_OK) {
1353  return NGX_ERROR;
1354  }
1355 
1356  u->keepalive = 0;
1357  u->upgrade = 0;
1358 
1360  u->headers_in.content_length_n = -1;
1361 
1362  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1363  sizeof(ngx_table_elt_t))
1364  != NGX_OK)
1365  {
1366  return NGX_ERROR;
1367  }
1368 
1369  /* reinit the request chain */
1370 
1371  for (cl = u->request_bufs; cl; cl = cl->next) {
1372  cl->buf->pos = cl->buf->start;
1373  cl->buf->file_pos = 0;
1374  }
1375 
1376  /* reinit the subrequest's ngx_output_chain() context */
1377 
1378  if (r->request_body && r->request_body->temp_file
1379  && r != r->main && u->output.buf)
1380  {
1382  if (u->output.free == NULL) {
1383  return NGX_ERROR;
1384  }
1385 
1386  u->output.free->buf = u->output.buf;
1387  u->output.free->next = NULL;
1388 
1389  u->output.buf->pos = u->output.buf->start;
1390  u->output.buf->last = u->output.buf->start;
1391  }
1392 
1393  u->output.buf = NULL;
1394  u->output.in = NULL;
1395  u->output.busy = NULL;
1396 
1397  /* reinit u->buffer */
1398 
1399  u->buffer.pos = u->buffer.start;
1400 
1401 #if (NGX_HTTP_CACHE)
1402 
1403  if (r->cache) {
1404  u->buffer.pos += r->cache->header_start;
1405  }
1406 
1407 #endif
1408 
1409  u->buffer.last = u->buffer.pos;
1410 
1411  return NGX_OK;
1412 }
1413 
1414 
1415 static void
1416 ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1417 {
1418  ngx_int_t rc;
1419  ngx_connection_t *c;
1420 
1421  c = u->peer.connection;
1422 
1424  "http upstream send request");
1425 
1426  if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
1427  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1428  return;
1429  }
1430 
1431  c->log->action = "sending request to upstream";
1432 
1433  rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs);
1434 
1435  u->request_sent = 1;
1436 
1437  if (rc == NGX_ERROR) {
1438  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1439  return;
1440  }
1441 
1442  if (c->write->timer_set) {
1443  ngx_del_timer(c->write);
1444  }
1445 
1446  if (rc == NGX_AGAIN) {
1448 
1450  ngx_http_upstream_finalize_request(r, u,
1452  return;
1453  }
1454 
1455  return;
1456  }
1457 
1458  /* rc == NGX_OK */
1459 
1460  if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
1461  if (ngx_tcp_push(c->fd) == NGX_ERROR) {
1463  ngx_tcp_push_n " failed");
1464  ngx_http_upstream_finalize_request(r, u,
1466  return;
1467  }
1468 
1470  }
1471 
1473 
1474 #if 1
1475  if (c->read->ready) {
1476 
1477  /* post aio operation */
1478 
1479  /*
1480  * TODO comment
1481  * although we can post aio operation just in the end
1482  * of ngx_http_upstream_connect() CHECK IT !!!
1483  * it's better to do here because we postpone header buffer allocation
1484  */
1485 
1486  ngx_http_upstream_process_header(r, u);
1487  return;
1488  }
1489 #endif
1490 
1491  u->write_event_handler = ngx_http_upstream_dummy_handler;
1492 
1493  if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1494  ngx_http_upstream_finalize_request(r, u,
1496  return;
1497  }
1498 }
1499 
1500 
1501 static void
1502 ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
1504 {
1505  ngx_connection_t *c;
1506 
1507  c = u->peer.connection;
1508 
1510  "http upstream send request handler");
1511 
1512  if (c->write->timedout) {
1513  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
1514  return;
1515  }
1516 
1517 #if (NGX_HTTP_SSL)
1518 
1519  if (u->ssl && c->ssl == NULL) {
1520  ngx_http_upstream_ssl_init_connection(r, u, c);
1521  return;
1522  }
1523 
1524 #endif
1525 
1526  if (u->header_sent) {
1527  u->write_event_handler = ngx_http_upstream_dummy_handler;
1528 
1529  (void) ngx_handle_write_event(c->write, 0);
1530 
1531  return;
1532  }
1533 
1534  ngx_http_upstream_send_request(r, u);
1535 }
1536 
1537 
1538 static void
1539 ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1540 {
1541  ssize_t n;
1542  ngx_int_t rc;
1543  ngx_connection_t *c;
1544 
1545  c = u->peer.connection;
1546 
1548  "http upstream process header");
1549 
1550  c->log->action = "reading response header from upstream";
1551 
1552  if (c->read->timedout) {
1553  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
1554  return;
1555  }
1556 
1557  if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
1558  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1559  return;
1560  }
1561 
1562  if (u->buffer.start == NULL) {
1563  u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
1564  if (u->buffer.start == NULL) {
1565  ngx_http_upstream_finalize_request(r, u,
1567  return;
1568  }
1569 
1570  u->buffer.pos = u->buffer.start;
1571  u->buffer.last = u->buffer.start;
1572  u->buffer.end = u->buffer.start + u->conf->buffer_size;
1573  u->buffer.temporary = 1;
1574 
1575  u->buffer.tag = u->output.tag;
1576 
1577  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1578  sizeof(ngx_table_elt_t))
1579  != NGX_OK)
1580  {
1581  ngx_http_upstream_finalize_request(r, u,
1583  return;
1584  }
1585 
1586 #if (NGX_HTTP_CACHE)
1587 
1588  if (r->cache) {
1589  u->buffer.pos += r->cache->header_start;
1590  u->buffer.last = u->buffer.pos;
1591  }
1592 #endif
1593  }
1594 
1595  for ( ;; ) {
1596 
1597  n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
1598 
1599  if (n == NGX_AGAIN) {
1600 #if 0
1601  ngx_add_timer(rev, u->read_timeout);
1602 #endif
1603 
1604  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
1605  ngx_http_upstream_finalize_request(r, u,
1607  return;
1608  }
1609 
1610  return;
1611  }
1612 
1613  if (n == 0) {
1614  ngx_log_error(NGX_LOG_ERR, c->log, 0,
1615  "upstream prematurely closed connection");
1616  }
1617 
1618  if (n == NGX_ERROR || n == 0) {
1619  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1620  return;
1621  }
1622 
1623  u->buffer.last += n;
1624 
1625 #if 0
1626  u->valid_header_in = 0;
1627 
1628  u->peer.cached = 0;
1629 #endif
1630 
1631  rc = u->process_header(r);
1632 
1633  if (rc == NGX_AGAIN) {
1634 
1635  if (u->buffer.last == u->buffer.end) {
1636  ngx_log_error(NGX_LOG_ERR, c->log, 0,
1637  "upstream sent too big header");
1638 
1639  ngx_http_upstream_next(r, u,
1641  return;
1642  }
1643 
1644  continue;
1645  }
1646 
1647  break;
1648  }
1649 
1651  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
1652  return;
1653  }
1654 
1655  if (rc == NGX_ERROR) {
1656  ngx_http_upstream_finalize_request(r, u,
1658  return;
1659  }
1660 
1661  /* rc == NGX_OK */
1662 
1664 
1665  if (r->subrequest_in_memory) {
1666  u->buffer.last = u->buffer.pos;
1667  }
1668 
1669  if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
1670  return;
1671  }
1672 
1673  if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
1674  return;
1675  }
1676  }
1677 
1678  if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
1679  return;
1680  }
1681 
1682  if (!r->subrequest_in_memory) {
1683  ngx_http_upstream_send_response(r, u);
1684  return;
1685  }
1686 
1687  /* subrequest content in memory */
1688 
1689  if (u->input_filter == NULL) {
1690  u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
1691  u->input_filter = ngx_http_upstream_non_buffered_filter;
1692  u->input_filter_ctx = r;
1693  }
1694 
1696  ngx_http_upstream_finalize_request(r, u,
1698  return;
1699  }
1700 
1701  n = u->buffer.last - u->buffer.pos;
1702 
1703  if (n) {
1704  u->buffer.last -= n;
1705 
1706  u->state->response_length += n;
1707 
1708  if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
1709  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1710  return;
1711  }
1712 
1713  if (u->length == 0) {
1714  ngx_http_upstream_finalize_request(r, u, 0);
1715  return;
1716  }
1717  }
1718 
1719  u->read_event_handler = ngx_http_upstream_process_body_in_memory;
1720 
1721  ngx_http_upstream_process_body_in_memory(r, u);
1722 }
1723 
1724 
1725 static ngx_int_t
1726 ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
1727 {
1728  ngx_uint_t status;
1730 
1731  status = u->headers_in.status_n;
1732 
1733  for (un = ngx_http_upstream_next_errors; un->status; un++) {
1734 
1735  if (status != un->status) {
1736  continue;
1737  }
1738 
1739  if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) {
1740  ngx_http_upstream_next(r, u, un->mask);
1741  return NGX_OK;
1742  }
1743 
1744 #if (NGX_HTTP_CACHE)
1745 
1746  if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
1747  && (u->conf->cache_use_stale & un->mask))
1748  {
1749  ngx_int_t rc;
1750 
1751  rc = u->reinit_request(r);
1752 
1753  if (rc == NGX_OK) {
1754  u->cache_status = NGX_HTTP_CACHE_STALE;
1755  rc = ngx_http_upstream_cache_send(r, u);
1756  }
1757 
1758  ngx_http_upstream_finalize_request(r, u, rc);
1759  return NGX_OK;
1760  }
1761 
1762 #endif
1763  }
1764 
1765  return NGX_DECLINED;
1766 }
1767 
1768 
1769 static ngx_int_t
1770 ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
1772 {
1773  ngx_int_t status;
1774  ngx_uint_t i;
1775  ngx_table_elt_t *h;
1776  ngx_http_err_page_t *err_page;
1778 
1779  status = u->headers_in.status_n;
1780 
1781  if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) {
1782  ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
1783  return NGX_OK;
1784  }
1785 
1786  if (!u->conf->intercept_errors) {
1787  return NGX_DECLINED;
1788  }
1789 
1791 
1792  if (clcf->error_pages == NULL) {
1793  return NGX_DECLINED;
1794  }
1795 
1796  err_page = clcf->error_pages->elts;
1797  for (i = 0; i < clcf->error_pages->nelts; i++) {
1798 
1799  if (err_page[i].status == status) {
1800 
1801  if (status == NGX_HTTP_UNAUTHORIZED
1803  {
1805 
1806  if (h == NULL) {
1807  ngx_http_upstream_finalize_request(r, u,
1809  return NGX_OK;
1810  }
1811 
1812  *h = *u->headers_in.www_authenticate;
1813 
1815  }
1816 
1817 #if (NGX_HTTP_CACHE)
1818 
1819  if (r->cache) {
1820  time_t valid;
1821 
1822  valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
1823 
1824  if (valid) {
1825  r->cache->valid_sec = ngx_time() + valid;
1826  r->cache->error = status;
1827  }
1828 
1829  ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
1830  }
1831 #endif
1832  ngx_http_upstream_finalize_request(r, u, status);
1833 
1834  return NGX_OK;
1835  }
1836  }
1837 
1838  return NGX_DECLINED;
1839 }
1840 
1841 
1842 static ngx_int_t
1843 ngx_http_upstream_test_connect(ngx_connection_t *c)
1844 {
1845  int err;
1846  socklen_t len;
1847 
1848 #if (NGX_HAVE_KQUEUE)
1849 
1850  if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
1851  if (c->write->pending_eof || c->read->pending_eof) {
1852  if (c->write->pending_eof) {
1853  err = c->write->kq_errno;
1854 
1855  } else {
1856  err = c->read->kq_errno;
1857  }
1858 
1859  c->log->action = "connecting to upstream";
1860  (void) ngx_connection_error(c, err,
1861  "kevent() reported that connect() failed");
1862  return NGX_ERROR;
1863  }
1864 
1865  } else
1866 #endif
1867  {
1868  err = 0;
1869  len = sizeof(int);
1870 
1871  /*
1872  * BSDs and Linux return 0 and set a pending error in err
1873  * Solaris returns -1 and sets errno
1874  */
1875 
1876  if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
1877  == -1)
1878  {
1879  err = ngx_errno;
1880  }
1881 
1882  if (err) {
1883  c->log->action = "connecting to upstream";
1884  (void) ngx_connection_error(c, err, "connect() failed");
1885  return NGX_ERROR;
1886  }
1887  }
1888 
1889  return NGX_OK;
1890 }
1891 
1892 
1893 static ngx_int_t
1894 ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
1895 {
1896  ngx_str_t *uri, args;
1897  ngx_uint_t i, flags;
1898  ngx_list_part_t *part;
1899  ngx_table_elt_t *h;
1902 
1903  umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1904 
1907  {
1908  ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
1909 
1910  part = &u->headers_in.headers.part;
1911  h = part->elts;
1912 
1913  for (i = 0; /* void */; i++) {
1914 
1915  if (i >= part->nelts) {
1916  if (part->next == NULL) {
1917  break;
1918  }
1919 
1920  part = part->next;
1921  h = part->elts;
1922  i = 0;
1923  }
1924 
1925  hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1926  h[i].lowcase_key, h[i].key.len);
1927 
1928  if (hh && hh->redirect) {
1929  if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1932  return NGX_DONE;
1933  }
1934  }
1935  }
1936 
1937  uri = &u->headers_in.x_accel_redirect->value;
1938  ngx_str_null(&args);
1939  flags = NGX_HTTP_LOG_UNSAFE;
1940 
1941  if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1943  return NGX_DONE;
1944  }
1945 
1946  if (r->method != NGX_HTTP_HEAD) {
1947  r->method = NGX_HTTP_GET;
1948  }
1949 
1950  ngx_http_internal_redirect(r, uri, &args);
1952  return NGX_DONE;
1953  }
1954 
1955  part = &u->headers_in.headers.part;
1956  h = part->elts;
1957 
1958  for (i = 0; /* void */; i++) {
1959 
1960  if (i >= part->nelts) {
1961  if (part->next == NULL) {
1962  break;
1963  }
1964 
1965  part = part->next;
1966  h = part->elts;
1967  i = 0;
1968  }
1969 
1970  if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
1971  h[i].lowcase_key, h[i].key.len))
1972  {
1973  continue;
1974  }
1975 
1976  hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1977  h[i].lowcase_key, h[i].key.len);
1978 
1979  if (hh) {
1980  if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1981  ngx_http_upstream_finalize_request(r, u,
1983  return NGX_DONE;
1984  }
1985 
1986  continue;
1987  }
1988 
1989  if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
1990  ngx_http_upstream_finalize_request(r, u,
1992  return NGX_DONE;
1993  }
1994  }
1995 
1996  if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
1997  r->headers_out.server->hash = 0;
1998  }
1999 
2000  if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
2001  r->headers_out.date->hash = 0;
2002  }
2003 
2006 
2008 
2010 
2011  return NGX_OK;
2012 }
2013 
2014 
2015 static void
2016 ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
2018 {
2019  size_t size;
2020  ssize_t n;
2021  ngx_buf_t *b;
2022  ngx_event_t *rev;
2023  ngx_connection_t *c;
2024 
2025  c = u->peer.connection;
2026  rev = c->read;
2027 
2029  "http upstream process body on memory");
2030 
2031  if (rev->timedout) {
2032  ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2033  ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT);
2034  return;
2035  }
2036 
2037  b = &u->buffer;
2038 
2039  for ( ;; ) {
2040 
2041  size = b->end - b->last;
2042 
2043  if (size == 0) {
2045  "upstream buffer is too small to read response");
2046  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2047  return;
2048  }
2049 
2050  n = c->recv(c, b->last, size);
2051 
2052  if (n == NGX_AGAIN) {
2053  break;
2054  }
2055 
2056  if (n == 0 || n == NGX_ERROR) {
2057  ngx_http_upstream_finalize_request(r, u, n);
2058  return;
2059  }
2060 
2061  u->state->response_length += n;
2062 
2063  if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2064  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2065  return;
2066  }
2067 
2068  if (!rev->ready) {
2069  break;
2070  }
2071  }
2072 
2073  if (u->length == 0) {
2074  ngx_http_upstream_finalize_request(r, u, 0);
2075  return;
2076  }
2077 
2078  if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2079  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2080  return;
2081  }
2082 
2083  if (rev->active) {
2084  ngx_add_timer(rev, u->conf->read_timeout);
2085 
2086  } else if (rev->timer_set) {
2087  ngx_del_timer(rev);
2088  }
2089 }
2090 
2091 
2092 static void
2093 ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2094 {
2095  int tcp_nodelay;
2096  ssize_t n;
2097  ngx_int_t rc;
2098  ngx_event_pipe_t *p;
2099  ngx_connection_t *c;
2101 
2102  rc = ngx_http_send_header(r);
2103 
2104  if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
2105  ngx_http_upstream_finalize_request(r, u, rc);
2106  return;
2107  }
2108 
2109  if (u->upgrade) {
2110  ngx_http_upstream_upgrade(r, u);
2111  return;
2112  }
2113 
2114  c = r->connection;
2115 
2116  if (r->header_only) {
2117 
2118  if (u->cacheable || u->store) {
2119 
2120  if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
2122  ngx_shutdown_socket_n " failed");
2123  }
2124 
2127  c->error = 1;
2128 
2129  } else {
2130  ngx_http_upstream_finalize_request(r, u, rc);
2131  return;
2132  }
2133  }
2134 
2135  u->header_sent = 1;
2136 
2137  if (r->request_body && r->request_body->temp_file) {
2140  }
2141 
2143 
2144  if (!u->buffering) {
2145 
2146  if (u->input_filter == NULL) {
2147  u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
2148  u->input_filter = ngx_http_upstream_non_buffered_filter;
2149  u->input_filter_ctx = r;
2150  }
2151 
2152  u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
2153  r->write_event_handler =
2154  ngx_http_upstream_process_non_buffered_downstream;
2155 
2156  r->limit_rate = 0;
2157 
2159  ngx_http_upstream_finalize_request(r, u, 0);
2160  return;
2161  }
2162 
2163  if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
2164  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2165 
2166  tcp_nodelay = 1;
2167 
2168  if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2169  (const void *) &tcp_nodelay, sizeof(int)) == -1)
2170  {
2172  "setsockopt(TCP_NODELAY) failed");
2173  ngx_http_upstream_finalize_request(r, u, 0);
2174  return;
2175  }
2176 
2178  }
2179 
2180  n = u->buffer.last - u->buffer.pos;
2181 
2182  if (n) {
2183  u->buffer.last = u->buffer.pos;
2184 
2185  u->state->response_length += n;
2186 
2187  if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2188  ngx_http_upstream_finalize_request(r, u, 0);
2189  return;
2190  }
2191 
2192  ngx_http_upstream_process_non_buffered_downstream(r);
2193 
2194  } else {
2195  u->buffer.pos = u->buffer.start;
2196  u->buffer.last = u->buffer.start;
2197 
2199  ngx_http_upstream_finalize_request(r, u, 0);
2200  return;
2201  }
2202 
2203  if (u->peer.connection->read->ready || u->length == 0) {
2204  ngx_http_upstream_process_non_buffered_upstream(r, u);
2205  }
2206  }
2207 
2208  return;
2209  }
2210 
2211  /* TODO: preallocate event_pipe bufs, look "Content-Length" */
2212 
2213 #if (NGX_HTTP_CACHE)
2214 
2215  if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
2216  ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
2217  r->cache->file.fd = NGX_INVALID_FILE;
2218  }
2219 
2220  switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
2221 
2222  case NGX_ERROR:
2223  ngx_http_upstream_finalize_request(r, u, 0);
2224  return;
2225 
2226  case NGX_DECLINED:
2227  u->cacheable = 0;
2228  break;
2229 
2230  default: /* NGX_OK */
2231 
2232  if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
2233 
2234  r->cache->min_uses = u->conf->cache_min_uses;
2235  r->cache->body_start = u->conf->buffer_size;
2236  r->cache->file_cache = u->conf->cache->data;
2237 
2238  if (ngx_http_file_cache_create(r) != NGX_OK) {
2239  ngx_http_upstream_finalize_request(r, u, 0);
2240  return;
2241  }
2242  }
2243 
2244  break;
2245  }
2246 
2247  if (u->cacheable) {
2248  time_t now, valid;
2249 
2250  now = ngx_time();
2251 
2252  valid = r->cache->valid_sec;
2253 
2254  if (valid == 0) {
2255  valid = ngx_http_file_cache_valid(u->conf->cache_valid,
2256  u->headers_in.status_n);
2257  if (valid) {
2258  r->cache->valid_sec = now + valid;
2259  }
2260  }
2261 
2262  if (valid) {
2263  r->cache->last_modified = r->headers_out.last_modified_time;
2264  r->cache->date = now;
2265  r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
2266 
2268 
2269  } else {
2270  u->cacheable = 0;
2272  }
2273  }
2274 
2276  "http cacheable: %d", u->cacheable);
2277 
2278  if (u->cacheable == 0 && r->cache) {
2279  ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2280  }
2281 
2282 #endif
2283 
2284  p = u->pipe;
2285 
2287  p->output_ctx = r;
2288  p->tag = u->output.tag;
2289  p->bufs = u->conf->bufs;
2290  p->busy_size = u->conf->busy_buffers_size;
2291  p->upstream = u->peer.connection;
2292  p->downstream = c;
2293  p->pool = r->pool;
2294  p->log = c->log;
2295 
2296  p->cacheable = u->cacheable || u->store;
2297 
2298  p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
2299  if (p->temp_file == NULL) {
2300  ngx_http_upstream_finalize_request(r, u, 0);
2301  return;
2302  }
2303 
2305  p->temp_file->file.log = c->log;
2306  p->temp_file->path = u->conf->temp_path;
2307  p->temp_file->pool = r->pool;
2308 
2309  if (p->cacheable) {
2310  p->temp_file->persistent = 1;
2311 
2312  } else {
2314  p->temp_file->warn = "an upstream response is buffered "
2315  "to a temporary file";
2316  }
2317 
2320 
2322  if (p->preread_bufs == NULL) {
2323  ngx_http_upstream_finalize_request(r, u, 0);
2324  return;
2325  }
2326 
2327  p->preread_bufs->buf = &u->buffer;
2328  p->preread_bufs->next = NULL;
2329  u->buffer.recycled = 1;
2330 
2331  p->preread_size = u->buffer.last - u->buffer.pos;
2332 
2333  if (u->cacheable) {
2334 
2335  p->buf_to_file = ngx_calloc_buf(r->pool);
2336  if (p->buf_to_file == NULL) {
2337  ngx_http_upstream_finalize_request(r, u, 0);
2338  return;
2339  }
2340 
2341  p->buf_to_file->start = u->buffer.start;
2342  p->buf_to_file->pos = u->buffer.start;
2343  p->buf_to_file->last = u->buffer.pos;
2344  p->buf_to_file->temporary = 1;
2345  }
2346 
2348  /* the posted aio operation may corrupt a shadow buffer */
2349  p->single_buf = 1;
2350  }
2351 
2352  /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
2353  p->free_bufs = 1;
2354 
2355  /*
2356  * event_pipe would do u->buffer.last += p->preread_size
2357  * as though these bytes were read
2358  */
2359  u->buffer.last = u->buffer.pos;
2360 
2361  if (u->conf->cyclic_temp_file) {
2362 
2363  /*
2364  * we need to disable the use of sendfile() if we use cyclic temp file
2365  * because the writing a new data may interfere with sendfile()
2366  * that uses the same kernel file pages (at least on FreeBSD)
2367  */
2368 
2369  p->cyclic_temp_file = 1;
2370  c->sendfile = 0;
2371 
2372  } else {
2373  p->cyclic_temp_file = 0;
2374  }
2375 
2376  p->read_timeout = u->conf->read_timeout;
2377  p->send_timeout = clcf->send_timeout;
2378  p->send_lowat = clcf->send_lowat;
2379 
2380  p->length = -1;
2381 
2382  if (u->input_filter_init
2383  && u->input_filter_init(p->input_ctx) != NGX_OK)
2384  {
2385  ngx_http_upstream_finalize_request(r, u, 0);
2386  return;
2387  }
2388 
2389  u->read_event_handler = ngx_http_upstream_process_upstream;
2390  r->write_event_handler = ngx_http_upstream_process_downstream;
2391 
2392  ngx_http_upstream_process_upstream(r, u);
2393 }
2394 
2395 
2396 static void
2397 ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
2398 {
2399  int tcp_nodelay;
2400  ngx_connection_t *c;
2402 
2403  c = r->connection;
2405 
2406  /* TODO: prevent upgrade if not requested or not possible */
2407 
2408  r->keepalive = 0;
2409  c->log->action = "proxying upgraded connection";
2410 
2411  u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
2412  u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
2413  r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
2414  r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;
2415 
2416  if (clcf->tcp_nodelay) {
2417  tcp_nodelay = 1;
2418 
2419  if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
2420  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2421 
2422  if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2423  (const void *) &tcp_nodelay, sizeof(int)) == -1)
2424  {
2426  "setsockopt(TCP_NODELAY) failed");
2427  ngx_http_upstream_finalize_request(r, u, 0);
2428  return;
2429  }
2430 
2432  }
2433 
2436  "tcp_nodelay");
2437 
2438  if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY,
2439  (const void *) &tcp_nodelay, sizeof(int)) == -1)
2440  {
2442  "setsockopt(TCP_NODELAY) failed");
2443  ngx_http_upstream_finalize_request(r, u, 0);
2444  return;
2445  }
2446 
2448  }
2449  }
2450 
2452  ngx_http_upstream_finalize_request(r, u, 0);
2453  return;
2454  }
2455 
2456  if (u->peer.connection->read->ready
2457  || u->buffer.pos != u->buffer.last)
2458  {
2459  ngx_http_upstream_process_upgraded(r, 1, 1);
2460  }
2461 
2462  if (c->read->ready
2463  || r->header_in->pos != r->header_in->last)
2464  {
2465  ngx_http_upstream_process_upgraded(r, 0, 1);
2466  }
2467 }
2468 
2469 
2470 static void
2471 ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
2472 {
2473  ngx_http_upstream_process_upgraded(r, 0, 0);
2474 }
2475 
2476 
2477 static void
2478 ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
2479 {
2480  ngx_http_upstream_process_upgraded(r, 1, 1);
2481 }
2482 
2483 
2484 static void
2485 ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
2487 {
2488  ngx_http_upstream_process_upgraded(r, 1, 0);
2489 }
2490 
2491 
2492 static void
2493 ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
2495 {
2496  ngx_http_upstream_process_upgraded(r, 0, 1);
2497 }
2498 
2499 
2500 static void
2501 ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
2502  ngx_uint_t from_upstream, ngx_uint_t do_write)
2503 {
2504  size_t size;
2505  ssize_t n;
2506  ngx_buf_t *b;
2507  ngx_connection_t *c, *downstream, *upstream, *dst, *src;
2510 
2511  c = r->connection;
2512  u = r->upstream;
2513 
2515  "http upstream process upgraded, fu:%ui", from_upstream);
2516 
2517  downstream = c;
2518  upstream = u->peer.connection;
2519 
2520  if (downstream->write->timedout) {
2521  c->timedout = 1;
2522  ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
2523  ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
2524  return;
2525  }
2526 
2527  if (upstream->read->timedout || upstream->write->timedout) {
2528  ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2529  ngx_http_upstream_finalize_request(r, u, 0);
2530  return;
2531  }
2532 
2533  if (from_upstream) {
2534  src = upstream;
2535  dst = downstream;
2536  b = &u->buffer;
2537 
2538  } else {
2539  src = downstream;
2540  dst = upstream;
2541  b = &u->from_client;
2542 
2543  if (r->header_in->last > r->header_in->pos) {
2544  b = r->header_in;
2545  b->end = b->last;
2546  do_write = 1;
2547  }
2548 
2549  if (b->start == NULL) {
2550  b->start = ngx_palloc(r->pool, u->conf->buffer_size);
2551  if (b->start == NULL) {
2552  ngx_http_upstream_finalize_request(r, u, 0);
2553  return;
2554  }
2555 
2556  b->pos = b->start;
2557  b->last = b->start;
2558  b->end = b->start + u->conf->buffer_size;
2559  b->temporary = 1;
2560  b->tag = u->output.tag;
2561  }
2562  }
2563 
2564  for ( ;; ) {
2565 
2566  if (do_write) {
2567 
2568  size = b->last - b->pos;
2569 
2570  if (size && dst->write->ready) {
2571 
2572  n = dst->send(dst, b->pos, size);
2573 
2574  if (n == NGX_ERROR) {
2575  ngx_http_upstream_finalize_request(r, u, 0);
2576  return;
2577  }
2578 
2579  if (n > 0) {
2580  b->pos += n;
2581 
2582  if (b->pos == b->last) {
2583  b->pos = b->start;
2584  b->last = b->start;
2585  }
2586  }
2587  }
2588  }
2589 
2590  size = b->end - b->last;
2591 
2592  if (size && src->read->ready) {
2593 
2594  n = src->recv(src, b->last, size);
2595 
2596  if (n == NGX_AGAIN || n == 0) {
2597  break;
2598  }
2599 
2600  if (n > 0) {
2601  do_write = 1;
2602  b->last += n;
2603 
2604  continue;
2605  }
2606 
2607  if (n == NGX_ERROR) {
2608  src->read->eof = 1;
2609  }
2610  }
2611 
2612  break;
2613  }
2614 
2615  if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
2616  || (downstream->read->eof && u->from_client.pos == u->from_client.last)
2617  || (downstream->read->eof && upstream->read->eof))
2618  {
2620  "http upstream upgraded done");
2621  ngx_http_upstream_finalize_request(r, u, 0);
2622  return;
2623  }
2624 
2626 
2627  if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
2628  != NGX_OK)
2629  {
2630  ngx_http_upstream_finalize_request(r, u, 0);
2631  return;
2632  }
2633 
2634  if (upstream->write->active && !upstream->write->ready) {
2635  ngx_add_timer(upstream->write, u->conf->send_timeout);
2636 
2637  } else if (upstream->write->timer_set) {
2638  ngx_del_timer(upstream->write);
2639  }
2640 
2641  if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
2642  ngx_http_upstream_finalize_request(r, u, 0);
2643  return;
2644  }
2645 
2646  if (upstream->read->active && !upstream->read->ready) {
2647  ngx_add_timer(upstream->read, u->conf->read_timeout);
2648 
2649  } else if (upstream->read->timer_set) {
2650  ngx_del_timer(upstream->read);
2651  }
2652 
2653  if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
2654  != NGX_OK)
2655  {
2656  ngx_http_upstream_finalize_request(r, u, 0);
2657  return;
2658  }
2659 
2660  if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {
2661  ngx_http_upstream_finalize_request(r, u, 0);
2662  return;
2663  }
2664 
2665  if (downstream->write->active && !downstream->write->ready) {
2666  ngx_add_timer(downstream->write, clcf->send_timeout);
2667 
2668  } else if (downstream->write->timer_set) {
2669  ngx_del_timer(downstream->write);
2670  }
2671 }
2672 
2673 
2674 static void
2675 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
2676 {
2677  ngx_event_t *wev;
2678  ngx_connection_t *c;
2680 
2681  c = r->connection;
2682  u = r->upstream;
2683  wev = c->write;
2684 
2686  "http upstream process non buffered downstream");
2687 
2688  c->log->action = "sending to client";
2689 
2690  if (wev->timedout) {
2691  c->timedout = 1;
2692  ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
2693  ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
2694  return;
2695  }
2696 
2697  ngx_http_upstream_process_non_buffered_request(r, 1);
2698 }
2699 
2700 
2701 static void
2702 ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
2704 {
2705  ngx_connection_t *c;
2706 
2707  c = u->peer.connection;
2708 
2710  "http upstream process non buffered upstream");
2711 
2712  c->log->action = "reading upstream";
2713 
2714  if (c->read->timedout) {
2715  ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2716  ngx_http_upstream_finalize_request(r, u, 0);
2717  return;
2718  }
2719 
2720  ngx_http_upstream_process_non_buffered_request(r, 0);
2721 }
2722 
2723 
2724 static void
2725 ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
2726  ngx_uint_t do_write)
2727 {
2728  size_t size;
2729  ssize_t n;
2730  ngx_buf_t *b;
2731  ngx_int_t rc;
2732  ngx_connection_t *downstream, *upstream;
2735 
2736  u = r->upstream;
2737  downstream = r->connection;
2738  upstream = u->peer.connection;
2739 
2740  b = &u->buffer;
2741 
2742  do_write = do_write || u->length == 0;
2743 
2744  for ( ;; ) {
2745 
2746  if (do_write) {
2747 
2748  if (u->out_bufs || u->busy_bufs) {
2749  rc = ngx_http_output_filter(r, u->out_bufs);
2750 
2751  if (rc == NGX_ERROR) {
2752  ngx_http_upstream_finalize_request(r, u, 0);
2753  return;
2754  }
2755 
2757  &u->out_bufs, u->output.tag);
2758  }
2759 
2760  if (u->busy_bufs == NULL) {
2761 
2762  if (u->length == 0
2763  || upstream->read->eof
2764  || upstream->read->error)
2765  {
2766  ngx_http_upstream_finalize_request(r, u, 0);
2767  return;
2768  }
2769 
2770  b->pos = b->start;
2771  b->last = b->start;
2772  }
2773  }
2774 
2775  size = b->end - b->last;
2776 
2777  if (size && upstream->read->ready) {
2778 
2779  n = upstream->recv(upstream, b->last, size);
2780 
2781  if (n == NGX_AGAIN) {
2782  break;
2783  }
2784 
2785  if (n > 0) {
2786  u->state->response_length += n;
2787 
2788  if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2789  ngx_http_upstream_finalize_request(r, u, 0);
2790  return;
2791  }
2792  }
2793 
2794  do_write = 1;
2795 
2796  continue;
2797  }
2798 
2799  break;
2800  }
2801 
2803 
2804  if (downstream->data == r) {
2805  if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
2806  != NGX_OK)
2807  {
2808  ngx_http_upstream_finalize_request(r, u, 0);
2809  return;
2810  }
2811  }
2812 
2813  if (downstream->write->active && !downstream->write->ready) {
2814  ngx_add_timer(downstream->write, clcf->send_timeout);
2815 
2816  } else if (downstream->write->timer_set) {
2817  ngx_del_timer(downstream->write);
2818  }
2819 
2820  if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
2821  ngx_http_upstream_finalize_request(r, u, 0);
2822  return;
2823  }
2824 
2825  if (upstream->read->active && !upstream->read->ready) {
2826  ngx_add_timer(upstream->read, u->conf->read_timeout);
2827 
2828  } else if (upstream->read->timer_set) {
2829  ngx_del_timer(upstream->read);
2830  }
2831 }
2832 
2833 
2834 static ngx_int_t
2835 ngx_http_upstream_non_buffered_filter_init(void *data)
2836 {
2837  return NGX_OK;
2838 }
2839 
2840 
2841 static ngx_int_t
2842 ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
2843 {
2844  ngx_http_request_t *r = data;
2845 
2846  ngx_buf_t *b;
2847  ngx_chain_t *cl, **ll;
2849 
2850  u = r->upstream;
2851 
2852  for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2853  ll = &cl->next;
2854  }
2855 
2856  cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2857  if (cl == NULL) {
2858  return NGX_ERROR;
2859  }
2860 
2861  *ll = cl;
2862 
2863  cl->buf->flush = 1;
2864  cl->buf->memory = 1;
2865 
2866  b = &u->buffer;
2867 
2868  cl->buf->pos = b->last;
2869  b->last += bytes;
2870  cl->buf->last = b->last;
2871  cl->buf->tag = u->output.tag;
2872 
2873  if (u->length == -1) {
2874  return NGX_OK;
2875  }
2876 
2877  u->length -= bytes;
2878 
2879  return NGX_OK;
2880 }
2881 
2882 
2883 static void
2884 ngx_http_upstream_process_downstream(ngx_http_request_t *r)
2885 {
2886  ngx_event_t *wev;
2887  ngx_connection_t *c;
2888  ngx_event_pipe_t *p;
2890 
2891  c = r->connection;
2892  u = r->upstream;
2893  p = u->pipe;
2894  wev = c->write;
2895 
2897  "http upstream process downstream");
2898 
2899  c->log->action = "sending to client";
2900 
2901  if (wev->timedout) {
2902 
2903  if (wev->delayed) {
2904 
2905  wev->timedout = 0;
2906  wev->delayed = 0;
2907 
2908  if (!wev->ready) {
2909  ngx_add_timer(wev, p->send_timeout);
2910 
2911  if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
2912  ngx_http_upstream_finalize_request(r, u, 0);
2913  }
2914 
2915  return;
2916  }
2917 
2918  if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
2919  ngx_http_upstream_finalize_request(r, u, 0);
2920  return;
2921  }
2922 
2923  } else {
2924  p->downstream_error = 1;
2925  c->timedout = 1;
2926  ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
2927  }
2928 
2929  } else {
2930 
2931  if (wev->delayed) {
2932 
2934  "http downstream delayed");
2935 
2936  if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
2937  ngx_http_upstream_finalize_request(r, u, 0);
2938  }
2939 
2940  return;
2941  }
2942 
2943  if (ngx_event_pipe(p, 1) == NGX_ABORT) {
2944  ngx_http_upstream_finalize_request(r, u, 0);
2945  return;
2946  }
2947  }
2948 
2949  ngx_http_upstream_process_request(r);
2950 }
2951 
2952 
2953 static void
2954 ngx_http_upstream_process_upstream(ngx_http_request_t *r,
2956 {
2957  ngx_connection_t *c;
2958 
2959  c = u->peer.connection;
2960 
2962  "http upstream process upstream");
2963 
2964  c->log->action = "reading upstream";
2965 
2966  if (c->read->timedout) {
2967  u->pipe->upstream_error = 1;
2968  ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2969 
2970  } else {
2971  if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
2972  ngx_http_upstream_finalize_request(r, u, 0);
2973  return;
2974  }
2975  }
2976 
2977  ngx_http_upstream_process_request(r);
2978 }
2979 
2980 
2981 static void
2982 ngx_http_upstream_process_request(ngx_http_request_t *r)
2983 {
2984  ngx_temp_file_t *tf;
2985  ngx_event_pipe_t *p;
2987 
2988  u = r->upstream;
2989  p = u->pipe;
2990 
2991  if (u->peer.connection) {
2992 
2993  if (u->store) {
2994 
2995  if (p->upstream_eof || p->upstream_done) {
2996 
2997  tf = u->pipe->temp_file;
2998 
2999  if (u->headers_in.status_n == NGX_HTTP_OK
3000  && (u->headers_in.content_length_n == -1
3001  || (u->headers_in.content_length_n == tf->offset)))
3002  {
3003  ngx_http_upstream_store(r, u);
3004  u->store = 0;
3005  }
3006  }
3007  }
3008 
3009 #if (NGX_HTTP_CACHE)
3010 
3011  if (u->cacheable) {
3012 
3013  if (p->upstream_done) {
3015 
3016  } else if (p->upstream_eof) {
3017 
3018  tf = u->pipe->temp_file;
3019 
3020  if (u->headers_in.content_length_n == -1
3022  == tf->offset - (off_t) r->cache->body_start)
3023  {
3025 
3026  } else {
3027  ngx_http_file_cache_free(r->cache, tf);
3028  }
3029 
3030  } else if (p->upstream_error) {
3031  ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
3032  }
3033  }
3034 
3035 #endif
3036 
3037  if (p->upstream_done || p->upstream_eof || p->upstream_error) {
3039  "http upstream exit: %p", p->out);
3040 #if 0
3041  ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3042 #endif
3043  ngx_http_upstream_finalize_request(r, u, 0);
3044  return;
3045  }
3046  }
3047 
3048  if (p->downstream_error) {
3050  "http upstream downstream error");
3051 
3052  if (!u->cacheable && !u->store && u->peer.connection) {
3053  ngx_http_upstream_finalize_request(r, u, 0);
3054  }
3055  }
3056 }
3057 
3058 
3059 static void
3060 ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
3061 {
3062  size_t root;
3063  time_t lm;
3064  ngx_str_t path;
3065  ngx_temp_file_t *tf;
3067 
3068  tf = u->pipe->temp_file;
3069 
3070  if (tf->file.fd == NGX_INVALID_FILE) {
3071 
3072  /* create file for empty 200 response */
3073 
3074  tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
3075  if (tf == NULL) {
3076  return;
3077  }
3078 
3079  tf->file.fd = NGX_INVALID_FILE;
3080  tf->file.log = r->connection->log;
3081  tf->path = u->conf->temp_path;
3082  tf->pool = r->pool;
3083  tf->persistent = 1;
3084 
3085  if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
3086  tf->persistent, tf->clean, tf->access)
3087  != NGX_OK)
3088  {
3089  return;
3090  }
3091 
3092  u->pipe->temp_file = tf;
3093  }
3094 
3095  ext.access = u->conf->store_access;
3096  ext.path_access = u->conf->store_access;
3097  ext.time = -1;
3098  ext.create_path = 1;
3099  ext.delete_file = 1;
3100  ext.log = r->connection->log;
3101 
3102  if (u->headers_in.last_modified) {
3103 
3106 
3107  if (lm != NGX_ERROR) {
3108  ext.time = lm;
3109  ext.fd = tf->file.fd;
3110  }
3111  }
3112 
3113  if (u->conf->store_lengths == NULL) {
3114 
3115  ngx_http_map_uri_to_path(r, &path, &root, 0);
3116 
3117  } else {
3118  if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
3119  u->conf->store_values->elts)
3120  == NULL)
3121  {
3122  return;
3123  }
3124  }
3125 
3126  path.len--;
3127 
3129  "upstream stores \"%s\" to \"%s\"",
3130  tf->file.name.data, path.data);
3131 
3132  (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
3133 }
3134 
3135 
3136 static void
3137 ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
3138 {
3140  "http upstream dummy handler");
3141 }
3142 
3143 
3144 static void
3145 ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3146  ngx_uint_t ft_type)
3147 {
3148  ngx_uint_t status, state;
3149 
3151  "http next upstream, %xi", ft_type);
3152 
3153 #if 0
3154  ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3155 #endif
3156 
3157  if (u->peer.sockaddr) {
3158 
3159  if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
3160  state = NGX_PEER_NEXT;
3161  } else {
3162  state = NGX_PEER_FAILED;
3163  }
3164 
3165  u->peer.free(&u->peer, u->peer.data, state);
3166  u->peer.sockaddr = NULL;
3167  }
3168 
3169  if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
3171  "upstream timed out");
3172  }
3173 
3174  if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
3175  status = 0;
3176 
3177  /* TODO: inform balancer instead */
3178 
3179  u->peer.tries++;
3180 
3181  } else {
3182  switch(ft_type) {
3183 
3185  status = NGX_HTTP_GATEWAY_TIME_OUT;
3186  break;
3187 
3190  break;
3191 
3193  status = NGX_HTTP_NOT_FOUND;
3194  break;
3195 
3196  /*
3197  * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
3198  * never reach here
3199  */
3200 
3201  default:
3202  status = NGX_HTTP_BAD_GATEWAY;
3203  }
3204  }
3205 
3206  if (r->connection->error) {
3207  ngx_http_upstream_finalize_request(r, u,
3209  return;
3210  }
3211 
3212  if (status) {
3213  u->state->status = status;
3214 
3215  if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
3216 
3217 #if (NGX_HTTP_CACHE)
3218 
3219  if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
3220  && (u->conf->cache_use_stale & ft_type))
3221  {
3222  ngx_int_t rc;
3223 
3224  rc = u->reinit_request(r);
3225 
3226  if (rc == NGX_OK) {
3227  u->cache_status = NGX_HTTP_CACHE_STALE;
3228  rc = ngx_http_upstream_cache_send(r, u);
3229  }
3230 
3231  ngx_http_upstream_finalize_request(r, u, rc);
3232  return;
3233  }
3234 #endif
3235 
3236  ngx_http_upstream_finalize_request(r, u, status);
3237  return;
3238  }
3239  }
3240 
3241  if (u->peer.connection) {
3243  "close http upstream connection: %d",
3244  u->peer.connection->fd);
3245 #if (NGX_HTTP_SSL)
3246 
3247  if (u->peer.connection->ssl) {
3248  u->peer.connection->ssl->no_wait_shutdown = 1;
3249  u->peer.connection->ssl->no_send_shutdown = 1;
3250 
3251  (void) ngx_ssl_shutdown(u->peer.connection);
3252  }
3253 #endif
3254 
3255  if (u->peer.connection->pool) {
3257  }
3258 
3260  u->peer.connection = NULL;
3261  }
3262 
3263 #if 0
3264  if (u->conf->busy_lock && !u->busy_locked) {
3265  ngx_http_upstream_busy_lock(p);
3266  return;
3267  }
3268 #endif
3269 
3270  ngx_http_upstream_connect(r, u);
3271 }
3272 
3273 
3274 static void
3275 ngx_http_upstream_cleanup(void *data)
3276 {
3277  ngx_http_request_t *r = data;
3278 
3280  "cleanup http upstream request: \"%V\"", &r->uri);
3281 
3282  ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
3283 }
3284 
3285 
3286 static void
3287 ngx_http_upstream_finalize_request(ngx_http_request_t *r,
3289 {
3290  ngx_time_t *tp;
3291 
3293  "finalize http upstream request: %i", rc);
3294 
3295  if (u->cleanup) {
3296  *u->cleanup = NULL;
3297  u->cleanup = NULL;
3298  }
3299 
3300  if (u->resolved && u->resolved->ctx) {
3302  u->resolved->ctx = NULL;
3303  }
3304 
3305  if (u->state && u->state->response_sec) {
3306  tp = ngx_timeofday();
3307  u->state->response_sec = tp->sec - u->state->response_sec;
3308  u->state->response_msec = tp->msec - u->state->response_msec;
3309 
3310  if (u->pipe && u->pipe->read_length) {
3312  }
3313  }
3314 
3315  u->finalize_request(r, rc);
3316 
3317  if (u->peer.free && u->peer.sockaddr) {
3318  u->peer.free(&u->peer, u->peer.data, 0);
3319  u->peer.sockaddr = NULL;
3320  }
3321 
3322  if (u->peer.connection) {
3323 
3324 #if (NGX_HTTP_SSL)
3325 
3326  /* TODO: do not shutdown persistent connection */
3327 
3328  if (u->peer.connection->ssl) {
3329 
3330  /*
3331  * We send the "close notify" shutdown alert to the upstream only
3332  * and do not wait its "close notify" shutdown alert.
3333  * It is acceptable according to the TLS standard.
3334  */
3335 
3336  u->peer.connection->ssl->no_wait_shutdown = 1;
3337 
3338  (void) ngx_ssl_shutdown(u->peer.connection);
3339  }
3340 #endif
3341 
3343  "close http upstream connection: %d",
3344  u->peer.connection->fd);
3345 
3346  if (u->peer.connection->pool) {
3348  }
3349 
3351  }
3352 
3353  u->peer.connection = NULL;
3354 
3355  if (u->pipe && u->pipe->temp_file) {
3357  "http upstream temp fd: %d",
3358  u->pipe->temp_file->file.fd);
3359  }
3360 
3361  if (u->store && u->pipe && u->pipe->temp_file
3362  && u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
3363  {
3365  == NGX_FILE_ERROR)
3366  {
3368  ngx_delete_file_n " \"%s\" failed",
3369  u->pipe->temp_file->file.name.data);
3370  }
3371  }
3372 
3373 #if (NGX_HTTP_CACHE)
3374 
3375  if (r->cache) {
3376 
3377  if (u->cacheable) {
3378 
3379  if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
3380  time_t valid;
3381 
3382  valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
3383 
3384  if (valid) {
3385  r->cache->valid_sec = ngx_time() + valid;
3386  r->cache->error = rc;
3387  }
3388  }
3389  }
3390 
3391  ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
3392  }
3393 
3394 #endif
3395 
3396  if (u->header_sent
3397  && rc != NGX_HTTP_REQUEST_TIME_OUT
3398  && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
3399  {
3400  rc = 0;
3401  }
3402 
3403  if (rc == NGX_DECLINED) {
3404  return;
3405  }
3406 
3407  r->connection->log->action = "sending to client";
3408 
3409  if (rc == 0
3410  && !r->header_only
3411 #if (NGX_HTTP_CACHE)
3412  && !r->cached
3413 #endif
3414  )
3415  {
3417  }
3418 
3420 }
3421 
3422 
3423 static ngx_int_t
3424 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3425  ngx_uint_t offset)
3426 {
3427  ngx_table_elt_t **ph;
3428 
3429  ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
3430 
3431  if (*ph == NULL) {
3432  *ph = h;
3433  }
3434 
3435  return NGX_OK;
3436 }
3437 
3438 
3439 static ngx_int_t
3440 ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3441  ngx_uint_t offset)
3442 {
3443  return NGX_OK;
3444 }
3445 
3446 
3447 static ngx_int_t
3448 ngx_http_upstream_process_content_length(ngx_http_request_t *r,
3449  ngx_table_elt_t *h, ngx_uint_t offset)
3450 {
3452 
3453  u = r->upstream;
3454 
3455  u->headers_in.content_length = h;
3457 
3458  return NGX_OK;
3459 }
3460 
3461 
3462 static ngx_int_t
3463 ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
3464  ngx_uint_t offset)
3465 {
3466 #if (NGX_HTTP_CACHE)
3468 
3469  u = r->upstream;
3470 
3472  u->cacheable = 0;
3473  }
3474 #endif
3475 
3476  return NGX_OK;
3477 }
3478 
3479 
3480 static ngx_int_t
3481 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
3482  ngx_table_elt_t *h, ngx_uint_t offset)
3483 {
3484  ngx_array_t *pa;
3485  ngx_table_elt_t **ph;
3487 
3488  u = r->upstream;
3489  pa = &u->headers_in.cache_control;
3490 
3491  if (pa->elts == NULL) {
3492  if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
3493  {
3494  return NGX_ERROR;
3495  }
3496  }
3497 
3498  ph = ngx_array_push(pa);
3499  if (ph == NULL) {
3500  return NGX_ERROR;
3501  }
3502 
3503  *ph = h;
3504 
3505 #if (NGX_HTTP_CACHE)
3506  {
3507  u_char *p, *last;
3508  ngx_int_t n;
3509 
3511  return NGX_OK;
3512  }
3513 
3514  if (r->cache == NULL) {
3515  return NGX_OK;
3516  }
3517 
3518  if (r->cache->valid_sec != 0) {
3519  return NGX_OK;
3520  }
3521 
3522  p = h->value.data;
3523  last = p + h->value.len;
3524 
3525  if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
3526  || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
3527  || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
3528  {
3529  u->cacheable = 0;
3530  return NGX_OK;
3531  }
3532 
3533  p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
3534 
3535  if (p == NULL) {
3536  return NGX_OK;
3537  }
3538 
3539  n = 0;
3540 
3541  for (p += 8; p < last; p++) {
3542  if (*p == ',' || *p == ';' || *p == ' ') {
3543  break;
3544  }
3545 
3546  if (*p >= '0' && *p <= '9') {
3547  n = n * 10 + *p - '0';
3548  continue;
3549  }
3550 
3551  u->cacheable = 0;
3552  return NGX_OK;
3553  }
3554 
3555  if (n == 0) {
3556  u->cacheable = 0;
3557  return NGX_OK;
3558  }
3559 
3560  r->cache->valid_sec = ngx_time() + n;
3561  }
3562 #endif
3563 
3564  return NGX_OK;
3565 }
3566 
3567 
3568 static ngx_int_t
3569 ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
3570  ngx_uint_t offset)
3571 {
3573 
3574  u = r->upstream;
3575  u->headers_in.expires = h;
3576 
3577 #if (NGX_HTTP_CACHE)
3578  {
3579  time_t expires;
3580 
3582  return NGX_OK;
3583  }
3584 
3585  if (r->cache == NULL) {
3586  return NGX_OK;
3587  }
3588 
3589  if (r->cache->valid_sec != 0) {
3590  return NGX_OK;
3591  }
3592 
3593  expires = ngx_http_parse_time(h->value.data, h->value.len);
3594 
3595  if (expires == NGX_ERROR || expires < ngx_time()) {
3596  u->cacheable = 0;
3597  return NGX_OK;
3598  }
3599 
3600  r->cache->valid_sec = expires;
3601  }
3602 #endif
3603 
3604  return NGX_OK;
3605 }
3606 
3607 
3608 static ngx_int_t
3609 ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
3610  ngx_table_elt_t *h, ngx_uint_t offset)
3611 {
3613 
3614  u = r->upstream;
3615  u->headers_in.x_accel_expires = h;
3616 
3617 #if (NGX_HTTP_CACHE)
3618  {
3619  u_char *p;
3620  size_t len;
3621  ngx_int_t n;
3622 
3624  return NGX_OK;
3625  }
3626 
3627  if (r->cache == NULL) {
3628  return NGX_OK;
3629  }
3630 
3631  len = h->value.len;
3632  p = h->value.data;
3633 
3634  if (p[0] != '@') {
3635  n = ngx_atoi(p, len);
3636 
3637  switch (n) {
3638  case 0:
3639  u->cacheable = 0;
3640  /* fall through */
3641 
3642  case NGX_ERROR:
3643  return NGX_OK;
3644 
3645  default:
3646  r->cache->valid_sec = ngx_time() + n;
3647  return NGX_OK;
3648  }
3649  }
3650 
3651  p++;
3652  len--;
3653 
3654  n = ngx_atoi(p, len);
3655 
3656  if (n != NGX_ERROR) {
3657  r->cache->valid_sec = n;
3658  }
3659  }
3660 #endif
3661 
3662  return NGX_OK;
3663 }
3664 
3665 
3666 static ngx_int_t
3667 ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
3668  ngx_uint_t offset)
3669 {
3670  ngx_int_t n;
3672 
3673  u = r->upstream;
3675 
3677  return NGX_OK;
3678  }
3679 
3680  n = ngx_atoi(h->value.data, h->value.len);
3681 
3682  if (n != NGX_ERROR) {
3683  r->limit_rate = (size_t) n;
3684  }
3685 
3686  return NGX_OK;
3687 }
3688 
3689 
3690 static ngx_int_t
3691 ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
3692  ngx_uint_t offset)
3693 {
3694  u_char c0, c1, c2;
3696 
3697  u = r->upstream;
3698 
3700  return NGX_OK;
3701  }
3702 
3703  if (u->conf->change_buffering) {
3704 
3705  if (h->value.len == 2) {
3706  c0 = ngx_tolower(h->value.data[0]);
3707  c1 = ngx_tolower(h->value.data[1]);
3708 
3709  if (c0 == 'n' && c1 == 'o') {
3710  u->buffering = 0;
3711  }
3712 
3713  } else if (h->value.len == 3) {
3714  c0 = ngx_tolower(h->value.data[0]);
3715  c1 = ngx_tolower(h->value.data[1]);
3716  c2 = ngx_tolower(h->value.data[2]);
3717 
3718  if (c0 == 'y' && c1 == 'e' && c2 == 's') {
3719  u->buffering = 1;
3720  }
3721  }
3722  }
3723 
3724  return NGX_OK;
3725 }
3726 
3727 
3728 static ngx_int_t
3729 ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
3730  ngx_uint_t offset)
3731 {
3733  return NGX_OK;
3734  }
3735 
3737 
3738  return NGX_OK;
3739 }
3740 
3741 
3742 static ngx_int_t
3743 ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
3744  ngx_uint_t offset)
3745 {
3746  r->upstream->headers_in.connection = h;
3747 
3748  if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3749  (u_char *) "close", 5 - 1)
3750  != NULL)
3751  {
3753  }
3754 
3755  return NGX_OK;
3756 }
3757 
3758 
3759 static ngx_int_t
3760 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
3761  ngx_table_elt_t *h, ngx_uint_t offset)
3762 {
3764 
3765  if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3766  (u_char *) "chunked", 7 - 1)
3767  != NULL)
3768  {
3769  r->upstream->headers_in.chunked = 1;
3770  }
3771 
3772  return NGX_OK;
3773 }
3774 
3775 
3776 static ngx_int_t
3777 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3778  ngx_uint_t offset)
3779 {
3780  ngx_table_elt_t *ho, **ph;
3781 
3782  ho = ngx_list_push(&r->headers_out.headers);
3783  if (ho == NULL) {
3784  return NGX_ERROR;
3785  }
3786 
3787  *ho = *h;
3788 
3789  if (offset) {
3790  ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
3791  *ph = ho;
3792  }
3793 
3794  return NGX_OK;
3795 }
3796 
3797 
3798 static ngx_int_t
3799 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
3800  ngx_table_elt_t *h, ngx_uint_t offset)
3801 {
3802  ngx_array_t *pa;
3803  ngx_table_elt_t *ho, **ph;
3804 
3805  pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
3806 
3807  if (pa->elts == NULL) {
3808  if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
3809  {
3810  return NGX_ERROR;
3811  }
3812  }
3813 
3814  ph = ngx_array_push(pa);
3815  if (ph == NULL) {
3816  return NGX_ERROR;
3817  }
3818 
3819  ho = ngx_list_push(&r->headers_out.headers);
3820  if (ho == NULL) {
3821  return NGX_ERROR;
3822  }
3823 
3824  *ho = *h;
3825  *ph = ho;
3826 
3827  return NGX_OK;
3828 }
3829 
3830 
3831 static ngx_int_t
3832 ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
3833  ngx_uint_t offset)
3834 {
3835  u_char *p, *last;
3836 
3838  r->headers_out.content_type = h->value;
3840 
3841  for (p = h->value.data; *p; p++) {
3842 
3843  if (*p != ';') {
3844  continue;
3845  }
3846 
3847  last = p;
3848 
3849  while (*++p == ' ') { /* void */ }
3850 
3851  if (*p == '\0') {
3852  return NGX_OK;
3853  }
3854 
3855  if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
3856  continue;
3857  }
3858 
3859  p += 8;
3860 
3861  r->headers_out.content_type_len = last - h->value.data;
3862 
3863  if (*p == '"') {
3864  p++;
3865  }
3866 
3867  last = h->value.data + h->value.len;
3868 
3869  if (*(last - 1) == '"') {
3870  last--;
3871  }
3872 
3873  r->headers_out.charset.len = last - p;
3874  r->headers_out.charset.data = p;
3875 
3876  return NGX_OK;
3877  }
3878 
3879  return NGX_OK;
3880 }
3881 
3882 
3883 static ngx_int_t
3884 ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
3885  ngx_uint_t offset)
3886 {
3887  ngx_table_elt_t *ho;
3888 
3889  ho = ngx_list_push(&r->headers_out.headers);
3890  if (ho == NULL) {
3891  return NGX_ERROR;
3892  }
3893 
3894  *ho = *h;
3895 
3896  r->headers_out.last_modified = ho;
3897 
3898 #if (NGX_HTTP_CACHE)
3899 
3900  if (r->upstream->cacheable) {
3902  h->value.len);
3903  }
3904 
3905 #endif
3906 
3907  return NGX_OK;
3908 }
3909 
3910 
3911 static ngx_int_t
3912 ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
3913  ngx_uint_t offset)
3914 {
3915  ngx_int_t rc;
3916  ngx_table_elt_t *ho;
3917 
3918  ho = ngx_list_push(&r->headers_out.headers);
3919  if (ho == NULL) {
3920  return NGX_ERROR;
3921  }
3922 
3923  *ho = *h;
3924 
3925  if (r->upstream->rewrite_redirect) {
3926  rc = r->upstream->rewrite_redirect(r, ho, 0);
3927 
3928  if (rc == NGX_DECLINED) {
3929  return NGX_OK;
3930  }
3931 
3932  if (rc == NGX_OK) {
3933  r->headers_out.location = ho;
3934 
3936  "rewritten location: \"%V\"", &ho->value);
3937  }
3938 
3939  return rc;
3940  }
3941 
3942  if (ho->value.data[0] != '/') {
3943  r->headers_out.location = ho;
3944  }
3945 
3946  /*
3947  * we do not set r->headers_out.location here to avoid the handling
3948  * the local redirects without a host name by ngx_http_header_filter()
3949  */
3950 
3951  return NGX_OK;
3952 }
3953 
3954 
3955 static ngx_int_t
3956 ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
3957  ngx_uint_t offset)
3958 {
3959  u_char *p;
3960  ngx_int_t rc;
3961  ngx_table_elt_t *ho;
3962 
3963  ho = ngx_list_push(&r->headers_out.headers);
3964  if (ho == NULL) {
3965  return NGX_ERROR;
3966  }
3967 
3968  *ho = *h;
3969 
3970  if (r->upstream->rewrite_redirect) {
3971 
3972  p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1);
3973 
3974  if (p) {
3975  rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);
3976 
3977  } else {
3978  return NGX_OK;
3979  }
3980 
3981  if (rc == NGX_DECLINED) {
3982  return NGX_OK;
3983  }
3984 
3985  if (rc == NGX_OK) {
3986  r->headers_out.refresh = ho;
3987 
3989  "rewritten refresh: \"%V\"", &ho->value);
3990  }
3991 
3992  return rc;
3993  }
3994 
3995  r->headers_out.refresh = ho;
3996 
3997  return NGX_OK;
3998 }
3999 
4000 
4001 static ngx_int_t
4002 ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
4003  ngx_uint_t offset)
4004 {
4005  ngx_int_t rc;
4006  ngx_table_elt_t *ho;
4007 
4008  ho = ngx_list_push(&r->headers_out.headers);
4009  if (ho == NULL) {
4010  return NGX_ERROR;
4011  }
4012 
4013  *ho = *h;
4014 
4015  if (r->upstream->rewrite_cookie) {
4016  rc = r->upstream->rewrite_cookie(r, ho);
4017 
4018  if (rc == NGX_DECLINED) {
4019  return NGX_OK;
4020  }
4021 
4022 #if (NGX_DEBUG)
4023  if (rc == NGX_OK) {
4025  "rewritten cookie: \"%V\"", &ho->value);
4026  }
4027 #endif
4028 
4029  return rc;
4030  }
4031 
4032  return NGX_OK;
4033 }
4034 
4035 
4036 static ngx_int_t
4037 ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
4038  ngx_table_elt_t *h, ngx_uint_t offset)
4039 {
4040  ngx_table_elt_t *ho;
4041 
4042 #if (NGX_HTTP_CACHE)
4043 
4044  if (r->cached) {
4045  r->allow_ranges = 1;
4046  return NGX_OK;
4047 
4048  }
4049 
4050 #endif
4051 
4052  ho = ngx_list_push(&r->headers_out.headers);
4053  if (ho == NULL) {
4054  return NGX_ERROR;
4055  }
4056 
4057  *ho = *h;
4058 
4059  r->headers_out.accept_ranges = ho;
4060 
4061  return NGX_OK;
4062 }
4063 
4064 
4065 #if (NGX_HTTP_GZIP)
4066 
4067 static ngx_int_t
4068 ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
4069  ngx_table_elt_t *h, ngx_uint_t offset)
4070 {
4071  ngx_table_elt_t *ho;
4072 
4073  ho = ngx_list_push(&r->headers_out.headers);
4074  if (ho == NULL) {
4075  return NGX_ERROR;
4076  }
4077 
4078  *ho = *h;
4079 
4080  r->headers_out.content_encoding = ho;
4081 
4082  return NGX_OK;
4083 }
4084 
4085 #endif
4086 
4087 
4088 static ngx_int_t
4089 ngx_http_upstream_add_variables(ngx_conf_t *cf)
4090 {
4091  ngx_http_variable_t *var, *v;
4092 
4093  for (v = ngx_http_upstream_vars; v->name.len; v++) {
4094  var = ngx_http_add_variable(cf, &v->name, v->flags);
4095  if (var == NULL) {
4096  return NGX_ERROR;
4097  }
4098 
4099  var->get_handler = v->get_handler;
4100  var->data = v->data;
4101  }
4102 
4103  return NGX_OK;
4104 }
4105 
4106 
4107 static ngx_int_t
4108 ngx_http_upstream_addr_variable(ngx_http_request_t *r,
4109  ngx_http_variable_value_t *v, uintptr_t data)
4110 {
4111  u_char *p;
4112  size_t len;
4113  ngx_uint_t i;
4115 
4116  v->valid = 1;
4117  v->no_cacheable = 0;
4118  v->not_found = 0;
4119 
4120  if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
4121  v->not_found = 1;
4122  return NGX_OK;
4123  }
4124 
4125  len = 0;
4126  state = r->upstream_states->elts;
4127 
4128  for (i = 0; i < r->upstream_states->nelts; i++) {
4129  if (state[i].peer) {
4130  len += state[i].peer->len + 2;
4131 
4132  } else {
4133  len += 3;
4134  }
4135  }
4136 
4137  p = ngx_pnalloc(r->pool, len);
4138  if (p == NULL) {
4139  return NGX_ERROR;
4140  }
4141 
4142  v->data = p;
4143 
4144  i = 0;
4145 
4146  for ( ;; ) {
4147  if (state[i].peer) {
4148  p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len);
4149  }
4150 
4151  if (++i == r->upstream_states->nelts) {
4152  break;
4153  }
4154 
4155  if (state[i].peer) {
4156  *p++ = ',';
4157  *p++ = ' ';
4158 
4159  } else {
4160  *p++ = ' ';
4161  *p++ = ':';
4162  *p++ = ' ';
4163 
4164  if (++i == r->upstream_states->nelts) {
4165  break;
4166  }
4167 
4168  continue;
4169  }
4170  }
4171 
4172  v->len = p - v->data;
4173 
4174  return NGX_OK;
4175 }
4176 
4177 
4178 static ngx_int_t
4179 ngx_http_upstream_status_variable(ngx_http_request_t *r,
4180  ngx_http_variable_value_t *v, uintptr_t data)
4181 {
4182  u_char *p;
4183  size_t len;
4184  ngx_uint_t i;
4186 
4187  v->valid = 1;
4188  v->no_cacheable = 0;
4189  v->not_found = 0;
4190 
4191  if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
4192  v->not_found = 1;
4193  return NGX_OK;
4194  }
4195 
4196  len = r->upstream_states->nelts * (3 + 2);
4197 
4198  p = ngx_pnalloc(r->pool, len);
4199  if (p == NULL) {
4200  return NGX_ERROR;
4201  }
4202 
4203  v->data = p;
4204 
4205  i = 0;
4206  state = r->upstream_states->elts;
4207 
4208  for ( ;; ) {
4209  if (state[i].status) {
4210  p = ngx_sprintf(p, "%ui", state[i].status);
4211 
4212  } else {
4213  *p++ = '-';
4214  }
4215 
4216  if (++i == r->upstream_states->nelts) {
4217  break;
4218  }
4219 
4220  if (state[i].peer) {
4221  *p++ = ',';
4222  *p++ = ' ';
4223 
4224  } else {
4225  *p++ = ' ';
4226  *p++ = ':';
4227  *p++ = ' ';
4228 
4229  if (++i == r->upstream_states->nelts) {
4230  break;
4231  }
4232 
4233  continue;
4234  }
4235  }
4236 
4237  v->len = p - v->data;
4238 
4239  return NGX_OK;
4240 }
4241 
4242 
4243 static ngx_int_t
4244 ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
4245  ngx_http_variable_value_t *v, uintptr_t data)
4246 {
4247  u_char *p;
4248  size_t len;
4249  ngx_uint_t i;
4250  ngx_msec_int_t ms;
4252 
4253  v->valid = 1;
4254  v->no_cacheable = 0;
4255  v->not_found = 0;
4256 
4257  if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
4258  v->not_found = 1;
4259  return NGX_OK;
4260  }
4261 
4262  len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2);
4263 
4264  p = ngx_pnalloc(r->pool, len);
4265  if (p == NULL) {
4266  return NGX_ERROR;
4267  }
4268 
4269  v->data = p;
4270 
4271  i = 0;
4272  state = r->upstream_states->elts;
4273 
4274  for ( ;; ) {
4275  if (state[i].status) {
4276  ms = (ngx_msec_int_t)
4277  (state[i].response_sec * 1000 + state[i].response_msec);
4278  ms = ngx_max(ms, 0);
4279  p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
4280 
4281  } else {
4282  *p++ = '-';
4283  }
4284 
4285  if (++i == r->upstream_states->nelts) {
4286  break;
4287  }
4288 
4289  if (state[i].peer) {
4290  *p++ = ',';
4291  *p++ = ' ';
4292 
4293  } else {
4294  *p++ = ' ';
4295  *p++ = ':';
4296  *p++ = ' ';
4297 
4298  if (++i == r->upstream_states->nelts) {
4299  break;
4300  }
4301 
4302  continue;
4303  }
4304  }
4305 
4306  v->len = p - v->data;
4307 
4308  return NGX_OK;
4309 }
4310 
4311 
4312 static ngx_int_t
4313 ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
4314  ngx_http_variable_value_t *v, uintptr_t data)
4315 {
4316  u_char *p;
4317  size_t len;
4318  ngx_uint_t i;
4320 
4321  v->valid = 1;
4322  v->no_cacheable = 0;
4323  v->not_found = 0;
4324 
4325  if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
4326  v->not_found = 1;
4327  return NGX_OK;
4328  }
4329 
4330  len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2);
4331 
4332  p = ngx_pnalloc(r->pool, len);
4333  if (p == NULL) {
4334  return NGX_ERROR;
4335  }
4336 
4337  v->data = p;
4338 
4339  i = 0;
4340  state = r->upstream_states->elts;
4341 
4342  for ( ;; ) {
4343  p = ngx_sprintf(p, "%O", state[i].response_length);
4344 
4345  if (++i == r->upstream_states->nelts) {
4346  break;
4347  }
4348 
4349  if (state[i].peer) {
4350  *p++ = ',';
4351  *p++ = ' ';
4352 
4353  } else {
4354  *p++ = ' ';
4355  *p++ = ':';
4356  *p++ = ' ';
4357 
4358  if (++i == r->upstream_states->nelts) {
4359  break;
4360  }
4361 
4362  continue;
4363  }
4364  }
4365 
4366  v->len = p - v->data;
4367 
4368  return NGX_OK;
4369 }
4370 
4371 
4372 ngx_int_t
4374  ngx_http_variable_value_t *v, uintptr_t data)
4375 {
4376  if (r->upstream == NULL) {
4377  v->not_found = 1;
4378  return NGX_OK;
4379  }
4380 
4381  return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
4383  sizeof("upstream_http_") - 1);
4384 }
4385 
4386 
4387 #if (NGX_HTTP_CACHE)
4388 
4389 ngx_int_t
4390 ngx_http_upstream_cache_status(ngx_http_request_t *r,
4391  ngx_http_variable_value_t *v, uintptr_t data)
4392 {
4393  ngx_uint_t n;
4394 
4395  if (r->upstream == NULL || r->upstream->cache_status == 0) {
4396  v->not_found = 1;
4397  return NGX_OK;
4398  }
4399 
4400  n = r->upstream->cache_status - 1;
4401 
4402  v->valid = 1;
4403  v->no_cacheable = 0;
4404  v->not_found = 0;
4405  v->len = ngx_http_cache_status[n].len;
4407 
4408  return NGX_OK;
4409 }
4410 
4411 #endif
4412 
4413 
4414 static char *
4415 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
4416 {
4417  char *rv;
4418  void *mconf;
4419  ngx_str_t *value;
4420  ngx_url_t u;
4421  ngx_uint_t m;
4422  ngx_conf_t pcf;
4423  ngx_http_module_t *module;
4424  ngx_http_conf_ctx_t *ctx, *http_ctx;
4426 
4427  ngx_memzero(&u, sizeof(ngx_url_t));
4428 
4429  value = cf->args->elts;
4430  u.host = value[1];
4431  u.no_resolve = 1;
4432  u.no_port = 1;
4433 
4440  if (uscf == NULL) {
4441  return NGX_CONF_ERROR;
4442  }
4443 
4444 
4445  ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
4446  if (ctx == NULL) {
4447  return NGX_CONF_ERROR;
4448  }
4449 
4450  http_ctx = cf->ctx;
4451  ctx->main_conf = http_ctx->main_conf;
4452 
4453  /* the upstream{}'s srv_conf */
4454 
4455  ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
4456  if (ctx->srv_conf == NULL) {
4457  return NGX_CONF_ERROR;
4458  }
4459 
4460  ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
4461 
4462  uscf->srv_conf = ctx->srv_conf;
4463 
4464 
4465  /* the upstream{}'s loc_conf */
4466 
4467  ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
4468  if (ctx->loc_conf == NULL) {
4469  return NGX_CONF_ERROR;
4470  }
4471 
4472  for (m = 0; ngx_modules[m]; m++) {
4473  if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
4474  continue;
4475  }
4476 
4477  module = ngx_modules[m]->ctx;
4478 
4479  if (module->create_srv_conf) {
4480  mconf = module->create_srv_conf(cf);
4481  if (mconf == NULL) {
4482  return NGX_CONF_ERROR;
4483  }
4484 
4485  ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
4486  }
4487 
4488  if (module->create_loc_conf) {
4489  mconf = module->create_loc_conf(cf);
4490  if (mconf == NULL) {
4491  return NGX_CONF_ERROR;
4492  }
4493 
4494  ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf;
4495  }
4496  }
4497 
4498 
4499  /* parse inside upstream{} */
4500 
4501  pcf = *cf;
4502  cf->ctx = ctx;
4504 
4505  rv = ngx_conf_parse(cf, NULL);
4506 
4507  *cf = pcf;
4508 
4509  if (rv != NGX_CONF_OK) {
4510  return rv;
4511  }
4512 
4513  if (uscf->servers == NULL) {
4515  "no servers are inside upstream");
4516  return NGX_CONF_ERROR;
4517  }
4518 
4519  return rv;
4520 }
4521 
4522 
4523 static char *
4524 ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4525 {
4526  ngx_http_upstream_srv_conf_t *uscf = conf;
4527 
4528  time_t fail_timeout;
4529  ngx_str_t *value, s;
4530  ngx_url_t u;
4531  ngx_int_t weight, max_fails;
4532  ngx_uint_t i;
4534 
4535  if (uscf->servers == NULL) {
4536  uscf->servers = ngx_array_create(cf->pool, 4,
4537  sizeof(ngx_http_upstream_server_t));
4538  if (uscf->servers == NULL) {
4539  return NGX_CONF_ERROR;
4540  }
4541  }
4542 
4543  us = ngx_array_push(uscf->servers);
4544  if (us == NULL) {
4545  return NGX_CONF_ERROR;
4546  }
4547 
4549 
4550  value = cf->args->elts;
4551 
4552  ngx_memzero(&u, sizeof(ngx_url_t));
4553 
4554  u.url = value[1];
4555  u.default_port = 80;
4556 
4557  if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
4558  if (u.err) {
4560  "%s in upstream \"%V\"", u.err, &u.url);
4561  }
4562 
4563  return NGX_CONF_ERROR;
4564  }
4565 
4566  weight = 1;
4567  max_fails = 1;
4568  fail_timeout = 10;
4569 
4570  for (i = 2; i < cf->args->nelts; i++) {
4571 
4572  if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {
4573 
4574  if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) {
4575  goto invalid;
4576  }
4577 
4578  weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
4579 
4580  if (weight == NGX_ERROR || weight == 0) {
4581  goto invalid;
4582  }
4583 
4584  continue;
4585  }
4586 
4587  if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
4588 
4589  if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
4590  goto invalid;
4591  }
4592 
4593  max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
4594 
4595  if (max_fails == NGX_ERROR) {
4596  goto invalid;
4597  }
4598 
4599  continue;
4600  }
4601 
4602  if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {
4603 
4604  if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) {
4605  goto invalid;
4606  }
4607 
4608  s.len = value[i].len - 13;
4609  s.data = &value[i].data[13];
4610 
4611  fail_timeout = ngx_parse_time(&s, 1);
4612 
4613  if (fail_timeout == (time_t) NGX_ERROR) {
4614  goto invalid;
4615  }
4616 
4617  continue;
4618  }
4619 
4620  if (ngx_strncmp(value[i].data, "backup", 6) == 0) {
4621 
4622  if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) {
4623  goto invalid;
4624  }
4625 
4626  us->backup = 1;
4627 
4628  continue;
4629  }
4630 
4631  if (ngx_strncmp(value[i].data, "down", 4) == 0) {
4632 
4633  if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
4634  goto invalid;
4635  }
4636 
4637  us->down = 1;
4638 
4639  continue;
4640  }
4641 
4642  goto invalid;
4643  }
4644 
4645  us->addrs = u.addrs;
4646  us->naddrs = u.naddrs;
4647  us->weight = weight;
4648  us->max_fails = max_fails;
4649  us->fail_timeout = fail_timeout;
4650 
4651  return NGX_CONF_OK;
4652 
4653 invalid:
4654 
4656  "invalid parameter \"%V\"", &value[i]);
4657 
4658  return NGX_CONF_ERROR;
4659 }
4660 
4661 
4664 {
4665  ngx_uint_t i;
4667  ngx_http_upstream_srv_conf_t *uscf, **uscfp;
4669 
4670  if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {
4671 
4672  if (ngx_parse_url(cf->pool, u) != NGX_OK) {
4673  if (u->err) {
4675  "%s in upstream \"%V\"", u->err, &u->url);
4676  }
4677 
4678  return NULL;
4679  }
4680  }
4681 
4682  umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
4683 
4684  uscfp = umcf->upstreams.elts;
4685 
4686  for (i = 0; i < umcf->upstreams.nelts; i++) {
4687 
4688  if (uscfp[i]->host.len != u->host.len
4689  || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
4690  != 0)
4691  {
4692  continue;
4693  }
4694 
4695  if ((flags & NGX_HTTP_UPSTREAM_CREATE)
4696  && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
4697  {
4699  "duplicate upstream \"%V\"", &u->host);
4700  return NULL;
4701  }
4702 
4703  if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) {
4705  "upstream \"%V\" may not have port %d",
4706  &u->host, u->port);
4707  return NULL;
4708  }
4709 
4710  if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) {
4711  ngx_log_error(NGX_LOG_WARN, cf->log, 0,
4712  "upstream \"%V\" may not have port %d in %s:%ui",
4713  &u->host, uscfp[i]->port,
4714  uscfp[i]->file_name, uscfp[i]->line);
4715  return NULL;
4716  }
4717 
4718  if (uscfp[i]->port && u->port
4719  && uscfp[i]->port != u->port)
4720  {
4721  continue;
4722  }
4723 
4724  if (uscfp[i]->default_port && u->default_port
4725  && uscfp[i]->default_port != u->default_port)
4726  {
4727  continue;
4728  }
4729 
4730  if (flags & NGX_HTTP_UPSTREAM_CREATE) {
4731  uscfp[i]->flags = flags;
4732  }
4733 
4734  return uscfp[i];
4735  }
4736 
4737  uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
4738  if (uscf == NULL) {
4739  return NULL;
4740  }
4741 
4742  uscf->flags = flags;
4743  uscf->host = u->host;
4744  uscf->file_name = cf->conf_file->file.name.data;
4745  uscf->line = cf->conf_file->line;
4746  uscf->port = u->port;
4747  uscf->default_port = u->default_port;
4748  uscf->no_port = u->no_port;
4749 
4750  if (u->naddrs == 1) {
4751  uscf->servers = ngx_array_create(cf->pool, 1,
4752  sizeof(ngx_http_upstream_server_t));
4753  if (uscf->servers == NULL) {
4754  return NULL;
4755  }
4756 
4757  us = ngx_array_push(uscf->servers);
4758  if (us == NULL) {
4759  return NULL;
4760  }
4761 
4763 
4764  us->addrs = u->addrs;
4765  us->naddrs = 1;
4766  }
4767 
4768  uscfp = ngx_array_push(&umcf->upstreams);
4769  if (uscfp == NULL) {
4770  return NULL;
4771  }
4772 
4773  *uscfp = uscf;
4774 
4775  return uscf;
4776 }
4777 
4778 
4779 char *
4781  void *conf)
4782 {
4783  char *p = conf;
4784 
4785  ngx_int_t rc;
4786  ngx_str_t *value;
4788  ngx_http_upstream_local_t **plocal, *local;
4790 
4791  plocal = (ngx_http_upstream_local_t **) (p + cmd->offset);
4792 
4793  if (*plocal != NGX_CONF_UNSET_PTR) {
4794  return "is duplicate";
4795  }
4796 
4797  value = cf->args->elts;
4798 
4799  if (ngx_strcmp(value[1].data, "off") == 0) {
4800  *plocal = NULL;
4801  return NGX_CONF_OK;
4802  }
4803 
4805 
4806  ccv.cf = cf;
4807  ccv.value = &value[1];
4808  ccv.complex_value = &cv;
4809 
4810  if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4811  return NGX_CONF_ERROR;
4812  }
4813 
4814  local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
4815  if (local == NULL) {
4816  return NGX_CONF_ERROR;
4817  }
4818 
4819  *plocal = local;
4820 
4821  if (cv.lengths) {
4822  local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
4823  if (local->value == NULL) {
4824  return NGX_CONF_ERROR;
4825  }
4826 
4827  *local->value = cv;
4828 
4829  return NGX_CONF_OK;
4830  }
4831 
4832  local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
4833  if (local->addr == NULL) {
4834  return NGX_CONF_ERROR;
4835  }
4836 
4837  rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
4838 
4839  switch (rc) {
4840  case NGX_OK:
4841  local->addr->name = value[1];
4842  return NGX_CONF_OK;
4843 
4844  case NGX_DECLINED:
4846  "invalid address \"%V\"", &value[1]);
4847  /* fall through */
4848 
4849  default:
4850  return NGX_CONF_ERROR;
4851  }
4852 }
4853 
4854 
4855 static ngx_addr_t *
4856 ngx_http_upstream_get_local(ngx_http_request_t *r,
4858 {
4859  ngx_int_t rc;
4860  ngx_str_t val;
4861  ngx_addr_t *addr;
4862 
4863  if (local == NULL) {
4864  return NULL;
4865  }
4866 
4867  if (local->value == NULL) {
4868  return local->addr;
4869  }
4870 
4871  if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
4872  return NULL;
4873  }
4874 
4875  if (val.len == 0) {
4876  return NULL;
4877  }
4878 
4879  addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
4880  if (addr == NULL) {
4881  return NULL;
4882  }
4883 
4884  rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
4885 
4886  switch (rc) {
4887  case NGX_OK:
4888  addr->name = val;
4889  return addr;
4890 
4891  case NGX_DECLINED:
4893  "invalid local address \"%V\"", &val);
4894  /* fall through */
4895 
4896  default:
4897  return NULL;
4898  }
4899 }
4900 
4901 
4902 char *
4904  void *conf)
4905 {
4906  char *p = conf;
4907 
4908  ngx_str_t *value;
4909  ngx_array_t **a;
4911 
4912  a = (ngx_array_t **) (p + cmd->offset);
4913 
4914  if (*a == NULL) {
4915  *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
4916  if (*a == NULL) {
4917  return NGX_CONF_ERROR;
4918  }
4919  }
4920 
4921  param = ngx_array_push(*a);
4922  if (param == NULL) {
4923  return NGX_CONF_ERROR;
4924  }
4925 
4926  value = cf->args->elts;
4927 
4928  param->key = value[1];
4929  param->value = value[2];
4930  param->skip_empty = 0;
4931 
4932  if (cf->args->nelts == 4) {
4933  if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
4935  "invalid parameter \"%V\"", &value[3]);
4936  return NGX_CONF_ERROR;
4937  }
4938 
4939  param->skip_empty = 1;
4940  }
4941 
4942  return NGX_CONF_OK;
4943 }
4944 
4945 
4946 ngx_int_t
4949  ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
4950 {
4951  ngx_str_t *h;
4952  ngx_uint_t i, j;
4953  ngx_array_t hide_headers;
4954  ngx_hash_key_t *hk;
4955 
4956  if (conf->hide_headers == NGX_CONF_UNSET_PTR
4957  && conf->pass_headers == NGX_CONF_UNSET_PTR)
4958  {
4959  conf->hide_headers = prev->hide_headers;
4960  conf->pass_headers = prev->pass_headers;
4961 
4962  conf->hide_headers_hash = prev->hide_headers_hash;
4963 
4964  if (conf->hide_headers_hash.buckets
4965 #if (NGX_HTTP_CACHE)
4966  && ((conf->cache == NULL) == (prev->cache == NULL))
4967 #endif
4968  )
4969  {
4970  return NGX_OK;
4971  }
4972 
4973  } else {
4974  if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
4975  conf->hide_headers = prev->hide_headers;
4976  }
4977 
4978  if (conf->pass_headers == NGX_CONF_UNSET_PTR) {
4979  conf->pass_headers = prev->pass_headers;
4980  }
4981  }
4982 
4983  if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
4984  != NGX_OK)
4985  {
4986  return NGX_ERROR;
4987  }
4988 
4989  for (h = default_hide_headers; h->len; h++) {
4990  hk = ngx_array_push(&hide_headers);
4991  if (hk == NULL) {
4992  return NGX_ERROR;
4993  }
4994 
4995  hk->key = *h;
4996  hk->key_hash = ngx_hash_key_lc(h->data, h->len);
4997  hk->value = (void *) 1;
4998  }
4999 
5000  if (conf->hide_headers != NGX_CONF_UNSET_PTR) {
5001 
5002  h = conf->hide_headers->elts;
5003 
5004  for (i = 0; i < conf->hide_headers->nelts; i++) {
5005 
5006  hk = hide_headers.elts;
5007 
5008  for (j = 0; j < hide_headers.nelts; j++) {
5009  if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
5010  goto exist;
5011  }
5012  }
5013 
5014  hk = ngx_array_push(&hide_headers);
5015  if (hk == NULL) {
5016  return NGX_ERROR;
5017  }
5018 
5019  hk->key = h[i];
5020  hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
5021  hk->value = (void *) 1;
5022 
5023  exist:
5024 
5025  continue;
5026  }
5027  }
5028 
5029  if (conf->pass_headers != NGX_CONF_UNSET_PTR) {
5030 
5031  h = conf->pass_headers->elts;
5032  hk = hide_headers.elts;
5033 
5034  for (i = 0; i < conf->pass_headers->nelts; i++) {
5035  for (j = 0; j < hide_headers.nelts; j++) {
5036 
5037  if (hk[j].key.data == NULL) {
5038  continue;
5039  }
5040 
5041  if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
5042  hk[j].key.data = NULL;
5043  break;
5044  }
5045  }
5046  }
5047  }
5048 
5049  hash->hash = &conf->hide_headers_hash;
5050  hash->key = ngx_hash_key_lc;
5051  hash->pool = cf->pool;
5052  hash->temp_pool = NULL;
5053 
5054  return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
5055 }
5056 
5057 
5058 static void *
5059 ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
5060 {
5062 
5063  umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
5064  if (umcf == NULL) {
5065  return NULL;
5066  }
5067 
5068  if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
5069  sizeof(ngx_http_upstream_srv_conf_t *))
5070  != NGX_OK)
5071  {
5072  return NULL;
5073  }
5074 
5075  return umcf;
5076 }
5077 
5078 
5079 static char *
5080 ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
5081 {
5082  ngx_http_upstream_main_conf_t *umcf = conf;
5083 
5084  ngx_uint_t i;
5085  ngx_array_t headers_in;
5086  ngx_hash_key_t *hk;
5087  ngx_hash_init_t hash;
5091 
5092  uscfp = umcf->upstreams.elts;
5093 
5094  for (i = 0; i < umcf->upstreams.nelts; i++) {
5095 
5096  init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
5098 
5099  if (init(cf, uscfp[i]) != NGX_OK) {
5100  return NGX_CONF_ERROR;
5101  }
5102  }
5103 
5104 
5105  /* upstream_headers_in_hash */
5106 
5107  if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
5108  != NGX_OK)
5109  {
5110  return NGX_CONF_ERROR;
5111  }
5112 
5113  for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
5114  hk = ngx_array_push(&headers_in);
5115  if (hk == NULL) {
5116  return NGX_CONF_ERROR;
5117  }
5118 
5119  hk->key = header->name;
5120  hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
5121  hk->value = header;
5122  }
5123 
5124  hash.hash = &umcf->headers_in_hash;
5125  hash.key = ngx_hash_key_lc;
5126  hash.max_size = 512;
5128  hash.name = "upstream_headers_in_hash";
5129  hash.pool = cf->pool;
5130  hash.temp_pool = NULL;
5131 
5132  if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
5133  return NGX_CONF_ERROR;
5134  }
5135 
5136  return NGX_CONF_OK;
5137 }