src/http/ngx_http_upstream.c - nginx source code

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. #if (NGX_HTTP_CACHE)
  9. static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
  10.     ngx_http_upstream_t *u);
  11. static ngx_int_t ngx_http_upstream_cache_get(ngx_http_request_t *r,
  12.     ngx_http_upstream_t *u, ngx_http_file_cache_t **cache);
  13. static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
  14.     ngx_http_upstream_t *u);
  15. static ngx_int_t ngx_http_upstream_cache_background_update(
  16.     ngx_http_request_t *r, ngx_http_upstream_t *u);
  17. static ngx_int_t ngx_http_upstream_cache_check_range(ngx_http_request_t *r,
  18.     ngx_http_upstream_t *u);
  19. static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
  20.     ngx_http_variable_value_t *v, uintptr_t data);
  21. static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
  22.     ngx_http_variable_value_t *v, uintptr_t data);
  23. static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r,
  24.     ngx_http_variable_value_t *v, uintptr_t data);
  25. #endif

  26. static void ngx_http_upstream_init_request(ngx_http_request_t *r);
  27. static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
  28. static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
  29. static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
  30. static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
  31.     ngx_event_t *ev);
  32. static void ngx_http_upstream_connect(ngx_http_request_t *r,
  33.     ngx_http_upstream_t *u);
  34. static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
  35.     ngx_http_upstream_t *u);
  36. static void ngx_http_upstream_send_request(ngx_http_request_t *r,
  37.     ngx_http_upstream_t *u, ngx_uint_t do_write);
  38. static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r,
  39.     ngx_http_upstream_t *u, ngx_uint_t do_write);
  40. static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
  41.     ngx_http_upstream_t *u);
  42. static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
  43. static void ngx_http_upstream_process_header(ngx_http_request_t *r,
  44.     ngx_http_upstream_t *u);
  45. static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
  46.     ngx_http_upstream_t *u);
  47. static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
  48.     ngx_http_upstream_t *u);
  49. static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
  50. static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
  51.     ngx_http_upstream_t *u);
  52. static ngx_int_t ngx_http_upstream_process_trailers(ngx_http_request_t *r,
  53.     ngx_http_upstream_t *u);
  54. static void ngx_http_upstream_send_response(ngx_http_request_t *r,
  55.     ngx_http_upstream_t *u);
  56. static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
  57.     ngx_http_upstream_t *u);
  58. static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
  59. static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
  60. static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
  61.     ngx_http_upstream_t *u);
  62. static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
  63.     ngx_http_upstream_t *u);
  64. static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
  65.     ngx_uint_t from_upstream, ngx_uint_t do_write);
  66. static void
  67.     ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
  68. static void
  69.     ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
  70.     ngx_http_upstream_t *u);
  71. static void
  72.     ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
  73.     ngx_uint_t do_write);
  74. #if (NGX_THREADS)
  75. static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
  76.     ngx_file_t *file);
  77. static void ngx_http_upstream_thread_event_handler(ngx_event_t *ev);
  78. #endif
  79. static ngx_int_t ngx_http_upstream_output_filter(void *data,
  80.     ngx_chain_t *chain);
  81. static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
  82. static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
  83.     ngx_http_upstream_t *u);
  84. static void ngx_http_upstream_process_request(ngx_http_request_t *r,
  85.     ngx_http_upstream_t *u);
  86. static void ngx_http_upstream_store(ngx_http_request_t *r,
  87.     ngx_http_upstream_t *u);
  88. static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
  89.     ngx_http_upstream_t *u);
  90. static void ngx_http_upstream_next(ngx_http_request_t *r,
  91.     ngx_http_upstream_t *u, ngx_uint_t ft_type);
  92. static void ngx_http_upstream_cleanup(void *data);
  93. static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
  94.     ngx_http_upstream_t *u, ngx_int_t rc);

  95. static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
  96.     ngx_table_elt_t *h, ngx_uint_t offset);
  97. static ngx_int_t
  98.     ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
  99.     ngx_table_elt_t *h, ngx_uint_t offset);
  100. static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
  101.     ngx_table_elt_t *h, ngx_uint_t offset);
  102. static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
  103.     ngx_table_elt_t *h, ngx_uint_t offset);
  104. static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
  105.     ngx_table_elt_t *h, ngx_uint_t offset);
  106. static ngx_int_t
  107.     ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
  108.     ngx_table_elt_t *h, ngx_uint_t offset);
  109. static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
  110.     ngx_table_elt_t *h, ngx_uint_t offset);
  111. static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
  112.     ngx_table_elt_t *h, ngx_uint_t offset);
  113. static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
  114.     ngx_table_elt_t *h, ngx_uint_t offset);
  115. static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
  116.     ngx_table_elt_t *h, ngx_uint_t offset);
  117. static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
  118.     ngx_table_elt_t *h, ngx_uint_t offset);
  119. static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
  120.     ngx_table_elt_t *h, ngx_uint_t offset);
  121. static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
  122.     ngx_table_elt_t *h, ngx_uint_t offset);
  123. static ngx_int_t
  124.     ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
  125.     ngx_table_elt_t *h, ngx_uint_t offset);
  126. static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r,
  127.     ngx_table_elt_t *h, ngx_uint_t offset);
  128. static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
  129.     ngx_table_elt_t *h, ngx_uint_t offset);
  130. static ngx_int_t
  131.     ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
  132.     ngx_table_elt_t *h, ngx_uint_t offset);
  133. static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
  134.     ngx_table_elt_t *h, ngx_uint_t offset);
  135. static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
  136.     ngx_table_elt_t *h, ngx_uint_t offset);
  137. static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
  138.     ngx_table_elt_t *h, ngx_uint_t offset);
  139. static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
  140.     ngx_table_elt_t *h, ngx_uint_t offset);
  141. static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
  142.     ngx_table_elt_t *h, ngx_uint_t offset);
  143. static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
  144.     ngx_table_elt_t *h, ngx_uint_t offset);

  145. static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
  146. static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
  147.     ngx_http_variable_value_t *v, uintptr_t data);
  148. static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
  149.     ngx_http_variable_value_t *v, uintptr_t data);
  150. static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
  151.     ngx_http_variable_value_t *v, uintptr_t data);
  152. static ngx_int_t ngx_http_upstream_response_length_variable(
  153.     ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
  154. static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r,
  155.     ngx_http_variable_value_t *v, uintptr_t data);
  156. static ngx_int_t ngx_http_upstream_trailer_variable(ngx_http_request_t *r,
  157.     ngx_http_variable_value_t *v, uintptr_t data);
  158. static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
  159.     ngx_http_variable_value_t *v, uintptr_t data);

  160. static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
  161. static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
  162.     void *conf);
  163. #if (NGX_HTTP_UPSTREAM_ZONE)
  164. static char *ngx_http_upstream_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
  165.     void *conf);
  166. #endif

  167. static ngx_int_t ngx_http_upstream_set_local(ngx_http_request_t *r,
  168.   ngx_http_upstream_t *u, ngx_http_upstream_local_t *local);

  169. static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
  170. static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);

  171. #if (NGX_HTTP_SSL)
  172. static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
  173.     ngx_http_upstream_t *u, ngx_connection_t *c);
  174. static void ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c);
  175. static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *,
  176.     ngx_http_upstream_t *u, ngx_connection_t *c);
  177. static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c);
  178. static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
  179.     ngx_http_upstream_t *u, ngx_connection_t *c);
  180. static ngx_int_t ngx_http_upstream_ssl_certificate(ngx_http_request_t *r,
  181.     ngx_http_upstream_t *u, ngx_connection_t *c);
  182. #endif


  183. static ngx_http_upstream_header_t  ngx_http_upstream_headers_in[] = {

  184.     { ngx_string("Status"),
  185.                  ngx_http_upstream_process_header_line,
  186.                  offsetof(ngx_http_upstream_headers_in_t, status),
  187.                  ngx_http_upstream_copy_header_line, 0, 0 },

  188.     { ngx_string("Content-Type"),
  189.                  ngx_http_upstream_process_header_line,
  190.                  offsetof(ngx_http_upstream_headers_in_t, content_type),
  191.                  ngx_http_upstream_copy_content_type, 0, 1 },

  192.     { ngx_string("Content-Length"),
  193.                  ngx_http_upstream_process_content_length, 0,
  194.                  ngx_http_upstream_ignore_header_line, 0, 0 },

  195.     { ngx_string("Date"),
  196.                  ngx_http_upstream_process_header_line,
  197.                  offsetof(ngx_http_upstream_headers_in_t, date),
  198.                  ngx_http_upstream_copy_header_line,
  199.                  offsetof(ngx_http_headers_out_t, date), 0 },

  200.     { ngx_string("Last-Modified"),
  201.                  ngx_http_upstream_process_last_modified, 0,
  202.                  ngx_http_upstream_copy_last_modified, 0, 0 },

  203.     { ngx_string("ETag"),
  204.                  ngx_http_upstream_process_header_line,
  205.                  offsetof(ngx_http_upstream_headers_in_t, etag),
  206.                  ngx_http_upstream_copy_header_line,
  207.                  offsetof(ngx_http_headers_out_t, etag), 0 },

  208.     { ngx_string("Server"),
  209.                  ngx_http_upstream_process_header_line,
  210.                  offsetof(ngx_http_upstream_headers_in_t, server),
  211.                  ngx_http_upstream_copy_header_line,
  212.                  offsetof(ngx_http_headers_out_t, server), 0 },

  213.     { ngx_string("WWW-Authenticate"),
  214.                  ngx_http_upstream_process_multi_header_lines,
  215.                  offsetof(ngx_http_upstream_headers_in_t, www_authenticate),
  216.                  ngx_http_upstream_copy_header_line, 0, 0 },

  217.     { ngx_string("Location"),
  218.                  ngx_http_upstream_process_header_line,
  219.                  offsetof(ngx_http_upstream_headers_in_t, location),
  220.                  ngx_http_upstream_rewrite_location, 0, 0 },

  221.     { ngx_string("Refresh"),
  222.                  ngx_http_upstream_process_header_line,
  223.                  offsetof(ngx_http_upstream_headers_in_t, refresh),
  224.                  ngx_http_upstream_rewrite_refresh, 0, 0 },

  225.     { ngx_string("Set-Cookie"),
  226.                  ngx_http_upstream_process_set_cookie,
  227.                  offsetof(ngx_http_upstream_headers_in_t, set_cookie),
  228.                  ngx_http_upstream_rewrite_set_cookie, 0, 1 },

  229.     { ngx_string("Content-Disposition"),
  230.                  ngx_http_upstream_ignore_header_line, 0,
  231.                  ngx_http_upstream_copy_header_line, 0, 1 },

  232.     { ngx_string("Cache-Control"),
  233.                  ngx_http_upstream_process_cache_control, 0,
  234.                  ngx_http_upstream_copy_multi_header_lines,
  235.                  offsetof(ngx_http_headers_out_t, cache_control), 1 },

  236.     { ngx_string("Expires"),
  237.                  ngx_http_upstream_process_expires, 0,
  238.                  ngx_http_upstream_copy_header_line,
  239.                  offsetof(ngx_http_headers_out_t, expires), 1 },

  240.     { ngx_string("Accept-Ranges"),
  241.                  ngx_http_upstream_ignore_header_line, 0,
  242.                  ngx_http_upstream_copy_allow_ranges,
  243.                  offsetof(ngx_http_headers_out_t, accept_ranges), 1 },

  244.     { ngx_string("Content-Range"),
  245.                  ngx_http_upstream_ignore_header_line, 0,
  246.                  ngx_http_upstream_copy_header_line,
  247.                  offsetof(ngx_http_headers_out_t, content_range), 0 },

  248.     { ngx_string("Connection"),
  249.                  ngx_http_upstream_process_connection, 0,
  250.                  ngx_http_upstream_ignore_header_line, 0, 0 },

  251.     { ngx_string("Keep-Alive"),
  252.                  ngx_http_upstream_ignore_header_line, 0,
  253.                  ngx_http_upstream_ignore_header_line, 0, 0 },

  254.     { ngx_string("Vary"),
  255.                  ngx_http_upstream_process_vary, 0,
  256.                  ngx_http_upstream_copy_header_line, 0, 0 },

  257.     { ngx_string("Link"),
  258.                  ngx_http_upstream_ignore_header_line, 0,
  259.                  ngx_http_upstream_copy_multi_header_lines,
  260.                  offsetof(ngx_http_headers_out_t, link), 0 },

  261.     { ngx_string("X-Accel-Expires"),
  262.                  ngx_http_upstream_process_accel_expires, 0,
  263.                  ngx_http_upstream_copy_header_line, 0, 0 },

  264.     { ngx_string("X-Accel-Redirect"),
  265.                  ngx_http_upstream_process_header_line,
  266.                  offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect),
  267.                  ngx_http_upstream_copy_header_line, 0, 0 },

  268.     { ngx_string("X-Accel-Limit-Rate"),
  269.                  ngx_http_upstream_process_limit_rate, 0,
  270.                  ngx_http_upstream_copy_header_line, 0, 0 },

  271.     { ngx_string("X-Accel-Buffering"),
  272.                  ngx_http_upstream_process_buffering, 0,
  273.                  ngx_http_upstream_copy_header_line, 0, 0 },

  274.     { ngx_string("X-Accel-Charset"),
  275.                  ngx_http_upstream_process_charset, 0,
  276.                  ngx_http_upstream_copy_header_line, 0, 0 },

  277.     { ngx_string("Transfer-Encoding"),
  278.                  ngx_http_upstream_process_transfer_encoding, 0,
  279.                  ngx_http_upstream_ignore_header_line, 0, 0 },

  280.     { ngx_string("Content-Encoding"),
  281.                  ngx_http_upstream_ignore_header_line, 0,
  282.                  ngx_http_upstream_copy_header_line,
  283.                  offsetof(ngx_http_headers_out_t, content_encoding), 0 },

  284.     { ngx_null_string, NULL, 0, NULL, 0, 0 }
  285. };


  286. static ngx_command_t  ngx_http_upstream_commands[] = {

  287.     { ngx_string("upstream"),
  288.       NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
  289.       ngx_http_upstream,
  290.       0,
  291.       0,
  292.       NULL },

  293.     { ngx_string("server"),
  294.       NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
  295.       ngx_http_upstream_server,
  296.       NGX_HTTP_SRV_CONF_OFFSET,
  297.       0,
  298.       NULL },

  299. #if (NGX_HTTP_UPSTREAM_ZONE)

  300.     { ngx_string("resolver"),
  301.       NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
  302.       ngx_http_upstream_resolver,
  303.       NGX_HTTP_SRV_CONF_OFFSET,
  304.       0,
  305.       NULL },

  306.     { ngx_string("resolver_timeout"),
  307.       NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
  308.       ngx_conf_set_msec_slot,
  309.       NGX_HTTP_SRV_CONF_OFFSET,
  310.       offsetof(ngx_http_upstream_srv_conf_t, resolver_timeout),
  311.       NULL },

  312. #endif

  313.       ngx_null_command
  314. };


  315. static ngx_http_module_t  ngx_http_upstream_module_ctx = {
  316.     ngx_http_upstream_add_variables,       /* preconfiguration */
  317.     NULL,                                  /* postconfiguration */

  318.     ngx_http_upstream_create_main_conf,    /* create main configuration */
  319.     ngx_http_upstream_init_main_conf,      /* init main configuration */

  320.     NULL,                                  /* create server configuration */
  321.     NULL,                                  /* merge server configuration */

  322.     NULL,                                  /* create location configuration */
  323.     NULL                                   /* merge location configuration */
  324. };


  325. ngx_module_t  ngx_http_upstream_module = {
  326.     NGX_MODULE_V1,
  327.     &ngx_http_upstream_module_ctx,         /* module context */
  328.     ngx_http_upstream_commands,            /* module directives */
  329.     NGX_HTTP_MODULE,                       /* module type */
  330.     NULL,                                  /* init master */
  331.     NULL,                                  /* init module */
  332.     NULL,                                  /* init process */
  333.     NULL,                                  /* init thread */
  334.     NULL,                                  /* exit thread */
  335.     NULL,                                  /* exit process */
  336.     NULL,                                  /* exit master */
  337.     NGX_MODULE_V1_PADDING
  338. };


  339. static ngx_http_variable_t  ngx_http_upstream_vars[] = {

  340.     { ngx_string("upstream_addr"), NULL,
  341.       ngx_http_upstream_addr_variable, 0,
  342.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  343.     { ngx_string("upstream_status"), NULL,
  344.       ngx_http_upstream_status_variable, 0,
  345.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  346.     { ngx_string("upstream_connect_time"), NULL,
  347.       ngx_http_upstream_response_time_variable, 2,
  348.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  349.     { ngx_string("upstream_header_time"), NULL,
  350.       ngx_http_upstream_response_time_variable, 1,
  351.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  352.     { ngx_string("upstream_response_time"), NULL,
  353.       ngx_http_upstream_response_time_variable, 0,
  354.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  355.     { ngx_string("upstream_response_length"), NULL,
  356.       ngx_http_upstream_response_length_variable, 0,
  357.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  358.     { ngx_string("upstream_bytes_received"), NULL,
  359.       ngx_http_upstream_response_length_variable, 1,
  360.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  361.     { ngx_string("upstream_bytes_sent"), NULL,
  362.       ngx_http_upstream_response_length_variable, 2,
  363.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  364. #if (NGX_HTTP_CACHE)

  365.     { ngx_string("upstream_cache_status"), NULL,
  366.       ngx_http_upstream_cache_status, 0,
  367.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  368.     { ngx_string("upstream_cache_last_modified"), NULL,
  369.       ngx_http_upstream_cache_last_modified, 0,
  370.       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

  371.     { ngx_string("upstream_cache_etag"), NULL,
  372.       ngx_http_upstream_cache_etag, 0,
  373.       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

  374. #endif

  375.     { ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable,
  376.       0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 },

  377.     { ngx_string("upstream_trailer_"), NULL, ngx_http_upstream_trailer_variable,
  378.       0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 },

  379.     { ngx_string("upstream_cookie_"), NULL, ngx_http_upstream_cookie_variable,
  380.       0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 },

  381.       ngx_http_null_variable
  382. };


  383. static ngx_http_upstream_next_t  ngx_http_upstream_next_errors[] = {
  384.     { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500 },
  385.     { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 },
  386.     { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 },
  387.     { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 },
  388.     { 403, NGX_HTTP_UPSTREAM_FT_HTTP_403 },
  389.     { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 },
  390.     { 429, NGX_HTTP_UPSTREAM_FT_HTTP_429 },
  391.     { 0, 0 }
  392. };


  393. ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[] = {
  394.     { ngx_string("GET"), NGX_HTTP_GET },
  395.     { ngx_string("HEAD"), NGX_HTTP_HEAD },
  396.     { ngx_string("POST"), NGX_HTTP_POST },
  397.     { ngx_null_string, 0 }
  398. };


  399. ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
  400.     { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
  401.     { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
  402.     { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
  403.     { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
  404.     { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
  405.     { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
  406.     { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
  407.     { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
  408.     { ngx_string("Vary"), NGX_HTTP_UPSTREAM_IGN_VARY },
  409.     { ngx_null_string, 0 }
  410. };


  411. ngx_int_t
  412. ngx_http_upstream_create(ngx_http_request_t *r)
  413. {
  414.     ngx_http_upstream_t  *u;

  415.     u = r->upstream;

  416.     if (u && u->cleanup) {
  417.         r->main->count++;
  418.         ngx_http_upstream_cleanup(r);
  419.     }

  420.     u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
  421.     if (u == NULL) {
  422.         return NGX_ERROR;
  423.     }

  424.     r->upstream = u;

  425.     u->peer.log = r->connection->log;
  426.     u->peer.log_error = NGX_ERROR_ERR;

  427. #if (NGX_HTTP_CACHE)
  428.     r->cache = NULL;
  429. #endif

  430.     u->headers_in.content_length_n = -1;
  431.     u->headers_in.last_modified_time = -1;

  432.     return NGX_OK;
  433. }


  434. void
  435. ngx_http_upstream_init(ngx_http_request_t *r)
  436. {
  437.     ngx_connection_t     *c;

  438.     c = r->connection;

  439.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  440.                    "http init upstream, client timer: %d", c->read->timer_set);

  441. #if (NGX_HTTP_V2)
  442.     if (r->stream) {
  443.         ngx_http_upstream_init_request(r);
  444.         return;
  445.     }
  446. #endif

  447. #if (NGX_HTTP_V3)
  448.     if (c->quic) {
  449.         ngx_http_upstream_init_request(r);
  450.         return;
  451.     }
  452. #endif

  453.     if (c->read->timer_set) {
  454.         ngx_del_timer(c->read);
  455.     }

  456.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  457.         if (!c->write->active) {
  458.             if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT)
  459.                 == NGX_ERROR)
  460.             {
  461.                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  462.                 return;
  463.             }
  464.         }
  465.     }

  466.     ngx_http_upstream_init_request(r);
  467. }


  468. static void
  469. ngx_http_upstream_init_request(ngx_http_request_t *r)
  470. {
  471.     ngx_str_t                      *host;
  472.     ngx_uint_t                      i;
  473.     ngx_resolver_ctx_t             *ctx, temp;
  474.     ngx_http_cleanup_t             *cln;
  475.     ngx_http_upstream_t            *u;
  476.     ngx_http_core_loc_conf_t       *clcf;
  477.     ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
  478.     ngx_http_upstream_main_conf_t  *umcf;

  479.     if (r->aio) {
  480.         return;
  481.     }

  482.     u = r->upstream;

  483. #if (NGX_HTTP_CACHE)

  484.     if (u->conf->cache) {
  485.         ngx_int_t  rc;

  486.         rc = ngx_http_upstream_cache(r, u);

  487.         if (rc == NGX_BUSY) {
  488.             r->write_event_handler = ngx_http_upstream_init_request;
  489.             return;
  490.         }

  491.         r->write_event_handler = ngx_http_request_empty_handler;

  492.         if (rc == NGX_ERROR) {
  493.             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  494.             return;
  495.         }

  496.         if (rc == NGX_OK) {
  497.             rc = ngx_http_upstream_cache_send(r, u);

  498.             if (rc == NGX_DONE) {
  499.                 return;
  500.             }

  501.             if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
  502.                 rc = NGX_DECLINED;
  503.                 r->cached = 0;
  504.                 u->buffer.start = NULL;
  505.                 u->cache_status = NGX_HTTP_CACHE_MISS;
  506.                 u->request_sent = 1;
  507.             }
  508.         }

  509.         if (rc != NGX_DECLINED) {
  510.             ngx_http_finalize_request(r, rc);
  511.             return;
  512.         }
  513.     }

  514. #endif

  515.     u->store = u->conf->store;

  516.     if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {

  517.         if (r->connection->read->ready) {
  518.             ngx_post_event(r->connection->read, &ngx_posted_events);

  519.         } else {
  520.             if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
  521.                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  522.                 return;
  523.             }
  524.         }

  525.         r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
  526.         r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
  527.     }

  528.     if (r->request_body) {
  529.         u->request_bufs = r->request_body->bufs;
  530.     }

  531.     if (u->create_request(r) != NGX_OK) {
  532.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  533.         return;
  534.     }

  535.     if (ngx_http_upstream_set_local(r, u, u->conf->local) != NGX_OK) {
  536.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  537.         return;
  538.     }

  539.     if (u->conf->socket_keepalive) {
  540.         u->peer.so_keepalive = 1;
  541.     }

  542.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  543.     u->output.alignment = clcf->directio_alignment;
  544.     u->output.pool = r->pool;
  545.     u->output.bufs.num = 1;
  546.     u->output.bufs.size = clcf->client_body_buffer_size;

  547.     if (u->output.output_filter == NULL) {
  548.         u->output.output_filter = ngx_chain_writer;
  549.         u->output.filter_ctx = &u->writer;
  550.     }

  551.     u->writer.pool = r->pool;

  552.     if (r->upstream_states == NULL) {

  553.         r->upstream_states = ngx_array_create(r->pool, 1,
  554.                                             sizeof(ngx_http_upstream_state_t));
  555.         if (r->upstream_states == NULL) {
  556.             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  557.             return;
  558.         }

  559.     } else {

  560.         u->state = ngx_array_push(r->upstream_states);
  561.         if (u->state == NULL) {
  562.             ngx_http_upstream_finalize_request(r, u,
  563.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  564.             return;
  565.         }

  566.         ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
  567.     }

  568.     cln = ngx_http_cleanup_add(r, 0);
  569.     if (cln == NULL) {
  570.         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
  571.         return;
  572.     }

  573.     cln->handler = ngx_http_upstream_cleanup;
  574.     cln->data = r;
  575.     u->cleanup = &cln->handler;

  576.     if (u->resolved == NULL) {

  577.         uscf = u->conf->upstream;

  578.     } else {

  579. #if (NGX_HTTP_SSL)
  580.         u->ssl_name = u->resolved->host;
  581. #endif

  582.         host = &u->resolved->host;

  583.         umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  584.         uscfp = umcf->upstreams.elts;

  585.         for (i = 0; i < umcf->upstreams.nelts; i++) {

  586.             uscf = uscfp[i];

  587.             if (uscf->host.len == host->len
  588.                 && ((uscf->port == 0 && u->resolved->no_port)
  589.                      || uscf->port == u->resolved->port)
  590.                 && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0)
  591.             {
  592.                 goto found;
  593.             }
  594.         }

  595.         if (u->resolved->sockaddr) {

  596.             if (u->resolved->port == 0
  597.                 && u->resolved->sockaddr->sa_family != AF_UNIX)
  598.             {
  599.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  600.                               "no port in upstream \"%V\"", host);
  601.                 ngx_http_upstream_finalize_request(r, u,
  602.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  603.                 return;
  604.             }

  605.             if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
  606.                 != NGX_OK)
  607.             {
  608.                 ngx_http_upstream_finalize_request(r, u,
  609.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  610.                 return;
  611.             }

  612.             ngx_http_upstream_connect(r, u);

  613.             return;
  614.         }

  615.         if (u->resolved->port == 0) {
  616.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  617.                           "no port in upstream \"%V\"", host);
  618.             ngx_http_upstream_finalize_request(r, u,
  619.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  620.             return;
  621.         }

  622.         temp.name = *host;

  623.         ctx = ngx_resolve_start(clcf->resolver, &temp);
  624.         if (ctx == NULL) {
  625.             ngx_http_upstream_finalize_request(r, u,
  626.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  627.             return;
  628.         }

  629.         if (ctx == NGX_NO_RESOLVER) {
  630.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  631.                           "no resolver defined to resolve %V", host);

  632.             ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
  633.             return;
  634.         }

  635.         ctx->name = *host;
  636.         ctx->handler = ngx_http_upstream_resolve_handler;
  637.         ctx->data = r;
  638.         ctx->timeout = clcf->resolver_timeout;

  639.         u->resolved->ctx = ctx;

  640.         if (ngx_resolve_name(ctx) != NGX_OK) {
  641.             u->resolved->ctx = NULL;
  642.             ngx_http_upstream_finalize_request(r, u,
  643.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  644.             return;
  645.         }

  646.         return;
  647.     }

  648. found:

  649.     if (uscf == NULL) {
  650.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  651.                       "no upstream configuration");
  652.         ngx_http_upstream_finalize_request(r, u,
  653.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  654.         return;
  655.     }

  656.     u->upstream = uscf;

  657. #if (NGX_HTTP_SSL)
  658.     u->ssl_name = uscf->host;
  659. #endif

  660.     if (uscf->peer.init(r, uscf) != NGX_OK) {
  661.         ngx_http_upstream_finalize_request(r, u,
  662.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  663.         return;
  664.     }

  665.     u->peer.start_time = ngx_current_msec;

  666.     if (u->conf->next_upstream_tries
  667.         && u->peer.tries > u->conf->next_upstream_tries)
  668.     {
  669.         u->peer.tries = u->conf->next_upstream_tries;
  670.     }

  671.     ngx_http_upstream_connect(r, u);
  672. }


  673. #if (NGX_HTTP_CACHE)

  674. static ngx_int_t
  675. ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
  676. {
  677.     ngx_int_t               rc;
  678.     ngx_http_cache_t       *c;
  679.     ngx_http_file_cache_t  *cache;

  680.     c = r->cache;

  681.     if (c == NULL) {

  682.         if (!(r->method & u->conf->cache_methods)) {
  683.             return NGX_DECLINED;
  684.         }

  685.         rc = ngx_http_upstream_cache_get(r, u, &cache);

  686.         if (rc != NGX_OK) {
  687.             return rc;
  688.         }

  689.         if (r->method == NGX_HTTP_HEAD && u->conf->cache_convert_head) {
  690.             u->method = ngx_http_core_get_method;
  691.         }

  692.         if (ngx_http_file_cache_new(r) != NGX_OK) {
  693.             return NGX_ERROR;
  694.         }

  695.         if (u->create_key(r) != NGX_OK) {
  696.             return NGX_ERROR;
  697.         }

  698.         /* TODO: add keys */

  699.         ngx_http_file_cache_create_key(r);

  700.         if (r->cache->header_start + 256 > u->conf->buffer_size) {
  701.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  702.                           "%V_buffer_size %uz is not enough for cache key, "
  703.                           "it should be increased to at least %uz",
  704.                           &u->conf->module, u->conf->buffer_size,
  705.                           ngx_align(r->cache->header_start + 256, 1024));

  706.             r->cache = NULL;
  707.             return NGX_DECLINED;
  708.         }

  709.         u->cacheable = 1;

  710.         c = r->cache;

  711.         c->body_start = u->conf->buffer_size;
  712.         c->min_uses = u->conf->cache_min_uses;
  713.         c->file_cache = cache;

  714.         switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {

  715.         case NGX_ERROR:
  716.             return NGX_ERROR;

  717.         case NGX_DECLINED:
  718.             u->cache_status = NGX_HTTP_CACHE_BYPASS;
  719.             return NGX_DECLINED;

  720.         default: /* NGX_OK */
  721.             break;
  722.         }

  723.         c->lock = u->conf->cache_lock;
  724.         c->lock_timeout = u->conf->cache_lock_timeout;
  725.         c->lock_age = u->conf->cache_lock_age;

  726.         u->cache_status = NGX_HTTP_CACHE_MISS;
  727.     }

  728.     rc = ngx_http_file_cache_open(r);

  729.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  730.                    "http upstream cache: %i", rc);

  731.     switch (rc) {

  732.     case NGX_HTTP_CACHE_STALE:

  733.         if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
  734.              || c->stale_updating) && !r->background
  735.             && u->conf->cache_background_update)
  736.         {
  737.             if (ngx_http_upstream_cache_background_update(r, u) == NGX_OK) {
  738.                 r->cache->background = 1;
  739.                 u->cache_status = rc;
  740.                 rc = NGX_OK;

  741.             } else {
  742.                 rc = NGX_ERROR;
  743.             }
  744.         }

  745.         break;

  746.     case NGX_HTTP_CACHE_UPDATING:

  747.         if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
  748.              || c->stale_updating) && !r->background)
  749.         {
  750.             u->cache_status = rc;
  751.             rc = NGX_OK;

  752.         } else {
  753.             rc = NGX_HTTP_CACHE_STALE;
  754.         }

  755.         break;

  756.     case NGX_OK:
  757.         u->cache_status = NGX_HTTP_CACHE_HIT;
  758.     }

  759.     switch (rc) {

  760.     case NGX_OK:

  761.         return NGX_OK;

  762.     case NGX_HTTP_CACHE_STALE:

  763.         c->valid_sec = 0;
  764.         c->updating_sec = 0;
  765.         c->error_sec = 0;

  766.         u->buffer.start = NULL;
  767.         u->cache_status = NGX_HTTP_CACHE_EXPIRED;

  768.         break;

  769.     case NGX_DECLINED:

  770.         if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
  771.             u->buffer.start = NULL;

  772.         } else {
  773.             u->buffer.pos = u->buffer.start + c->header_start;
  774.             u->buffer.last = u->buffer.pos;
  775.         }

  776.         break;

  777.     case NGX_HTTP_CACHE_SCARCE:

  778.         u->cacheable = 0;

  779.         break;

  780.     case NGX_AGAIN:

  781.         return NGX_BUSY;

  782.     case NGX_ERROR:

  783.         return NGX_ERROR;

  784.     default:

  785.         /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */

  786.         u->cache_status = NGX_HTTP_CACHE_HIT;

  787.         return rc;
  788.     }

  789.     if (ngx_http_upstream_cache_check_range(r, u) == NGX_DECLINED) {
  790.         u->cacheable = 0;
  791.     }

  792.     r->cached = 0;

  793.     return NGX_DECLINED;
  794. }


  795. static ngx_int_t
  796. ngx_http_upstream_cache_get(ngx_http_request_t *r, ngx_http_upstream_t *u,
  797.     ngx_http_file_cache_t **cache)
  798. {
  799.     ngx_str_t               *name, val;
  800.     ngx_uint_t               i;
  801.     ngx_http_file_cache_t  **caches;

  802.     if (u->conf->cache_zone) {
  803.         *cache = u->conf->cache_zone->data;
  804.         return NGX_OK;
  805.     }

  806.     if (ngx_http_complex_value(r, u->conf->cache_value, &val) != NGX_OK) {
  807.         return NGX_ERROR;
  808.     }

  809.     if (val.len == 0
  810.         || (val.len == 3 && ngx_strncmp(val.data, "off", 3) == 0))
  811.     {
  812.         return NGX_DECLINED;
  813.     }

  814.     caches = u->caches->elts;

  815.     for (i = 0; i < u->caches->nelts; i++) {
  816.         name = &caches[i]->shm_zone->shm.name;

  817.         if (name->len == val.len
  818.             && ngx_strncmp(name->data, val.data, val.len) == 0)
  819.         {
  820.             *cache = caches[i];
  821.             return NGX_OK;
  822.         }
  823.     }

  824.     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  825.                   "cache \"%V\" not found", &val);

  826.     return NGX_ERROR;
  827. }


  828. static ngx_int_t
  829. ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
  830. {
  831.     ngx_int_t          rc;
  832.     ngx_http_cache_t  *c;

  833.     r->cached = 1;
  834.     c = r->cache;

  835.     if (c->header_start == c->body_start) {
  836.         r->http_version = NGX_HTTP_VERSION_9;
  837.         return ngx_http_cache_send(r);
  838.     }

  839.     /* TODO: cache stack */

  840.     u->buffer = *c->buf;
  841.     u->buffer.pos += c->header_start;

  842.     ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
  843.     u->headers_in.content_length_n = -1;
  844.     u->headers_in.last_modified_time = -1;

  845.     if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
  846.                       sizeof(ngx_table_elt_t))
  847.         != NGX_OK)
  848.     {
  849.         return NGX_ERROR;
  850.     }

  851.     if (ngx_list_init(&u->headers_in.trailers, r->pool, 2,
  852.                       sizeof(ngx_table_elt_t))
  853.         != NGX_OK)
  854.     {
  855.         return NGX_ERROR;
  856.     }

  857.     rc = u->process_header(r);

  858.     if (rc == NGX_OK) {

  859.         if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
  860.             return NGX_DONE;
  861.         }

  862.         return ngx_http_cache_send(r);
  863.     }

  864.     if (rc == NGX_ERROR) {
  865.         return NGX_ERROR;
  866.     }

  867.     if (rc == NGX_AGAIN) {
  868.         rc = NGX_HTTP_UPSTREAM_INVALID_HEADER;
  869.     }

  870.     /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */

  871.     ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
  872.                   "cache file \"%s\" contains invalid header",
  873.                   c->file.name.data);

  874.     /* TODO: delete file */

  875.     return rc;
  876. }


  877. static ngx_int_t
  878. ngx_http_upstream_cache_background_update(ngx_http_request_t *r,
  879.     ngx_http_upstream_t *u)
  880. {
  881.     ngx_http_request_t  *sr;

  882.     if (r == r->main) {
  883.         r->preserve_body = 1;
  884.     }

  885.     if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL,
  886.                             NGX_HTTP_SUBREQUEST_CLONE
  887.                             |NGX_HTTP_SUBREQUEST_BACKGROUND)
  888.         != NGX_OK)
  889.     {
  890.         return NGX_ERROR;
  891.     }

  892.     sr->header_only = 1;

  893.     return NGX_OK;
  894. }


  895. static ngx_int_t
  896. ngx_http_upstream_cache_check_range(ngx_http_request_t *r,
  897.     ngx_http_upstream_t *u)
  898. {
  899.     off_t             offset;
  900.     u_char           *p, *start;
  901.     ngx_table_elt_t  *h;

  902.     h = r->headers_in.range;

  903.     if (h == NULL
  904.         || !u->cacheable
  905.         || u->conf->cache_max_range_offset == NGX_MAX_OFF_T_VALUE)
  906.     {
  907.         return NGX_OK;
  908.     }

  909.     if (u->conf->cache_max_range_offset == 0) {
  910.         return NGX_DECLINED;
  911.     }

  912.     if (h->value.len < 7
  913.         || ngx_strncasecmp(h->value.data, (u_char *) "bytes=", 6) != 0)
  914.     {
  915.         return NGX_OK;
  916.     }

  917.     p = h->value.data + 6;

  918.     while (*p == ' ') { p++; }

  919.     if (*p == '-') {
  920.         return NGX_DECLINED;
  921.     }

  922.     start = p;

  923.     while (*p >= '0' && *p <= '9') { p++; }

  924.     offset = ngx_atoof(start, p - start);

  925.     if (offset >= u->conf->cache_max_range_offset) {
  926.         return NGX_DECLINED;
  927.     }

  928.     return NGX_OK;
  929. }

  930. #endif


  931. static void
  932. ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
  933. {
  934.     ngx_uint_t                     run_posted;
  935.     ngx_connection_t              *c;
  936.     ngx_http_request_t            *r;
  937.     ngx_http_upstream_t           *u;
  938.     ngx_http_upstream_resolved_t  *ur;

  939.     run_posted = ctx->async;

  940.     r = ctx->data;
  941.     c = r->connection;

  942.     u = r->upstream;
  943.     ur = u->resolved;

  944.     ngx_http_set_log_request(c->log, r);

  945.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  946.                    "http upstream resolve: \"%V?%V\"", &r->uri, &r->args);

  947.     if (ctx->state) {
  948.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  949.                       "%V could not be resolved (%i: %s)",
  950.                       &ctx->name, ctx->state,
  951.                       ngx_resolver_strerror(ctx->state));

  952.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
  953.         goto failed;
  954.     }

  955.     ur->naddrs = ctx->naddrs;
  956.     ur->addrs = ctx->addrs;

  957. #if (NGX_DEBUG)
  958.     {
  959.     u_char      text[NGX_SOCKADDR_STRLEN];
  960.     ngx_str_t   addr;
  961.     ngx_uint_t  i;

  962.     addr.data = text;

  963.     for (i = 0; i < ctx->naddrs; i++) {
  964.         addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
  965.                                  text, NGX_SOCKADDR_STRLEN, 0);

  966.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  967.                        "name was resolved to %V", &addr);
  968.     }
  969.     }
  970. #endif

  971.     if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) {
  972.         ngx_http_upstream_finalize_request(r, u,
  973.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  974.         goto failed;
  975.     }

  976.     ngx_resolve_name_done(ctx);
  977.     ur->ctx = NULL;

  978.     u->peer.start_time = ngx_current_msec;

  979.     if (u->conf->next_upstream_tries
  980.         && u->peer.tries > u->conf->next_upstream_tries)
  981.     {
  982.         u->peer.tries = u->conf->next_upstream_tries;
  983.     }

  984.     ngx_http_upstream_connect(r, u);

  985. failed:

  986.     if (run_posted) {
  987.         ngx_http_run_posted_requests(c);
  988.     }
  989. }


  990. static void
  991. ngx_http_upstream_handler(ngx_event_t *ev)
  992. {
  993.     ngx_connection_t     *c;
  994.     ngx_http_request_t   *r;
  995.     ngx_http_upstream_t  *u;

  996.     c = ev->data;
  997.     r = c->data;

  998.     u = r->upstream;
  999.     c = r->connection;

  1000.     ngx_http_set_log_request(c->log, r);

  1001.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1002.                    "http upstream request: \"%V?%V\"", &r->uri, &r->args);

  1003.     if (ev->delayed && ev->timedout) {
  1004.         ev->delayed = 0;
  1005.         ev->timedout = 0;
  1006.     }

  1007.     if (ev->write) {
  1008.         u->write_event_handler(r, u);

  1009.     } else {
  1010.         u->read_event_handler(r, u);
  1011.     }

  1012.     ngx_http_run_posted_requests(c);
  1013. }


  1014. static void
  1015. ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
  1016. {
  1017.     ngx_http_upstream_check_broken_connection(r, r->connection->read);
  1018. }


  1019. static void
  1020. ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
  1021. {
  1022.     ngx_http_upstream_check_broken_connection(r, r->connection->write);
  1023. }


  1024. static void
  1025. ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
  1026.     ngx_event_t *ev)
  1027. {
  1028.     int                  n;
  1029.     char                 buf[1];
  1030.     ngx_err_t            err;
  1031.     ngx_int_t            event;
  1032.     ngx_connection_t     *c;
  1033.     ngx_http_upstream_t  *u;

  1034.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
  1035.                    "http upstream check client, write event:%d, \"%V\"",
  1036.                    ev->write, &r->uri);

  1037.     c = r->connection;
  1038.     u = r->upstream;

  1039.     if (c->error) {
  1040.         if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {

  1041.             event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;

  1042.             if (ngx_del_event(ev, event, 0) != NGX_OK) {
  1043.                 ngx_http_upstream_finalize_request(r, u,
  1044.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1045.                 return;
  1046.             }
  1047.         }

  1048.         if (!u->cacheable) {
  1049.             ngx_http_upstream_finalize_request(r, u,
  1050.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1051.         }

  1052.         return;
  1053.     }

  1054. #if (NGX_HTTP_V2)
  1055.     if (r->stream) {
  1056.         return;
  1057.     }
  1058. #endif

  1059. #if (NGX_HTTP_V3)

  1060.     if (c->quic) {
  1061.         if (c->write->error) {
  1062.             ngx_http_upstream_finalize_request(r, u,
  1063.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1064.         }

  1065.         return;
  1066.     }

  1067. #endif

  1068. #if (NGX_HAVE_KQUEUE)

  1069.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {

  1070.         if (!ev->pending_eof) {
  1071.             return;
  1072.         }

  1073.         ev->eof = 1;
  1074.         c->error = 1;

  1075.         if (ev->kq_errno) {
  1076.             ev->error = 1;
  1077.         }

  1078.         if (!u->cacheable && u->peer.connection) {
  1079.             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
  1080.                           "kevent() reported that client prematurely closed "
  1081.                           "connection, so upstream connection is closed too");
  1082.             ngx_http_upstream_finalize_request(r, u,
  1083.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1084.             return;
  1085.         }

  1086.         ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
  1087.                       "kevent() reported that client prematurely closed "
  1088.                       "connection");

  1089.         if (u->peer.connection == NULL) {
  1090.             ngx_http_upstream_finalize_request(r, u,
  1091.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1092.         }

  1093.         return;
  1094.     }

  1095. #endif

  1096. #if (NGX_HAVE_EPOLLRDHUP)

  1097.     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
  1098.         socklen_t  len;

  1099.         if (!ev->pending_eof) {
  1100.             return;
  1101.         }

  1102.         ev->eof = 1;
  1103.         c->error = 1;

  1104.         err = 0;
  1105.         len = sizeof(ngx_err_t);

  1106.         /*
  1107.          * BSDs and Linux return 0 and set a pending error in err
  1108.          * Solaris returns -1 and sets errno
  1109.          */

  1110.         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
  1111.             == -1)
  1112.         {
  1113.             err = ngx_socket_errno;
  1114.         }

  1115.         if (err) {
  1116.             ev->error = 1;
  1117.         }

  1118.         if (!u->cacheable && u->peer.connection) {
  1119.             ngx_log_error(NGX_LOG_INFO, ev->log, err,
  1120.                         "epoll_wait() reported that client prematurely closed "
  1121.                         "connection, so upstream connection is closed too");
  1122.             ngx_http_upstream_finalize_request(r, u,
  1123.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1124.             return;
  1125.         }

  1126.         ngx_log_error(NGX_LOG_INFO, ev->log, err,
  1127.                       "epoll_wait() reported that client prematurely closed "
  1128.                       "connection");

  1129.         if (u->peer.connection == NULL) {
  1130.             ngx_http_upstream_finalize_request(r, u,
  1131.                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1132.         }

  1133.         return;
  1134.     }

  1135. #endif

  1136.     n = recv(c->fd, buf, 1, MSG_PEEK);

  1137.     err = ngx_socket_errno;

  1138.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err,
  1139.                    "http upstream recv(): %d", n);

  1140.     if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
  1141.         return;
  1142.     }

  1143.     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {

  1144.         event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;

  1145.         if (ngx_del_event(ev, event, 0) != NGX_OK) {
  1146.             ngx_http_upstream_finalize_request(r, u,
  1147.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1148.             return;
  1149.         }
  1150.     }

  1151.     if (n > 0) {
  1152.         return;
  1153.     }

  1154.     if (n == -1) {
  1155.         if (err == NGX_EAGAIN) {
  1156.             return;
  1157.         }

  1158.         ev->error = 1;

  1159.     } else { /* n == 0 */
  1160.         err = 0;
  1161.     }

  1162.     ev->eof = 1;
  1163.     c->error = 1;

  1164.     if (!u->cacheable && u->peer.connection) {
  1165.         ngx_log_error(NGX_LOG_INFO, ev->log, err,
  1166.                       "client prematurely closed connection, "
  1167.                       "so upstream connection is closed too");
  1168.         ngx_http_upstream_finalize_request(r, u,
  1169.                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1170.         return;
  1171.     }

  1172.     ngx_log_error(NGX_LOG_INFO, ev->log, err,
  1173.                   "client prematurely closed connection");

  1174.     if (u->peer.connection == NULL) {
  1175.         ngx_http_upstream_finalize_request(r, u,
  1176.                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
  1177.     }
  1178. }


  1179. static void
  1180. ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
  1181. {
  1182.     ngx_int_t                  rc;
  1183.     ngx_connection_t          *c;
  1184.     ngx_http_core_loc_conf_t  *clcf;

  1185.     r->connection->log->action = "connecting to upstream";

  1186.     if (u->state && u->state->response_time == (ngx_msec_t) -1) {
  1187.         u->state->response_time = ngx_current_msec - u->start_time;
  1188.     }

  1189.     u->state = ngx_array_push(r->upstream_states);
  1190.     if (u->state == NULL) {
  1191.         ngx_http_upstream_finalize_request(r, u,
  1192.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  1193.         return;
  1194.     }

  1195.     ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));

  1196.     u->start_time = ngx_current_msec;

  1197.     u->state->response_time = (ngx_msec_t) -1;
  1198.     u->state->connect_time = (ngx_msec_t) -1;
  1199.     u->state->header_time = (ngx_msec_t) -1;

  1200.     rc = ngx_event_connect_peer(&u->peer);

  1201.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1202.                    "http upstream connect: %i", rc);

  1203.     if (rc == NGX_ERROR) {
  1204.         ngx_http_upstream_finalize_request(r, u,
  1205.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  1206.         return;
  1207.     }

  1208.     u->state->peer = u->peer.name;

  1209. #if (NGX_HTTP_UPSTREAM_ZONE)
  1210.     if (u->upstream && u->upstream->shm_zone
  1211.         && (u->upstream->flags & NGX_HTTP_UPSTREAM_MODIFY))
  1212.     {
  1213.         u->state->peer = ngx_palloc(r->pool,
  1214.                                     sizeof(ngx_str_t) + u->peer.name->len);
  1215.         if (u->state->peer == NULL) {
  1216.             ngx_http_upstream_finalize_request(r, u,
  1217.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1218.             return;
  1219.         }

  1220.         u->state->peer->len = u->peer.name->len;
  1221.         u->state->peer->data = (u_char *) (u->state->peer + 1);
  1222.         ngx_memcpy(u->state->peer->data, u->peer.name->data, u->peer.name->len);

  1223.         u->peer.name = u->state->peer;
  1224.     }
  1225. #endif

  1226.     if (rc == NGX_BUSY) {
  1227.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
  1228.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
  1229.         return;
  1230.     }

  1231.     if (rc == NGX_DECLINED) {
  1232.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1233.         return;
  1234.     }

  1235.     /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */

  1236.     c = u->peer.connection;

  1237.     c->requests++;

  1238.     c->data = r;

  1239.     c->write->handler = ngx_http_upstream_handler;
  1240.     c->read->handler = ngx_http_upstream_handler;

  1241.     u->write_event_handler = ngx_http_upstream_send_request_handler;
  1242.     u->read_event_handler = ngx_http_upstream_process_header;

  1243.     c->sendfile &= r->connection->sendfile;
  1244.     u->output.sendfile = c->sendfile;

  1245.     if (r->connection->tcp_nopush == NGX_TCP_NOPUSH_DISABLED) {
  1246.         c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
  1247.     }

  1248.     if (c->pool == NULL) {

  1249.         /* we need separate pool here to be able to cache SSL connections */

  1250.         c->pool = ngx_create_pool(128, r->connection->log);
  1251.         if (c->pool == NULL) {
  1252.             ngx_http_upstream_finalize_request(r, u,
  1253.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1254.             return;
  1255.         }
  1256.     }

  1257.     c->log = r->connection->log;
  1258.     c->pool->log = c->log;
  1259.     c->read->log = c->log;
  1260.     c->write->log = c->log;

  1261.     /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */

  1262.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1263.     u->writer.out = NULL;
  1264.     u->writer.last = &u->writer.out;
  1265.     u->writer.connection = c;
  1266.     u->writer.limit = clcf->sendfile_max_chunk;

  1267.     if (u->request_sent) {
  1268.         if (ngx_http_upstream_reinit(r, u) != NGX_OK) {
  1269.             ngx_http_upstream_finalize_request(r, u,
  1270.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1271.             return;
  1272.         }
  1273.     }

  1274.     if (r->request_body
  1275.         && r->request_body->buf
  1276.         && r->request_body->temp_file
  1277.         && r == r->main)
  1278.     {
  1279.         /*
  1280.          * the r->request_body->buf can be reused for one request only,
  1281.          * the subrequests should allocate their own temporary bufs
  1282.          */

  1283.         u->output.free = ngx_alloc_chain_link(r->pool);
  1284.         if (u->output.free == NULL) {
  1285.             ngx_http_upstream_finalize_request(r, u,
  1286.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1287.             return;
  1288.         }

  1289.         u->output.free->buf = r->request_body->buf;
  1290.         u->output.free->next = NULL;
  1291.         u->output.allocated = 1;

  1292.         r->request_body->buf->pos = r->request_body->buf->start;
  1293.         r->request_body->buf->last = r->request_body->buf->start;
  1294.         r->request_body->buf->tag = u->output.tag;
  1295.     }

  1296.     u->request_sent = 0;
  1297.     u->request_body_sent = 0;
  1298.     u->request_body_blocked = 0;

  1299.     if (rc == NGX_AGAIN) {
  1300.         ngx_add_timer(c->write, u->conf->connect_timeout);
  1301.         return;
  1302.     }

  1303. #if (NGX_HTTP_SSL)

  1304.     if (u->ssl && c->ssl == NULL) {
  1305.         ngx_http_upstream_ssl_init_connection(r, u, c);
  1306.         return;
  1307.     }

  1308. #endif

  1309.     ngx_http_upstream_send_request(r, u, 1);
  1310. }


  1311. #if (NGX_HTTP_SSL)

  1312. static void
  1313. ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
  1314.     ngx_http_upstream_t *u, ngx_connection_t *c)
  1315. {
  1316.     ngx_int_t                  rc;
  1317.     ngx_http_core_loc_conf_t  *clcf;

  1318.     if (ngx_http_upstream_test_connect(c) != NGX_OK) {
  1319.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1320.         return;
  1321.     }

  1322.     if (ngx_ssl_create_connection(u->conf->ssl, c,
  1323.                                   NGX_SSL_BUFFER|NGX_SSL_CLIENT)
  1324.         != NGX_OK)
  1325.     {
  1326.         ngx_http_upstream_finalize_request(r, u,
  1327.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  1328.         return;
  1329.     }

  1330.     if (u->conf->ssl_server_name || u->conf->ssl_verify) {
  1331.         if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) {
  1332.             ngx_http_upstream_finalize_request(r, u,
  1333.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1334.             return;
  1335.         }
  1336.     }

  1337.     if (u->conf->ssl_certificate
  1338.         && u->conf->ssl_certificate->value.len
  1339.         && (u->conf->ssl_certificate->lengths
  1340.             || u->conf->ssl_certificate_key->lengths))
  1341.     {
  1342.         if (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) {
  1343.             ngx_http_upstream_finalize_request(r, u,
  1344.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1345.             return;
  1346.         }
  1347.     }

  1348.     if (u->conf->ssl_session_reuse) {
  1349.         c->ssl->save_session = ngx_http_upstream_ssl_save_session;

  1350.         if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
  1351.             ngx_http_upstream_finalize_request(r, u,
  1352.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1353.             return;
  1354.         }

  1355.         /* abbreviated SSL handshake may interact badly with Nagle */

  1356.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1357.         if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
  1358.             ngx_http_upstream_finalize_request(r, u,
  1359.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1360.             return;
  1361.         }
  1362.     }

  1363.     r->connection->log->action = "SSL handshaking to upstream";

  1364.     rc = ngx_ssl_handshake(c);

  1365.     if (rc == NGX_AGAIN) {

  1366.         if (!c->write->timer_set) {
  1367.             ngx_add_timer(c->write, u->conf->connect_timeout);
  1368.         }

  1369.         c->ssl->handler = ngx_http_upstream_ssl_handshake_handler;
  1370.         return;
  1371.     }

  1372.     ngx_http_upstream_ssl_handshake(r, u, c);
  1373. }


  1374. static void
  1375. ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c)
  1376. {
  1377.     ngx_http_request_t   *r;
  1378.     ngx_http_upstream_t  *u;

  1379.     r = c->data;

  1380.     u = r->upstream;
  1381.     c = r->connection;

  1382.     ngx_http_set_log_request(c->log, r);

  1383.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1384.                    "http upstream ssl handshake: \"%V?%V\"",
  1385.                    &r->uri, &r->args);

  1386.     ngx_http_upstream_ssl_handshake(r, u, u->peer.connection);

  1387.     ngx_http_run_posted_requests(c);
  1388. }


  1389. static void
  1390. ngx_http_upstream_ssl_handshake(ngx_http_request_t *r, ngx_http_upstream_t *u,
  1391.     ngx_connection_t *c)
  1392. {
  1393.     long  rc;

  1394.     if (c->ssl->handshaked) {

  1395.         if (u->conf->ssl_verify) {
  1396.             rc = SSL_get_verify_result(c->ssl->connection);

  1397.             if (rc != X509_V_OK) {
  1398.                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
  1399.                               "upstream SSL certificate verify error: (%l:%s)",
  1400.                               rc, X509_verify_cert_error_string(rc));
  1401.                 goto failed;
  1402.             }

  1403.             if (ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) {
  1404.                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
  1405.                               "upstream SSL certificate does not match \"%V\"",
  1406.                               &u->ssl_name);
  1407.                 goto failed;
  1408.             }
  1409.         }

  1410.         if (!c->ssl->sendfile) {
  1411.             c->sendfile = 0;
  1412.             u->output.sendfile = 0;
  1413.         }

  1414.         c->write->handler = ngx_http_upstream_handler;
  1415.         c->read->handler = ngx_http_upstream_handler;

  1416.         ngx_http_upstream_send_request(r, u, 1);

  1417.         return;
  1418.     }

  1419.     if (c->write->timedout) {
  1420.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
  1421.         return;
  1422.     }

  1423. failed:

  1424.     ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1425. }


  1426. static void
  1427. ngx_http_upstream_ssl_save_session(ngx_connection_t *c)
  1428. {
  1429.     ngx_http_request_t   *r;
  1430.     ngx_http_upstream_t  *u;

  1431.     if (c->idle) {
  1432.         return;
  1433.     }

  1434.     r = c->data;

  1435.     u = r->upstream;
  1436.     c = r->connection;

  1437.     ngx_http_set_log_request(c->log, r);

  1438.     u->peer.save_session(&u->peer, u->peer.data);
  1439. }


  1440. static ngx_int_t
  1441. ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u,
  1442.     ngx_connection_t *c)
  1443. {
  1444.     u_char     *p, *last;
  1445.     ngx_str_t   name;

  1446.     if (u->conf->ssl_name) {
  1447.         if (ngx_http_complex_value(r, u->conf->ssl_name, &name) != NGX_OK) {
  1448.             return NGX_ERROR;
  1449.         }

  1450.     } else {
  1451.         name = u->ssl_name;
  1452.     }

  1453.     if (name.len == 0) {
  1454.         goto done;
  1455.     }

  1456.     /*
  1457.      * ssl name here may contain port, notably if derived from $proxy_host
  1458.      * or $http_host; we have to strip it
  1459.      */

  1460.     p = name.data;
  1461.     last = name.data + name.len;

  1462.     if (*p == '[') {
  1463.         p = ngx_strlchr(p, last, ']');

  1464.         if (p == NULL) {
  1465.             p = name.data;
  1466.         }
  1467.     }

  1468.     p = ngx_strlchr(p, last, ':');

  1469.     if (p != NULL) {
  1470.         name.len = p - name.data;
  1471.     }

  1472.     if (!u->conf->ssl_server_name) {
  1473.         goto done;
  1474.     }

  1475. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME

  1476.     /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */

  1477.     if (name.len == 0 || *name.data == '[') {
  1478.         goto done;
  1479.     }

  1480.     if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) {
  1481.         goto done;
  1482.     }

  1483.     /*
  1484.      * SSL_set_tlsext_host_name() needs a null-terminated string,
  1485.      * hence we explicitly null-terminate name here
  1486.      */

  1487.     p = ngx_pnalloc(r->pool, name.len + 1);
  1488.     if (p == NULL) {
  1489.         return NGX_ERROR;
  1490.     }

  1491.     (void) ngx_cpystrn(p, name.data, name.len + 1);

  1492.     name.data = p;

  1493.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1494.                    "upstream SSL server name: \"%s\"", name.data);

  1495.     if (SSL_set_tlsext_host_name(c->ssl->connection,
  1496.                                  (char *) name.data)
  1497.         == 0)
  1498.     {
  1499.         ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0,
  1500.                       "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
  1501.         return NGX_ERROR;
  1502.     }

  1503. #endif

  1504. done:

  1505.     u->ssl_name = name;

  1506.     return NGX_OK;
  1507. }


  1508. static ngx_int_t
  1509. ngx_http_upstream_ssl_certificate(ngx_http_request_t *r,
  1510.     ngx_http_upstream_t *u, ngx_connection_t *c)
  1511. {
  1512.     ngx_str_t  cert, key;

  1513.     if (ngx_http_complex_value(r, u->conf->ssl_certificate, &cert)
  1514.         != NGX_OK)
  1515.     {
  1516.         return NGX_ERROR;
  1517.     }

  1518.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1519.                    "http upstream ssl cert: \"%s\"", cert.data);

  1520.     if (*cert.data == '\0') {
  1521.         return NGX_OK;
  1522.     }

  1523.     if (ngx_http_complex_value(r, u->conf->ssl_certificate_key, &key)
  1524.         != NGX_OK)
  1525.     {
  1526.         return NGX_ERROR;
  1527.     }

  1528.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1529.                    "http upstream ssl key: \"%s\"", key.data);

  1530.     if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key,
  1531.                                        u->conf->ssl_passwords)
  1532.         != NGX_OK)
  1533.     {
  1534.         return NGX_ERROR;
  1535.     }

  1536.     return NGX_OK;
  1537. }

  1538. #endif


  1539. static ngx_int_t
  1540. ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
  1541. {
  1542.     off_t         file_pos;
  1543.     ngx_chain_t  *cl;

  1544.     if (u->reinit_request(r) != NGX_OK) {
  1545.         return NGX_ERROR;
  1546.     }

  1547.     u->keepalive = 0;
  1548.     u->upgrade = 0;
  1549.     u->error = 0;

  1550.     ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
  1551.     u->headers_in.content_length_n = -1;
  1552.     u->headers_in.last_modified_time = -1;

  1553.     if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
  1554.                       sizeof(ngx_table_elt_t))
  1555.         != NGX_OK)
  1556.     {
  1557.         return NGX_ERROR;
  1558.     }

  1559.     if (ngx_list_init(&u->headers_in.trailers, r->pool, 2,
  1560.                       sizeof(ngx_table_elt_t))
  1561.         != NGX_OK)
  1562.     {
  1563.         return NGX_ERROR;
  1564.     }

  1565.     /* reinit the request chain */

  1566.     file_pos = 0;

  1567.     for (cl = u->request_bufs; cl; cl = cl->next) {
  1568.         cl->buf->pos = cl->buf->start;

  1569.         /* there is at most one file */

  1570.         if (cl->buf->in_file) {
  1571.             cl->buf->file_pos = file_pos;
  1572.             file_pos = cl->buf->file_last;
  1573.         }
  1574.     }

  1575.     /* reinit the subrequest's ngx_output_chain() context */

  1576.     if (r->request_body && r->request_body->temp_file
  1577.         && r != r->main && u->output.buf)
  1578.     {
  1579.         u->output.free = ngx_alloc_chain_link(r->pool);
  1580.         if (u->output.free == NULL) {
  1581.             return NGX_ERROR;
  1582.         }

  1583.         u->output.free->buf = u->output.buf;
  1584.         u->output.free->next = NULL;

  1585.         u->output.buf->pos = u->output.buf->start;
  1586.         u->output.buf->last = u->output.buf->start;
  1587.     }

  1588.     u->output.buf = NULL;
  1589.     u->output.in = NULL;
  1590.     u->output.busy = NULL;

  1591.     /* reinit u->buffer */

  1592.     u->buffer.pos = u->buffer.start;

  1593. #if (NGX_HTTP_CACHE)

  1594.     if (r->cache) {
  1595.         u->buffer.pos += r->cache->header_start;
  1596.     }

  1597. #endif

  1598.     u->buffer.last = u->buffer.pos;

  1599.     return NGX_OK;
  1600. }


  1601. static void
  1602. ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
  1603.     ngx_uint_t do_write)
  1604. {
  1605.     ngx_int_t          rc;
  1606.     ngx_connection_t  *c;

  1607.     c = u->peer.connection;

  1608.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1609.                    "http upstream send request");

  1610.     if (u->state->connect_time == (ngx_msec_t) -1) {
  1611.         u->state->connect_time = ngx_current_msec - u->start_time;
  1612.     }

  1613.     if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
  1614.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1615.         return;
  1616.     }

  1617.     c->log->action = "sending request to upstream";

  1618.     rc = ngx_http_upstream_send_request_body(r, u, do_write);

  1619.     if (rc == NGX_ERROR) {
  1620.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1621.         return;
  1622.     }

  1623.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  1624.         ngx_http_upstream_finalize_request(r, u, rc);
  1625.         return;
  1626.     }

  1627.     if (rc == NGX_AGAIN) {
  1628.         if (!c->write->ready || u->request_body_blocked) {
  1629.             ngx_add_timer(c->write, u->conf->send_timeout);

  1630.         } else if (c->write->timer_set) {
  1631.             ngx_del_timer(c->write);
  1632.         }

  1633.         if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
  1634.             ngx_http_upstream_finalize_request(r, u,
  1635.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1636.             return;
  1637.         }

  1638.         if (c->write->ready && c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
  1639.             if (ngx_tcp_push(c->fd) == -1) {
  1640.                 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
  1641.                               ngx_tcp_push_n " failed");
  1642.                 ngx_http_upstream_finalize_request(r, u,
  1643.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1644.                 return;
  1645.             }

  1646.             c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
  1647.         }

  1648.         if (c->read->ready) {
  1649.             ngx_post_event(c->read, &ngx_posted_events);
  1650.         }

  1651.         return;
  1652.     }

  1653.     /* rc == NGX_OK */

  1654.     if (c->write->timer_set) {
  1655.         ngx_del_timer(c->write);
  1656.     }

  1657.     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
  1658.         if (ngx_tcp_push(c->fd) == -1) {
  1659.             ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
  1660.                           ngx_tcp_push_n " failed");
  1661.             ngx_http_upstream_finalize_request(r, u,
  1662.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1663.             return;
  1664.         }

  1665.         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
  1666.     }

  1667.     if (!u->conf->preserve_output) {
  1668.         u->write_event_handler = ngx_http_upstream_dummy_handler;
  1669.     }

  1670.     if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
  1671.         ngx_http_upstream_finalize_request(r, u,
  1672.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  1673.         return;
  1674.     }

  1675.     if (!u->request_body_sent) {
  1676.         u->request_body_sent = 1;

  1677.         if (u->header_sent) {
  1678.             return;
  1679.         }

  1680.         ngx_add_timer(c->read, u->conf->read_timeout);

  1681.         if (c->read->ready) {
  1682.             ngx_http_upstream_process_header(r, u);
  1683.             return;
  1684.         }
  1685.     }
  1686. }


  1687. static ngx_int_t
  1688. ngx_http_upstream_send_request_body(ngx_http_request_t *r,
  1689.     ngx_http_upstream_t *u, ngx_uint_t do_write)
  1690. {
  1691.     ngx_int_t                  rc;
  1692.     ngx_chain_t               *out, *cl, *ln;
  1693.     ngx_connection_t          *c;
  1694.     ngx_http_core_loc_conf_t  *clcf;

  1695.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1696.                    "http upstream send request body");

  1697.     if (!r->request_body_no_buffering) {

  1698.         /* buffered request body */

  1699.         if (!u->request_sent) {
  1700.             u->request_sent = 1;
  1701.             out = u->request_bufs;

  1702.         } else {
  1703.             out = NULL;
  1704.         }

  1705.         rc = ngx_output_chain(&u->output, out);

  1706.         if (rc == NGX_AGAIN) {
  1707.             u->request_body_blocked = 1;

  1708.         } else {
  1709.             u->request_body_blocked = 0;
  1710.         }

  1711.         return rc;
  1712.     }

  1713.     if (!u->request_sent) {
  1714.         u->request_sent = 1;
  1715.         out = u->request_bufs;

  1716.         if (r->request_body->bufs) {
  1717.             for (cl = out; cl->next; cl = cl->next) { /* void */ }
  1718.             cl->next = r->request_body->bufs;
  1719.             r->request_body->bufs = NULL;
  1720.         }

  1721.         c = u->peer.connection;
  1722.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1723.         if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
  1724.             return NGX_ERROR;
  1725.         }

  1726.         r->read_event_handler = ngx_http_upstream_read_request_handler;

  1727.     } else {
  1728.         out = NULL;
  1729.     }

  1730.     for ( ;; ) {

  1731.         if (do_write) {
  1732.             rc = ngx_output_chain(&u->output, out);

  1733.             if (rc == NGX_ERROR) {
  1734.                 return NGX_ERROR;
  1735.             }

  1736.             while (out) {
  1737.                 ln = out;
  1738.                 out = out->next;
  1739.                 ngx_free_chain(r->pool, ln);
  1740.             }

  1741.             if (rc == NGX_AGAIN) {
  1742.                 u->request_body_blocked = 1;

  1743.             } else {
  1744.                 u->request_body_blocked = 0;
  1745.             }

  1746.             if (rc == NGX_OK && !r->reading_body) {
  1747.                 break;
  1748.             }
  1749.         }

  1750.         if (r->reading_body) {
  1751.             /* read client request body */

  1752.             rc = ngx_http_read_unbuffered_request_body(r);

  1753.             if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  1754.                 return rc;
  1755.             }

  1756.             out = r->request_body->bufs;
  1757.             r->request_body->bufs = NULL;
  1758.         }

  1759.         /* stop if there is nothing to send */

  1760.         if (out == NULL) {
  1761.             rc = NGX_AGAIN;
  1762.             break;
  1763.         }

  1764.         do_write = 1;
  1765.     }

  1766.     if (!r->reading_body) {
  1767.         if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
  1768.             r->read_event_handler =
  1769.                                   ngx_http_upstream_rd_check_broken_connection;
  1770.         }
  1771.     }

  1772.     return rc;
  1773. }


  1774. static void
  1775. ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
  1776.     ngx_http_upstream_t *u)
  1777. {
  1778.     ngx_connection_t  *c;

  1779.     c = u->peer.connection;

  1780.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1781.                    "http upstream send request handler");

  1782.     if (c->write->timedout) {
  1783.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
  1784.         return;
  1785.     }

  1786. #if (NGX_HTTP_SSL)

  1787.     if (u->ssl && c->ssl == NULL) {
  1788.         ngx_http_upstream_ssl_init_connection(r, u, c);
  1789.         return;
  1790.     }

  1791. #endif

  1792.     if (u->header_sent && !u->conf->preserve_output) {
  1793.         u->write_event_handler = ngx_http_upstream_dummy_handler;

  1794.         (void) ngx_handle_write_event(c->write, 0);

  1795.         return;
  1796.     }

  1797.     ngx_http_upstream_send_request(r, u, 1);
  1798. }


  1799. static void
  1800. ngx_http_upstream_read_request_handler(ngx_http_request_t *r)
  1801. {
  1802.     ngx_connection_t     *c;
  1803.     ngx_http_upstream_t  *u;

  1804.     c = r->connection;
  1805.     u = r->upstream;

  1806.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1807.                    "http upstream read request handler");

  1808.     if (c->read->timedout) {
  1809.         c->timedout = 1;
  1810.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
  1811.         return;
  1812.     }

  1813.     ngx_http_upstream_send_request(r, u, 0);
  1814. }


  1815. static void
  1816. ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
  1817. {
  1818.     ssize_t            n;
  1819.     ngx_int_t          rc;
  1820.     ngx_connection_t  *c;

  1821.     c = u->peer.connection;

  1822.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1823.                    "http upstream process header");

  1824.     c->log->action = "reading response header from upstream";

  1825.     if (c->read->timedout) {
  1826.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
  1827.         return;
  1828.     }

  1829.     if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
  1830.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1831.         return;
  1832.     }

  1833.     if (u->buffer.start == NULL) {
  1834.         u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
  1835.         if (u->buffer.start == NULL) {
  1836.             ngx_http_upstream_finalize_request(r, u,
  1837.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1838.             return;
  1839.         }

  1840.         u->buffer.pos = u->buffer.start;
  1841.         u->buffer.last = u->buffer.start;
  1842.         u->buffer.end = u->buffer.start + u->conf->buffer_size;
  1843.         u->buffer.temporary = 1;

  1844.         u->buffer.tag = u->output.tag;

  1845.         if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
  1846.                           sizeof(ngx_table_elt_t))
  1847.             != NGX_OK)
  1848.         {
  1849.             ngx_http_upstream_finalize_request(r, u,
  1850.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1851.             return;
  1852.         }

  1853.         if (ngx_list_init(&u->headers_in.trailers, r->pool, 2,
  1854.                           sizeof(ngx_table_elt_t))
  1855.             != NGX_OK)
  1856.         {
  1857.             ngx_http_upstream_finalize_request(r, u,
  1858.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1859.             return;
  1860.         }

  1861. #if (NGX_HTTP_CACHE)

  1862.         if (r->cache) {
  1863.             u->buffer.pos += r->cache->header_start;
  1864.             u->buffer.last = u->buffer.pos;
  1865.         }
  1866. #endif
  1867.     }

  1868.     for ( ;; ) {

  1869.         n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);

  1870.         if (n == NGX_AGAIN) {
  1871. #if 0
  1872.             ngx_add_timer(rev, u->read_timeout);
  1873. #endif

  1874.             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  1875.                 ngx_http_upstream_finalize_request(r, u,
  1876.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  1877.                 return;
  1878.             }

  1879.             return;
  1880.         }

  1881.         if (n == 0) {
  1882.             ngx_log_error(NGX_LOG_ERR, c->log, 0,
  1883.                           "upstream prematurely closed connection");
  1884.         }

  1885.         if (n == NGX_ERROR || n == 0) {
  1886.             ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
  1887.             return;
  1888.         }

  1889.         u->state->bytes_received += n;

  1890.         u->buffer.last += n;

  1891. #if 0
  1892.         u->valid_header_in = 0;

  1893.         u->peer.cached = 0;
  1894. #endif

  1895.         rc = u->process_header(r);

  1896.         if (rc == NGX_AGAIN) {

  1897.             if (u->buffer.last == u->buffer.end) {
  1898.                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
  1899.                               "upstream sent too big header");

  1900.                 ngx_http_upstream_next(r, u,
  1901.                                        NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
  1902.                 return;
  1903.             }

  1904.             continue;
  1905.         }

  1906.         break;
  1907.     }

  1908.     if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
  1909.         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
  1910.         return;
  1911.     }

  1912.     if (rc == NGX_ERROR) {
  1913.         ngx_http_upstream_finalize_request(r, u,
  1914.                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
  1915.         return;
  1916.     }

  1917.     /* rc == NGX_OK */

  1918.     u->state->header_time = ngx_current_msec - u->start_time;

  1919.     if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) {

  1920.         if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
  1921.             return;
  1922.         }

  1923.         if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
  1924.             return;
  1925.         }
  1926.     }

  1927.     if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
  1928.         return;
  1929.     }

  1930.     ngx_http_upstream_send_response(r, u);
  1931. }


  1932. static ngx_int_t
  1933. ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
  1934. {
  1935.     ngx_msec_t                 timeout;
  1936.     ngx_uint_t                 status, mask;
  1937.     ngx_http_upstream_next_t  *un;

  1938.     status = u->headers_in.status_n;

  1939.     for (un = ngx_http_upstream_next_errors; un->status; un++) {

  1940.         if (status != un->status) {
  1941.             continue;
  1942.         }

  1943.         timeout = u->conf->next_upstream_timeout;

  1944.         if (u->request_sent
  1945.             && (r->method & (NGX_HTTP_POST|NGX_HTTP_LOCK|NGX_HTTP_PATCH)))
  1946.         {
  1947.             mask = un->mask | NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT;

  1948.         } else {
  1949.             mask = un->mask;
  1950.         }

  1951.         if (u->peer.tries > 1
  1952.             && ((u->conf->next_upstream & mask) == mask)
  1953.             && !(u->request_sent && r->request_body_no_buffering)
  1954.             && !(timeout && ngx_current_msec - u->peer.start_time >= timeout))
  1955.         {
  1956.             ngx_http_upstream_next(r, u, un->mask);
  1957.             return NGX_OK;
  1958.         }

  1959. #if (NGX_HTTP_CACHE)

  1960.         if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
  1961.             && (u->conf->cache_use_stale & un->mask))
  1962.         {
  1963.             ngx_int_t  rc;

  1964.             rc = u->reinit_request(r);

  1965.             if (rc != NGX_OK) {
  1966.                 ngx_http_upstream_finalize_request(r, u, rc);
  1967.                 return NGX_OK;
  1968.             }

  1969.             u->cache_status = NGX_HTTP_CACHE_STALE;
  1970.             rc = ngx_http_upstream_cache_send(r, u);

  1971.             if (rc == NGX_DONE) {
  1972.                 return NGX_OK;
  1973.             }

  1974.             if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
  1975.                 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1976.             }

  1977.             ngx_http_upstream_finalize_request(r, u, rc);
  1978.             return NGX_OK;
  1979.         }

  1980. #endif

  1981.         break;
  1982.     }

  1983. #if (NGX_HTTP_CACHE)

  1984.     if (status == NGX_HTTP_NOT_MODIFIED
  1985.         && u->cache_status == NGX_HTTP_CACHE_EXPIRED
  1986.         && u->conf->cache_revalidate)
  1987.     {
  1988.         time_t     now, valid, updating, error;
  1989.         ngx_int_t  rc;

  1990.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1991.                        "http upstream not modified");

  1992.         now = ngx_time();

  1993.         valid = r->cache->valid_sec;
  1994.         updating = r->cache->updating_sec;
  1995.         error = r->cache->error_sec;

  1996.         rc = u->reinit_request(r);

  1997.         if (rc != NGX_OK) {
  1998.             ngx_http_upstream_finalize_request(r, u, rc);
  1999.             return NGX_OK;
  2000.         }

  2001.         u->cache_status = NGX_HTTP_CACHE_REVALIDATED;
  2002.         rc = ngx_http_upstream_cache_send(r, u);

  2003.         if (rc == NGX_DONE) {
  2004.             return NGX_OK;
  2005.         }

  2006.         if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
  2007.             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  2008.         }

  2009.         if (valid == 0) {
  2010.             valid = r->cache->valid_sec;
  2011.             updating = r->cache->updating_sec;
  2012.             error = r->cache->error_sec;
  2013.         }

  2014.         if (valid == 0) {
  2015.             valid = ngx_http_file_cache_valid(u->conf->cache_valid,
  2016.                                               u->headers_in.status_n);
  2017.             if (valid) {
  2018.                 valid = now + valid;
  2019.             }
  2020.         }

  2021.         if (valid) {
  2022.             r->cache->valid_sec = valid;
  2023.             r->cache->updating_sec = updating;
  2024.             r->cache->error_sec = error;

  2025.             r->cache->date = now;

  2026.             ngx_http_file_cache_update_header(r);
  2027.         }

  2028.         ngx_http_upstream_finalize_request(r, u, rc);
  2029.         return NGX_OK;
  2030.     }

  2031. #endif

  2032.     return NGX_DECLINED;
  2033. }


  2034. static ngx_int_t
  2035. ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
  2036.     ngx_http_upstream_t *u)
  2037. {
  2038.     ngx_int_t                  status;
  2039.     ngx_uint_t                 i;
  2040.     ngx_table_elt_t           *h, *ho, **ph;
  2041.     ngx_http_err_page_t       *err_page;
  2042.     ngx_http_core_loc_conf_t  *clcf;

  2043.     status = u->headers_in.status_n;

  2044.     if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) {
  2045.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
  2046.         return NGX_OK;
  2047.     }

  2048.     if (!u->conf->intercept_errors) {
  2049.         return NGX_DECLINED;
  2050.     }

  2051.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  2052.     if (clcf->error_pages == NULL) {
  2053.         return NGX_DECLINED;
  2054.     }

  2055.     err_page = clcf->error_pages->elts;
  2056.     for (i = 0; i < clcf->error_pages->nelts; i++) {

  2057.         if (err_page[i].status == status) {

  2058.             if (status == NGX_HTTP_UNAUTHORIZED
  2059.                 && u->headers_in.www_authenticate)
  2060.             {
  2061.                 h = u->headers_in.www_authenticate;
  2062.                 ph = &r->headers_out.www_authenticate;

  2063.                 while (h) {
  2064.                     ho = ngx_list_push(&r->headers_out.headers);

  2065.                     if (ho == NULL) {
  2066.                         ngx_http_upstream_finalize_request(r, u,
  2067.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  2068.                         return NGX_OK;
  2069.                     }

  2070.                     *ho = *h;
  2071.                     ho->next = NULL;

  2072.                     *ph = ho;
  2073.                     ph = &ho->next;

  2074.                     h = h->next;
  2075.                 }
  2076.             }

  2077. #if (NGX_HTTP_CACHE)

  2078.             if (r->cache) {

  2079.                 if (u->headers_in.no_cache || u->headers_in.expired) {
  2080.                     u->cacheable = 0;
  2081.                 }

  2082.                 if (u->cacheable) {
  2083.                     time_t  valid;

  2084.                     valid = r->cache->valid_sec;

  2085.                     if (valid == 0) {
  2086.                         valid = ngx_http_file_cache_valid(u->conf->cache_valid,
  2087.                                                           status);
  2088.                         if (valid) {
  2089.                             r->cache->valid_sec = ngx_time() + valid;
  2090.                         }
  2091.                     }

  2092.                     if (valid) {
  2093.                         r->cache->error = status;
  2094.                     }
  2095.                 }

  2096.                 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
  2097.             }
  2098. #endif
  2099.             ngx_http_upstream_finalize_request(r, u, status);

  2100.             return NGX_OK;
  2101.         }
  2102.     }

  2103.     return NGX_DECLINED;
  2104. }


  2105. static ngx_int_t
  2106. ngx_http_upstream_test_connect(ngx_connection_t *c)
  2107. {
  2108.     int        err;
  2109.     socklen_t  len;

  2110. #if (NGX_HAVE_KQUEUE)

  2111.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT)  {
  2112.         if (c->write->pending_eof || c->read->pending_eof) {
  2113.             if (c->write->pending_eof) {
  2114.                 err = c->write->kq_errno;

  2115.             } else {
  2116.                 err = c->read->kq_errno;
  2117.             }

  2118.             c->log->action = "connecting to upstream";
  2119.             (void) ngx_connection_error(c, err,
  2120.                                     "kevent() reported that connect() failed");
  2121.             return NGX_ERROR;
  2122.         }

  2123.     } else
  2124. #endif
  2125.     {
  2126.         err = 0;
  2127.         len = sizeof(int);

  2128.         /*
  2129.          * BSDs and Linux return 0 and set a pending error in err
  2130.          * Solaris returns -1 and sets errno
  2131.          */

  2132.         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
  2133.             == -1)
  2134.         {
  2135.             err = ngx_socket_errno;
  2136.         }

  2137.         if (err) {
  2138.             c->log->action = "connecting to upstream";
  2139.             (void) ngx_connection_error(c, err, "connect() failed");
  2140.             return NGX_ERROR;
  2141.         }
  2142.     }

  2143.     return NGX_OK;
  2144. }


  2145. static ngx_int_t
  2146. ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
  2147. {
  2148.     ngx_str_t                       uri, args;
  2149.     ngx_uint_t                      i, flags;
  2150.     ngx_list_part_t                *part;
  2151.     ngx_table_elt_t                *h;
  2152.     ngx_http_upstream_header_t     *hh;
  2153.     ngx_http_upstream_main_conf_t  *umcf;

  2154.     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  2155.     if (u->headers_in.no_cache || u->headers_in.expired) {
  2156.         u->cacheable = 0;
  2157.     }

  2158.     if (u->headers_in.x_accel_redirect
  2159.         && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
  2160.     {
  2161.         ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);

  2162.         part = &u->headers_in.headers.part;
  2163.         h = part->elts;

  2164.         for (i = 0; /* void */; i++) {

  2165.             if (i >= part->nelts) {
  2166.                 if (part->next == NULL) {
  2167.                     break;
  2168.                 }

  2169.                 part = part->next;
  2170.                 h = part->elts;
  2171.                 i = 0;
  2172.             }

  2173.             if (h[i].hash == 0) {
  2174.                 continue;
  2175.             }

  2176.             hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
  2177.                                h[i].lowcase_key, h[i].key.len);

  2178.             if (hh && hh->redirect) {
  2179.                 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
  2180.                     ngx_http_finalize_request(r,
  2181.                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
  2182.                     return NGX_DONE;
  2183.                 }
  2184.             }
  2185.         }

  2186.         uri = u->headers_in.x_accel_redirect->value;

  2187.         if (uri.data[0] == '@') {
  2188.             ngx_http_named_location(r, &uri);

  2189.         } else {
  2190.             ngx_str_null(&args);
  2191.             flags = NGX_HTTP_LOG_UNSAFE;

  2192.             if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
  2193.                 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
  2194.                 return NGX_DONE;
  2195.             }

  2196.             if (r->method != NGX_HTTP_HEAD) {
  2197.                 r->method = NGX_HTTP_GET;
  2198.                 r->method_name = ngx_http_core_get_method;
  2199.             }

  2200.             ngx_http_internal_redirect(r, &uri, &args);
  2201.         }

  2202.         ngx_http_finalize_request(r, NGX_DONE);
  2203.         return NGX_DONE;
  2204.     }

  2205.     part = &u->headers_in.headers.part;
  2206.     h = part->elts;

  2207.     for (i = 0; /* void */; i++) {

  2208.         if (i >= part->nelts) {
  2209.             if (part->next == NULL) {
  2210.                 break;
  2211.             }

  2212.             part = part->next;
  2213.             h = part->elts;
  2214.             i = 0;
  2215.         }

  2216.         if (h[i].hash == 0) {
  2217.             continue;
  2218.         }

  2219.         if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
  2220.                           h[i].lowcase_key, h[i].key.len))
  2221.         {
  2222.             continue;
  2223.         }

  2224.         hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
  2225.                            h[i].lowcase_key, h[i].key.len);

  2226.         if (hh) {
  2227.             if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
  2228.                 ngx_http_upstream_finalize_request(r, u,
  2229.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  2230.                 return NGX_DONE;
  2231.             }

  2232.             continue;
  2233.         }

  2234.         if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
  2235.             ngx_http_upstream_finalize_request(r, u,
  2236.                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
  2237.             return NGX_DONE;
  2238.         }
  2239.     }

  2240.     if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
  2241.         r->headers_out.server->hash = 0;
  2242.     }

  2243.     if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
  2244.         r->headers_out.date->hash = 0;
  2245.     }

  2246.     r->headers_out.status = u->headers_in.status_n;
  2247.     r->headers_out.status_line = u->headers_in.status_line;

  2248.     r->headers_out.content_length_n = u->headers_in.content_length_n;

  2249.     r->disable_not_modified = !u->cacheable;

  2250.     if (u->conf->force_ranges) {
  2251.         r->allow_ranges = 1;
  2252.         r->single_range = 1;

  2253. #if (NGX_HTTP_CACHE)
  2254.         if (r->cached) {
  2255.             r->single_range = 0;
  2256.         }
  2257. #endif
  2258.     }

  2259.     u->length = -1;

  2260.     return NGX_OK;
  2261. }


  2262. static ngx_int_t
  2263. ngx_http_upstream_process_trailers(ngx_http_request_t *r,
  2264.     ngx_http_upstream_t *u)
  2265. {
  2266.     ngx_uint_t        i;
  2267.     ngx_list_part_t  *part;
  2268.     ngx_table_elt_t  *h, *ho;

  2269.     if (!u->conf->pass_trailers) {
  2270.         return NGX_OK;
  2271.     }

  2272.     part = &u->headers_in.trailers.part;
  2273.     h = part->elts;

  2274.     for (i = 0; /* void */; i++) {

  2275.         if (i >= part->nelts) {
  2276.             if (part->next == NULL) {
  2277.                 break;
  2278.             }

  2279.             part = part->next;
  2280.             h = part->elts;
  2281.             i = 0;
  2282.         }

  2283.         if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
  2284.                           h[i].lowcase_key, h[i].key.len))
  2285.         {
  2286.             continue;
  2287.         }

  2288.         ho = ngx_list_push(&r->headers_out.trailers);
  2289.         if (ho == NULL) {
  2290.             return NGX_ERROR;
  2291.         }

  2292.         *ho = h[i];
  2293.     }

  2294.     return NGX_OK;
  2295. }


  2296. static void
  2297. ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
  2298. {
  2299.     ssize_t                    n;
  2300.     ngx_int_t                  rc;
  2301.     ngx_event_pipe_t          *p;
  2302.     ngx_connection_t          *c;
  2303.     ngx_http_core_loc_conf_t  *clcf;

  2304.     rc = ngx_http_send_header(r);

  2305.     if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
  2306.         ngx_http_upstream_finalize_request(r, u, rc);
  2307.         return;
  2308.     }

  2309.     u->header_sent = 1;

  2310.     if (u->upgrade) {

  2311. #if (NGX_HTTP_CACHE)

  2312.         if (r->cache) {
  2313.             ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
  2314.         }

  2315. #endif

  2316.         ngx_http_upstream_upgrade(r, u);
  2317.         return;
  2318.     }

  2319.     c = r->connection;

  2320.     if (r->header_only) {

  2321.         if (!u->buffering) {
  2322.             ngx_http_upstream_finalize_request(r, u, rc);
  2323.             return;
  2324.         }

  2325.         if (!u->cacheable && !u->store) {
  2326.             ngx_http_upstream_finalize_request(r, u, rc);
  2327.             return;
  2328.         }

  2329.         u->pipe->downstream_error = 1;
  2330.     }

  2331.     if (r->request_body && r->request_body->temp_file
  2332.         && r == r->main && !r->preserve_body
  2333.         && !u->conf->preserve_output)
  2334.     {
  2335.         ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
  2336.         r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
  2337.     }

  2338.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  2339.     if (!u->buffering) {

  2340. #if (NGX_HTTP_CACHE)

  2341.         if (r->cache) {
  2342.             ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
  2343.         }

  2344. #endif

  2345.         if (u->input_filter == NULL) {
  2346.             u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
  2347.             u->input_filter = ngx_http_upstream_non_buffered_filter;
  2348.             u->input_filter_ctx = r;
  2349.         }

  2350.         u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
  2351.         r->write_event_handler =
  2352.                              ngx_http_upstream_process_non_buffered_downstream;

  2353.         r->limit_rate = 0;
  2354.         r->limit_rate_set = 1;

  2355.         if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
  2356.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2357.             return;
  2358.         }

  2359.         if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
  2360.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2361.             return;
  2362.         }

  2363.         n = u->buffer.last - u->buffer.pos;

  2364.         if (n) {
  2365.             u->buffer.last = u->buffer.pos;

  2366.             u->state->response_length += n;

  2367.             if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
  2368.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2369.                 return;
  2370.             }

  2371.             ngx_http_upstream_process_non_buffered_downstream(r);

  2372.         } else {
  2373.             u->buffer.pos = u->buffer.start;
  2374.             u->buffer.last = u->buffer.start;

  2375.             if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
  2376.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2377.                 return;
  2378.             }

  2379.             ngx_http_upstream_process_non_buffered_upstream(r, u);
  2380.         }

  2381.         return;
  2382.     }

  2383.     /* TODO: preallocate event_pipe bufs, look "Content-Length" */

  2384. #if (NGX_HTTP_CACHE)

  2385.     if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
  2386.         ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
  2387.         r->cache->file.fd = NGX_INVALID_FILE;
  2388.     }

  2389.     switch (ngx_http_test_predicates(r, u->conf->no_cache)) {

  2390.     case NGX_ERROR:
  2391.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2392.         return;

  2393.     case NGX_DECLINED:
  2394.         u->cacheable = 0;
  2395.         break;

  2396.     default: /* NGX_OK */

  2397.         if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {

  2398.             /* create cache if previously bypassed */

  2399.             if (ngx_http_file_cache_create(r) != NGX_OK) {
  2400.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2401.                 return;
  2402.             }
  2403.         }

  2404.         break;
  2405.     }

  2406.     if (u->cacheable) {
  2407.         time_t  now, valid;

  2408.         now = ngx_time();

  2409.         valid = r->cache->valid_sec;

  2410.         if (valid == 0) {
  2411.             valid = ngx_http_file_cache_valid(u->conf->cache_valid,
  2412.                                               u->headers_in.status_n);
  2413.             if (valid) {
  2414.                 r->cache->valid_sec = now + valid;
  2415.             }
  2416.         }

  2417.         if (valid) {
  2418.             r->cache->date = now;
  2419.             r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);

  2420.             if (u->headers_in.status_n == NGX_HTTP_OK
  2421.                 || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT)
  2422.             {
  2423.                 r->cache->last_modified = u->headers_in.last_modified_time;

  2424.                 if (u->headers_in.etag) {
  2425.                     r->cache->etag = u->headers_in.etag->value;

  2426.                 } else {
  2427.                     ngx_str_null(&r->cache->etag);
  2428.                 }

  2429.             } else {
  2430.                 r->cache->last_modified = -1;
  2431.                 ngx_str_null(&r->cache->etag);
  2432.             }

  2433.             if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK) {
  2434.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2435.                 return;
  2436.             }

  2437.         } else {
  2438.             u->cacheable = 0;
  2439.         }
  2440.     }

  2441.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  2442.                    "http cacheable: %d", u->cacheable);

  2443.     if (u->cacheable == 0 && r->cache) {
  2444.         ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
  2445.     }

  2446.     if (r->header_only && !u->cacheable && !u->store) {
  2447.         ngx_http_upstream_finalize_request(r, u, 0);
  2448.         return;
  2449.     }

  2450. #endif

  2451.     p = u->pipe;

  2452.     p->output_filter = ngx_http_upstream_output_filter;
  2453.     p->output_ctx = r;
  2454.     p->tag = u->output.tag;
  2455.     p->bufs = u->conf->bufs;
  2456.     p->busy_size = u->conf->busy_buffers_size;
  2457.     p->upstream = u->peer.connection;
  2458.     p->downstream = c;
  2459.     p->pool = r->pool;
  2460.     p->log = c->log;
  2461.     p->limit_rate = ngx_http_complex_value_size(r, u->conf->limit_rate, 0);
  2462.     p->start_sec = ngx_time();

  2463.     p->cacheable = u->cacheable || u->store;

  2464.     p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
  2465.     if (p->temp_file == NULL) {
  2466.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2467.         return;
  2468.     }

  2469.     p->temp_file->file.fd = NGX_INVALID_FILE;
  2470.     p->temp_file->file.log = c->log;
  2471.     p->temp_file->path = u->conf->temp_path;
  2472.     p->temp_file->pool = r->pool;

  2473.     if (p->cacheable) {
  2474.         p->temp_file->persistent = 1;

  2475. #if (NGX_HTTP_CACHE)
  2476.         if (r->cache && !r->cache->file_cache->use_temp_path) {
  2477.             p->temp_file->path = r->cache->file_cache->path;
  2478.             p->temp_file->file.name = r->cache->file.name;
  2479.         }
  2480. #endif

  2481.     } else {
  2482.         p->temp_file->log_level = NGX_LOG_WARN;
  2483.         p->temp_file->warn = "an upstream response is buffered "
  2484.                              "to a temporary file";
  2485.     }

  2486.     p->max_temp_file_size = u->conf->max_temp_file_size;
  2487.     p->temp_file_write_size = u->conf->temp_file_write_size;

  2488. #if (NGX_THREADS)
  2489.     if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_write) {
  2490.         p->thread_handler = ngx_http_upstream_thread_handler;
  2491.         p->thread_ctx = r;
  2492.     }
  2493. #endif

  2494.     p->preread_bufs = ngx_alloc_chain_link(r->pool);
  2495.     if (p->preread_bufs == NULL) {
  2496.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2497.         return;
  2498.     }

  2499.     p->preread_bufs->buf = &u->buffer;
  2500.     p->preread_bufs->next = NULL;
  2501.     u->buffer.recycled = 1;

  2502.     p->preread_size = u->buffer.last - u->buffer.pos;

  2503.     if (u->cacheable) {

  2504.         p->buf_to_file = ngx_calloc_buf(r->pool);
  2505.         if (p->buf_to_file == NULL) {
  2506.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2507.             return;
  2508.         }

  2509.         p->buf_to_file->start = u->buffer.start;
  2510.         p->buf_to_file->pos = u->buffer.start;
  2511.         p->buf_to_file->last = u->buffer.pos;
  2512.         p->buf_to_file->temporary = 1;
  2513.     }

  2514.     if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
  2515.         /* the posted aio operation may corrupt a shadow buffer */
  2516.         p->single_buf = 1;
  2517.     }

  2518.     /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
  2519.     p->free_bufs = 1;

  2520.     /*
  2521.      * event_pipe would do u->buffer.last += p->preread_size
  2522.      * as though these bytes were read
  2523.      */
  2524.     u->buffer.last = u->buffer.pos;

  2525.     if (u->conf->cyclic_temp_file) {

  2526.         /*
  2527.          * we need to disable the use of sendfile() if we use cyclic temp file
  2528.          * because the writing a new data may interfere with sendfile()
  2529.          * that uses the same kernel file pages (at least on FreeBSD)
  2530.          */

  2531.         p->cyclic_temp_file = 1;
  2532.         c->sendfile = 0;

  2533.     } else {
  2534.         p->cyclic_temp_file = 0;
  2535.     }

  2536.     p->read_timeout = u->conf->read_timeout;
  2537.     p->send_timeout = clcf->send_timeout;
  2538.     p->send_lowat = clcf->send_lowat;

  2539.     p->length = -1;

  2540.     if (u->input_filter_init
  2541.         && u->input_filter_init(p->input_ctx) != NGX_OK)
  2542.     {
  2543.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2544.         return;
  2545.     }

  2546.     u->read_event_handler = ngx_http_upstream_process_upstream;
  2547.     r->write_event_handler = ngx_http_upstream_process_downstream;

  2548.     ngx_http_upstream_process_upstream(r, u);
  2549. }


  2550. static void
  2551. ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
  2552. {
  2553.     ngx_connection_t          *c;
  2554.     ngx_http_core_loc_conf_t  *clcf;

  2555.     c = r->connection;
  2556.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  2557.     /* TODO: prevent upgrade if not requested or not possible */

  2558.     if (r != r->main) {
  2559.         ngx_log_error(NGX_LOG_ERR, c->log, 0,
  2560.                       "connection upgrade in subrequest");
  2561.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2562.         return;
  2563.     }

  2564.     r->keepalive = 0;
  2565.     c->log->action = "proxying upgraded connection";

  2566.     u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
  2567.     u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
  2568.     r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
  2569.     r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;

  2570.     if (clcf->tcp_nodelay) {

  2571.         if (ngx_tcp_nodelay(c) != NGX_OK) {
  2572.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2573.             return;
  2574.         }

  2575.         if (ngx_tcp_nodelay(u->peer.connection) != NGX_OK) {
  2576.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2577.             return;
  2578.         }
  2579.     }

  2580.     if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
  2581.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2582.         return;
  2583.     }

  2584.     if (u->peer.connection->read->ready
  2585.         || u->buffer.pos != u->buffer.last)
  2586.     {
  2587.         ngx_post_event(c->read, &ngx_posted_events);
  2588.         ngx_http_upstream_process_upgraded(r, 1, 1);
  2589.         return;
  2590.     }

  2591.     ngx_http_upstream_process_upgraded(r, 0, 1);
  2592. }


  2593. static void
  2594. ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
  2595. {
  2596.     ngx_http_upstream_process_upgraded(r, 0, 0);
  2597. }


  2598. static void
  2599. ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
  2600. {
  2601.     ngx_http_upstream_process_upgraded(r, 1, 1);
  2602. }


  2603. static void
  2604. ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
  2605.     ngx_http_upstream_t *u)
  2606. {
  2607.     ngx_http_upstream_process_upgraded(r, 1, 0);
  2608. }


  2609. static void
  2610. ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
  2611.     ngx_http_upstream_t *u)
  2612. {
  2613.     ngx_http_upstream_process_upgraded(r, 0, 1);
  2614. }


  2615. static void
  2616. ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
  2617.     ngx_uint_t from_upstream, ngx_uint_t do_write)
  2618. {
  2619.     size_t                     size;
  2620.     ssize_t                    n;
  2621.     ngx_buf_t                 *b;
  2622.     ngx_uint_t                 flags;
  2623.     ngx_connection_t          *c, *downstream, *upstream, *dst, *src;
  2624.     ngx_http_upstream_t       *u;
  2625.     ngx_http_core_loc_conf_t  *clcf;

  2626.     c = r->connection;
  2627.     u = r->upstream;

  2628.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  2629.                    "http upstream process upgraded, fu:%ui", from_upstream);

  2630.     downstream = c;
  2631.     upstream = u->peer.connection;

  2632.     if (downstream->write->timedout) {
  2633.         c->timedout = 1;
  2634.         ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
  2635.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
  2636.         return;
  2637.     }

  2638.     if (upstream->read->timedout || upstream->write->timedout) {
  2639.         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
  2640.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
  2641.         return;
  2642.     }

  2643.     if (from_upstream) {
  2644.         src = upstream;
  2645.         dst = downstream;
  2646.         b = &u->buffer;

  2647.     } else {
  2648.         src = downstream;
  2649.         dst = upstream;
  2650.         b = &u->from_client;

  2651.         if (r->header_in->last > r->header_in->pos) {
  2652.             b = r->header_in;
  2653.             b->end = b->last;
  2654.             do_write = 1;
  2655.         }

  2656.         if (b->start == NULL) {
  2657.             b->start = ngx_palloc(r->pool, u->conf->buffer_size);
  2658.             if (b->start == NULL) {
  2659.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2660.                 return;
  2661.             }

  2662.             b->pos = b->start;
  2663.             b->last = b->start;
  2664.             b->end = b->start + u->conf->buffer_size;
  2665.             b->temporary = 1;
  2666.             b->tag = u->output.tag;
  2667.         }
  2668.     }

  2669.     for ( ;; ) {

  2670.         if (do_write) {

  2671.             size = b->last - b->pos;

  2672.             if (size && dst->write->ready) {

  2673.                 n = dst->send(dst, b->pos, size);

  2674.                 if (n == NGX_ERROR) {
  2675.                     ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2676.                     return;
  2677.                 }

  2678.                 if (n > 0) {
  2679.                     b->pos += n;

  2680.                     if (b->pos == b->last) {
  2681.                         b->pos = b->start;
  2682.                         b->last = b->start;
  2683.                     }
  2684.                 }
  2685.             }
  2686.         }

  2687.         size = b->end - b->last;

  2688.         if (size && src->read->ready) {

  2689.             n = src->recv(src, b->last, size);

  2690.             if (n == NGX_AGAIN || n == 0) {
  2691.                 break;
  2692.             }

  2693.             if (n > 0) {
  2694.                 do_write = 1;
  2695.                 b->last += n;

  2696.                 if (from_upstream) {
  2697.                     u->state->bytes_received += n;
  2698.                 }

  2699.                 continue;
  2700.             }

  2701.             if (n == NGX_ERROR) {
  2702.                 src->read->eof = 1;
  2703.             }
  2704.         }

  2705.         break;
  2706.     }

  2707.     if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
  2708.         || (downstream->read->eof && u->from_client.pos == u->from_client.last)
  2709.         || (downstream->read->eof && upstream->read->eof))
  2710.     {
  2711.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  2712.                        "http upstream upgraded done");
  2713.         ngx_http_upstream_finalize_request(r, u, 0);
  2714.         return;
  2715.     }

  2716.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  2717.     if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
  2718.         != NGX_OK)
  2719.     {
  2720.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2721.         return;
  2722.     }

  2723.     if (upstream->write->active && !upstream->write->ready) {
  2724.         ngx_add_timer(upstream->write, u->conf->send_timeout);

  2725.     } else if (upstream->write->timer_set) {
  2726.         ngx_del_timer(upstream->write);
  2727.     }

  2728.     if (upstream->read->eof || upstream->read->error) {
  2729.         flags = NGX_CLOSE_EVENT;

  2730.     } else {
  2731.         flags = 0;
  2732.     }

  2733.     if (ngx_handle_read_event(upstream->read, flags) != NGX_OK) {
  2734.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2735.         return;
  2736.     }

  2737.     if (upstream->read->active && !upstream->read->ready) {
  2738.         ngx_add_timer(upstream->read, u->conf->read_timeout);

  2739.     } else if (upstream->read->timer_set) {
  2740.         ngx_del_timer(upstream->read);
  2741.     }

  2742.     if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
  2743.         != NGX_OK)
  2744.     {
  2745.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2746.         return;
  2747.     }

  2748.     if (downstream->read->eof || downstream->read->error) {
  2749.         flags = NGX_CLOSE_EVENT;

  2750.     } else {
  2751.         flags = 0;
  2752.     }

  2753.     if (ngx_handle_read_event(downstream->read, flags) != NGX_OK) {
  2754.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2755.         return;
  2756.     }

  2757.     if (downstream->write->active && !downstream->write->ready) {
  2758.         ngx_add_timer(downstream->write, clcf->send_timeout);

  2759.     } else if (downstream->write->timer_set) {
  2760.         ngx_del_timer(downstream->write);
  2761.     }
  2762. }


  2763. static void
  2764. ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
  2765. {
  2766.     ngx_event_t          *wev;
  2767.     ngx_connection_t     *c;
  2768.     ngx_http_upstream_t  *u;

  2769.     c = r->connection;
  2770.     u = r->upstream;
  2771.     wev = c->write;

  2772.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  2773.                    "http upstream process non buffered downstream");

  2774.     c->log->action = "sending to client";

  2775.     if (wev->timedout) {
  2776.         c->timedout = 1;
  2777.         ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
  2778.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
  2779.         return;
  2780.     }

  2781.     ngx_http_upstream_process_non_buffered_request(r, 1);
  2782. }


  2783. static void
  2784. ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
  2785.     ngx_http_upstream_t *u)
  2786. {
  2787.     ngx_connection_t  *c;

  2788.     c = u->peer.connection;

  2789.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  2790.                    "http upstream process non buffered upstream");

  2791.     c->log->action = "reading upstream";

  2792.     if (c->read->timedout) {
  2793.         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
  2794.         ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
  2795.         return;
  2796.     }

  2797.     ngx_http_upstream_process_non_buffered_request(r, 0);
  2798. }


  2799. static void
  2800. ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
  2801.     ngx_uint_t do_write)
  2802. {
  2803.     size_t                     size;
  2804.     ssize_t                    n;
  2805.     ngx_buf_t                 *b;
  2806.     ngx_int_t                  rc;
  2807.     ngx_uint_t                 flags;
  2808.     ngx_connection_t          *downstream, *upstream;
  2809.     ngx_http_upstream_t       *u;
  2810.     ngx_http_core_loc_conf_t  *clcf;

  2811.     u = r->upstream;
  2812.     downstream = r->connection;
  2813.     upstream = u->peer.connection;

  2814.     b = &u->buffer;

  2815.     do_write = do_write || u->length == 0;

  2816.     for ( ;; ) {

  2817.         if (do_write) {

  2818.             if (u->out_bufs || u->busy_bufs || downstream->buffered) {
  2819.                 rc = ngx_http_output_filter(r, u->out_bufs);

  2820.                 if (rc == NGX_ERROR) {
  2821.                     ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2822.                     return;
  2823.                 }

  2824.                 ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
  2825.                                         &u->out_bufs, u->output.tag);
  2826.             }

  2827.             if (u->busy_bufs == NULL) {

  2828.                 if (u->length == 0
  2829.                     || (upstream->read->eof && u->length == -1))
  2830.                 {
  2831.                     ngx_http_upstream_finalize_request(r, u, 0);
  2832.                     return;
  2833.                 }

  2834.                 if (upstream->read->eof) {
  2835.                     ngx_log_error(NGX_LOG_ERR, upstream->log, 0,
  2836.                                   "upstream prematurely closed connection");

  2837.                     ngx_http_upstream_finalize_request(r, u,
  2838.                                                        NGX_HTTP_BAD_GATEWAY);
  2839.                     return;
  2840.                 }

  2841.                 if (upstream->read->error || u->error) {
  2842.                     ngx_http_upstream_finalize_request(r, u,
  2843.                                                        NGX_HTTP_BAD_GATEWAY);
  2844.                     return;
  2845.                 }

  2846.                 b->pos = b->start;
  2847.                 b->last = b->start;
  2848.             }
  2849.         }

  2850.         size = b->end - b->last;

  2851.         if (size && upstream->read->ready) {

  2852.             n = upstream->recv(upstream, b->last, size);

  2853.             if (n == NGX_AGAIN) {
  2854.                 break;
  2855.             }

  2856.             if (n > 0) {
  2857.                 u->state->bytes_received += n;
  2858.                 u->state->response_length += n;

  2859.                 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
  2860.                     ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2861.                     return;
  2862.                 }
  2863.             }

  2864.             do_write = 1;

  2865.             continue;
  2866.         }

  2867.         break;
  2868.     }

  2869.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  2870.     if (downstream->data == r) {
  2871.         if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
  2872.             != NGX_OK)
  2873.         {
  2874.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2875.             return;
  2876.         }
  2877.     }

  2878.     if (downstream->write->active && !downstream->write->ready) {
  2879.         ngx_add_timer(downstream->write, clcf->send_timeout);

  2880.     } else if (downstream->write->timer_set) {
  2881.         ngx_del_timer(downstream->write);
  2882.     }

  2883.     if (upstream->read->eof || upstream->read->error) {
  2884.         flags = NGX_CLOSE_EVENT;

  2885.     } else {
  2886.         flags = 0;
  2887.     }

  2888.     if (ngx_handle_read_event(upstream->read, flags) != NGX_OK) {
  2889.         ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  2890.         return;
  2891.     }

  2892.     if (upstream->read->active && !upstream->read->ready) {
  2893.         ngx_add_timer(upstream->read, u->conf->read_timeout);

  2894.     } else if (upstream->read->timer_set) {
  2895.         ngx_del_timer(upstream->read);
  2896.     }
  2897. }


  2898. ngx_int_t
  2899. ngx_http_upstream_non_buffered_filter_init(void *data)
  2900. {
  2901.     return NGX_OK;
  2902. }


  2903. ngx_int_t
  2904. ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
  2905. {
  2906.     ngx_http_request_t  *r = data;

  2907.     ngx_buf_t            *b;
  2908.     ngx_chain_t          *cl, **ll;
  2909.     ngx_http_upstream_t  *u;

  2910.     u = r->upstream;

  2911.     if (u->length == 0) {
  2912.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  2913.                       "upstream sent more data than specified in "
  2914.                       "\"Content-Length\" header");
  2915.         return NGX_OK;
  2916.     }

  2917.     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
  2918.         ll = &cl->next;
  2919.     }

  2920.     cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
  2921.     if (cl == NULL) {
  2922.         return NGX_ERROR;
  2923.     }

  2924.     *ll = cl;

  2925.     cl->buf->flush = 1;
  2926.     cl->buf->memory = 1;

  2927.     b = &u->buffer;

  2928.     cl->buf->pos = b->last;
  2929.     b->last += bytes;
  2930.     cl->buf->last = b->last;
  2931.     cl->buf->tag = u->output.tag;

  2932.     if (u->length == -1) {
  2933.         return NGX_OK;
  2934.     }

  2935.     if (bytes > u->length) {

  2936.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  2937.                       "upstream sent more data than specified in "
  2938.                       "\"Content-Length\" header");

  2939.         cl->buf->last = cl->buf->pos + u->length;
  2940.         u->length = 0;

  2941.         return NGX_OK;
  2942.     }

  2943.     u->length -= bytes;

  2944.     return NGX_OK;
  2945. }


  2946. #if (NGX_THREADS)

  2947. static ngx_int_t
  2948. ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
  2949. {
  2950.     ngx_str_t                  name;
  2951.     ngx_event_pipe_t          *p;
  2952.     ngx_connection_t          *c;
  2953.     ngx_thread_pool_t         *tp;
  2954.     ngx_http_request_t        *r;
  2955.     ngx_http_core_loc_conf_t  *clcf;

  2956.     r = file->thread_ctx;
  2957.     p = r->upstream->pipe;

  2958.     if (r->aio) {
  2959.         /*
  2960.          * tolerate sendfile() calls if another operation is already
  2961.          * running; this can happen due to subrequests, multiple calls
  2962.          * of the next body filter from a filter, or in HTTP/2 due to
  2963.          * a write event on the main connection
  2964.          */

  2965.         c = r->connection;

  2966. #if (NGX_HTTP_V2)
  2967.         if (r->stream) {
  2968.             c = r->stream->connection->connection;
  2969.         }
  2970. #endif

  2971.         if (task == c->sendfile_task) {
  2972.             return NGX_OK;
  2973.         }
  2974.     }

  2975.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  2976.     tp = clcf->thread_pool;

  2977.     if (tp == NULL) {
  2978.         if (ngx_http_complex_value(r, clcf->thread_pool_value, &name)
  2979.             != NGX_OK)
  2980.         {
  2981.             return NGX_ERROR;
  2982.         }

  2983.         tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);

  2984.         if (tp == NULL) {
  2985.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2986.                           "thread pool \"%V\" not found", &name);
  2987.             return NGX_ERROR;
  2988.         }
  2989.     }

  2990.     task->event.data = r;
  2991.     task->event.handler = ngx_http_upstream_thread_event_handler;

  2992.     if (ngx_thread_task_post(tp, task) != NGX_OK) {
  2993.         return NGX_ERROR;
  2994.     }

  2995.     r->main->blocked++;
  2996.     r->aio = 1;
  2997.     p->aio = 1;

  2998.     ngx_add_timer(&task->event, 60000);

  2999.     return NGX_OK;
  3000. }


  3001. static void
  3002. ngx_http_upstream_thread_event_handler(ngx_event_t *ev)
  3003. {
  3004.     ngx_connection_t    *c;
  3005.     ngx_http_request_t  *r;

  3006.     r = ev->data;
  3007.     c = r->connection;

  3008.     ngx_http_set_log_request(c->log, r);

  3009.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3010.                    "http upstream thread: \"%V?%V\"", &r->uri, &r->args);

  3011.     if (ev->timedout) {
  3012.         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
  3013.                       "thread operation took too long");
  3014.         ev->timedout = 0;
  3015.         return;
  3016.     }

  3017.     if (ev->timer_set) {
  3018.         ngx_del_timer(ev);
  3019.     }

  3020.     r->main->blocked--;
  3021.     r->aio = 0;

  3022. #if (NGX_HTTP_V2)

  3023.     if (r->stream) {
  3024.         /*
  3025.          * for HTTP/2, update write event to make sure processing will
  3026.          * reach the main connection to handle sendfile() in threads
  3027.          */

  3028.         c->write->ready = 1;
  3029.         c->write->active = 0;
  3030.     }

  3031. #endif

  3032.     if (r->done || r->main->terminated) {
  3033.         /*
  3034.          * trigger connection event handler if the subrequest was
  3035.          * already finalized (this can happen if the handler is used
  3036.          * for sendfile() in threads), or if the request was terminated
  3037.          */

  3038.         c->write->handler(c->write);

  3039.     } else {
  3040.         r->write_event_handler(r);
  3041.         ngx_http_run_posted_requests(c);
  3042.     }
  3043. }

  3044. #endif


  3045. static ngx_int_t
  3046. ngx_http_upstream_output_filter(void *data, ngx_chain_t *chain)
  3047. {
  3048.     ngx_int_t            rc;
  3049.     ngx_event_pipe_t    *p;
  3050.     ngx_http_request_t  *r;

  3051.     r = data;
  3052.     p = r->upstream->pipe;

  3053.     rc = ngx_http_output_filter(r, chain);

  3054.     p->aio = r->aio;

  3055.     return rc;
  3056. }


  3057. static void
  3058. ngx_http_upstream_process_downstream(ngx_http_request_t *r)
  3059. {
  3060.     ngx_event_t          *wev;
  3061.     ngx_connection_t     *c;
  3062.     ngx_event_pipe_t     *p;
  3063.     ngx_http_upstream_t  *u;

  3064.     c = r->connection;
  3065.     u = r->upstream;
  3066.     p = u->pipe;
  3067.     wev = c->write;

  3068.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3069.                    "http upstream process downstream");

  3070.     c->log->action = "sending to client";

  3071. #if (NGX_THREADS)
  3072.     p->aio = r->aio;
  3073. #endif

  3074.     if (wev->timedout) {

  3075.         p->downstream_error = 1;
  3076.         c->timedout = 1;
  3077.         ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");

  3078.     } else {

  3079.         if (wev->delayed) {

  3080.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3081.                            "http downstream delayed");

  3082.             if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
  3083.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3084.             }

  3085.             return;
  3086.         }

  3087.         if (ngx_event_pipe(p, 1) == NGX_ABORT) {
  3088.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3089.             return;
  3090.         }
  3091.     }

  3092.     ngx_http_upstream_process_request(r, u);
  3093. }


  3094. static void
  3095. ngx_http_upstream_process_upstream(ngx_http_request_t *r,
  3096.     ngx_http_upstream_t *u)
  3097. {
  3098.     ngx_event_t       *rev;
  3099.     ngx_event_pipe_t  *p;
  3100.     ngx_connection_t  *c;

  3101.     c = u->peer.connection;
  3102.     p = u->pipe;
  3103.     rev = c->read;

  3104.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3105.                    "http upstream process upstream");

  3106.     c->log->action = "reading upstream";

  3107.     if (rev->timedout) {

  3108.         p->upstream_error = 1;
  3109.         ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");

  3110.     } else {

  3111.         if (rev->delayed) {

  3112.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3113.                            "http upstream delayed");

  3114.             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  3115.                 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3116.             }

  3117.             return;
  3118.         }

  3119.         if (ngx_event_pipe(p, 0) == NGX_ABORT) {
  3120.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3121.             return;
  3122.         }
  3123.     }

  3124.     ngx_http_upstream_process_request(r, u);
  3125. }


  3126. static void
  3127. ngx_http_upstream_process_request(ngx_http_request_t *r,
  3128.     ngx_http_upstream_t *u)
  3129. {
  3130.     ngx_temp_file_t   *tf;
  3131.     ngx_event_pipe_t  *p;

  3132.     p = u->pipe;

  3133. #if (NGX_THREADS)

  3134.     if (p->writing && !p->aio) {

  3135.         /*
  3136.          * make sure to call ngx_event_pipe()
  3137.          * if there is an incomplete aio write
  3138.          */

  3139.         if (ngx_event_pipe(p, 1) == NGX_ABORT) {
  3140.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3141.             return;
  3142.         }
  3143.     }

  3144.     if (p->writing) {
  3145.         return;
  3146.     }

  3147. #endif

  3148.     if (u->peer.connection) {

  3149.         if (u->store) {

  3150.             if (p->upstream_eof || p->upstream_done) {

  3151.                 tf = p->temp_file;

  3152.                 if (u->headers_in.status_n == NGX_HTTP_OK
  3153.                     && (p->upstream_done || p->length == -1)
  3154.                     && (u->headers_in.content_length_n == -1
  3155.                         || u->headers_in.content_length_n == tf->offset))
  3156.                 {
  3157.                     ngx_http_upstream_store(r, u);
  3158.                 }
  3159.             }
  3160.         }

  3161. #if (NGX_HTTP_CACHE)

  3162.         if (u->cacheable) {

  3163.             if (p->upstream_done) {
  3164.                 ngx_http_file_cache_update(r, p->temp_file);

  3165.             } else if (p->upstream_eof) {

  3166.                 tf = p->temp_file;

  3167.                 if (p->length == -1
  3168.                     && (u->headers_in.content_length_n == -1
  3169.                         || u->headers_in.content_length_n
  3170.                            == tf->offset - (off_t) r->cache->body_start))
  3171.                 {
  3172.                     ngx_http_file_cache_update(r, tf);

  3173.                 } else {
  3174.                     ngx_http_file_cache_free(r->cache, tf);
  3175.                 }

  3176.             } else if (p->upstream_error) {
  3177.                 ngx_http_file_cache_free(r->cache, p->temp_file);
  3178.             }
  3179.         }

  3180. #endif

  3181.         if (p->upstream_done || p->upstream_eof || p->upstream_error) {
  3182.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3183.                            "http upstream exit: %p", p->out);

  3184.             if (p->upstream_done
  3185.                 || (p->upstream_eof && p->length == -1))
  3186.             {
  3187.                 ngx_http_upstream_finalize_request(r, u, 0);
  3188.                 return;
  3189.             }

  3190.             if (p->upstream_eof) {
  3191.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3192.                               "upstream prematurely closed connection");
  3193.             }

  3194.             ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
  3195.             return;
  3196.         }
  3197.     }

  3198.     if (p->downstream_error) {
  3199.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3200.                        "http upstream downstream error");

  3201.         if (!u->cacheable && !u->store && u->peer.connection) {
  3202.             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
  3203.         }
  3204.     }
  3205. }


  3206. static void
  3207. ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
  3208. {
  3209.     size_t                  root;
  3210.     time_t                  lm;
  3211.     ngx_str_t               path;
  3212.     ngx_temp_file_t        *tf;
  3213.     ngx_ext_rename_file_t   ext;

  3214.     tf = u->pipe->temp_file;

  3215.     if (tf->file.fd == NGX_INVALID_FILE) {

  3216.         /* create file for empty 200 response */

  3217.         tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
  3218.         if (tf == NULL) {
  3219.             return;
  3220.         }

  3221.         tf->file.fd = NGX_INVALID_FILE;
  3222.         tf->file.log = r->connection->log;
  3223.         tf->path = u->conf->temp_path;
  3224.         tf->pool = r->pool;
  3225.         tf->persistent = 1;

  3226.         if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
  3227.                                  tf->persistent, tf->clean, tf->access)
  3228.             != NGX_OK)
  3229.         {
  3230.             return;
  3231.         }

  3232.         u->pipe->temp_file = tf;
  3233.     }

  3234.     ext.access = u->conf->store_access;
  3235.     ext.path_access = u->conf->store_access;
  3236.     ext.time = -1;
  3237.     ext.create_path = 1;
  3238.     ext.delete_file = 1;
  3239.     ext.log = r->connection->log;

  3240.     if (u->headers_in.last_modified) {

  3241.         lm = ngx_parse_http_time(u->headers_in.last_modified->value.data,
  3242.                                  u->headers_in.last_modified->value.len);

  3243.         if (lm != NGX_ERROR) {
  3244.             ext.time = lm;
  3245.             ext.fd = tf->file.fd;
  3246.         }
  3247.     }

  3248.     if (u->conf->store_lengths == NULL) {

  3249.         if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
  3250.             return;
  3251.         }

  3252.     } else {
  3253.         if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
  3254.                                 u->conf->store_values->elts)
  3255.             == NULL)
  3256.         {
  3257.             return;
  3258.         }
  3259.     }

  3260.     path.len--;

  3261.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3262.                    "upstream stores \"%s\" to \"%s\"",
  3263.                    tf->file.name.data, path.data);

  3264.     if (path.len == 0) {
  3265.         return;
  3266.     }

  3267.     (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);

  3268.     u->store = 0;
  3269. }


  3270. static void
  3271. ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
  3272. {
  3273.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3274.                    "http upstream dummy handler");
  3275. }


  3276. static void
  3277. ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
  3278.     ngx_uint_t ft_type)
  3279. {
  3280.     ngx_msec_t  timeout;
  3281.     ngx_uint_t  status, state;

  3282.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3283.                    "http next upstream, %xi", ft_type);

  3284.     if (u->peer.sockaddr) {

  3285.         if (u->peer.connection) {
  3286.             u->state->bytes_sent = u->peer.connection->sent;
  3287.         }

  3288.         if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403
  3289.             || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404)
  3290.         {
  3291.             state = NGX_PEER_NEXT;

  3292.         } else {
  3293.             state = NGX_PEER_FAILED;
  3294.         }

  3295.         u->peer.free(&u->peer, u->peer.data, state);
  3296.         u->peer.sockaddr = NULL;
  3297.     }

  3298.     if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
  3299.         ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,
  3300.                       "upstream timed out");
  3301.     }

  3302.     if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
  3303.         /* TODO: inform balancer instead */
  3304.         u->peer.tries++;
  3305.     }

  3306.     switch (ft_type) {

  3307.     case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
  3308.     case NGX_HTTP_UPSTREAM_FT_HTTP_504:
  3309.         status = NGX_HTTP_GATEWAY_TIME_OUT;
  3310.         break;

  3311.     case NGX_HTTP_UPSTREAM_FT_HTTP_500:
  3312.         status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  3313.         break;

  3314.     case NGX_HTTP_UPSTREAM_FT_HTTP_503:
  3315.         status = NGX_HTTP_SERVICE_UNAVAILABLE;
  3316.         break;

  3317.     case NGX_HTTP_UPSTREAM_FT_HTTP_403:
  3318.         status = NGX_HTTP_FORBIDDEN;
  3319.         break;

  3320.     case NGX_HTTP_UPSTREAM_FT_HTTP_404:
  3321.         status = NGX_HTTP_NOT_FOUND;
  3322.         break;

  3323.     case NGX_HTTP_UPSTREAM_FT_HTTP_429:
  3324.         status = NGX_HTTP_TOO_MANY_REQUESTS;
  3325.         break;

  3326.     /*
  3327.      * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
  3328.      * never reach here
  3329.      */

  3330.     default:
  3331.         status = NGX_HTTP_BAD_GATEWAY;
  3332.     }

  3333.     if (r->connection->error) {
  3334.         ngx_http_upstream_finalize_request(r, u,
  3335.                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
  3336.         return;
  3337.     }

  3338.     u->state->status = status;

  3339.     timeout = u->conf->next_upstream_timeout;

  3340.     if (u->request_sent
  3341.         && (r->method & (NGX_HTTP_POST|NGX_HTTP_LOCK|NGX_HTTP_PATCH)))
  3342.     {
  3343.         ft_type |= NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT;
  3344.     }

  3345.     if (u->peer.tries == 0
  3346.         || ((u->conf->next_upstream & ft_type) != ft_type)
  3347.         || (u->request_sent && r->request_body_no_buffering)
  3348.         || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
  3349.     {
  3350. #if (NGX_HTTP_CACHE)

  3351.         if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
  3352.             && ((u->conf->cache_use_stale & ft_type) || r->cache->stale_error))
  3353.         {
  3354.             ngx_int_t  rc;

  3355.             rc = u->reinit_request(r);

  3356.             if (rc != NGX_OK) {
  3357.                 ngx_http_upstream_finalize_request(r, u, rc);
  3358.                 return;
  3359.             }

  3360.             u->cache_status = NGX_HTTP_CACHE_STALE;
  3361.             rc = ngx_http_upstream_cache_send(r, u);

  3362.             if (rc == NGX_DONE) {
  3363.                 return;
  3364.             }

  3365.             if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
  3366.                 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  3367.             }

  3368.             ngx_http_upstream_finalize_request(r, u, rc);
  3369.             return;
  3370.         }
  3371. #endif

  3372.         ngx_http_upstream_finalize_request(r, u, status);
  3373.         return;
  3374.     }

  3375.     if (u->peer.connection) {
  3376.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3377.                        "close http upstream connection: %d",
  3378.                        u->peer.connection->fd);
  3379. #if (NGX_HTTP_SSL)

  3380.         if (u->peer.connection->ssl) {
  3381.             u->peer.connection->ssl->no_wait_shutdown = 1;
  3382.             u->peer.connection->ssl->no_send_shutdown = 1;

  3383.             (void) ngx_ssl_shutdown(u->peer.connection);
  3384.         }
  3385. #endif

  3386.         if (u->peer.connection->pool) {
  3387.             ngx_destroy_pool(u->peer.connection->pool);
  3388.         }

  3389.         ngx_close_connection(u->peer.connection);
  3390.         u->peer.connection = NULL;
  3391.     }

  3392.     ngx_http_upstream_connect(r, u);
  3393. }


  3394. static void
  3395. ngx_http_upstream_cleanup(void *data)
  3396. {
  3397.     ngx_http_request_t *r = data;

  3398.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3399.                    "cleanup http upstream request: \"%V\"", &r->uri);

  3400.     ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
  3401. }


  3402. static void
  3403. ngx_http_upstream_finalize_request(ngx_http_request_t *r,
  3404.     ngx_http_upstream_t *u, ngx_int_t rc)
  3405. {
  3406.     ngx_uint_t  flush;

  3407.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3408.                    "finalize http upstream request: %i", rc);

  3409.     if (u->cleanup == NULL) {
  3410.         /* the request was already finalized */
  3411.         ngx_http_finalize_request(r, NGX_DONE);
  3412.         return;
  3413.     }

  3414.     *u->cleanup = NULL;
  3415.     u->cleanup = NULL;

  3416.     if (u->resolved && u->resolved->ctx) {
  3417.         ngx_resolve_name_done(u->resolved->ctx);
  3418.         u->resolved->ctx = NULL;
  3419.     }

  3420.     if (u->state && u->state->response_time == (ngx_msec_t) -1) {
  3421.         u->state->response_time = ngx_current_msec - u->start_time;

  3422.         if (u->pipe && u->pipe->read_length) {
  3423.             u->state->bytes_received += u->pipe->read_length
  3424.                                         - u->pipe->preread_size;
  3425.             u->state->response_length = u->pipe->read_length;
  3426.         }

  3427.         if (u->peer.connection) {
  3428.             u->state->bytes_sent = u->peer.connection->sent;
  3429.         }
  3430.     }

  3431.     u->finalize_request(r, rc);

  3432.     if (u->peer.free && u->peer.sockaddr) {
  3433.         u->peer.free(&u->peer, u->peer.data, 0);
  3434.         u->peer.sockaddr = NULL;
  3435.     }

  3436.     if (u->peer.connection) {

  3437. #if (NGX_HTTP_SSL)

  3438.         /* TODO: do not shutdown persistent connection */

  3439.         if (u->peer.connection->ssl) {

  3440.             /*
  3441.              * We send the "close notify" shutdown alert to the upstream only
  3442.              * and do not wait its "close notify" shutdown alert.
  3443.              * It is acceptable according to the TLS standard.
  3444.              */

  3445.             u->peer.connection->ssl->no_wait_shutdown = 1;

  3446.             (void) ngx_ssl_shutdown(u->peer.connection);
  3447.         }
  3448. #endif

  3449.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3450.                        "close http upstream connection: %d",
  3451.                        u->peer.connection->fd);

  3452.         if (u->peer.connection->pool) {
  3453.             ngx_destroy_pool(u->peer.connection->pool);
  3454.         }

  3455.         ngx_close_connection(u->peer.connection);
  3456.     }

  3457.     u->peer.connection = NULL;

  3458.     if (u->pipe) {
  3459.         u->pipe->upstream = NULL;
  3460.     }

  3461.     if (u->pipe && u->pipe->temp_file) {
  3462.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3463.                        "http upstream temp fd: %d",
  3464.                        u->pipe->temp_file->file.fd);
  3465.     }

  3466.     if (u->store && u->pipe && u->pipe->temp_file
  3467.         && u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
  3468.     {
  3469.         if (ngx_delete_file(u->pipe->temp_file->file.name.data)
  3470.             == NGX_FILE_ERROR)
  3471.         {
  3472.             ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
  3473.                           ngx_delete_file_n " \"%s\" failed",
  3474.                           u->pipe->temp_file->file.name.data);
  3475.         }
  3476.     }

  3477. #if (NGX_HTTP_CACHE)

  3478.     if (r->cache) {

  3479.         if (u->cacheable) {

  3480.             if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
  3481.                 time_t  valid;

  3482.                 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);

  3483.                 if (valid) {
  3484.                     r->cache->valid_sec = ngx_time() + valid;
  3485.                     r->cache->error = rc;
  3486.                 }
  3487.             }
  3488.         }

  3489.         ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
  3490.     }

  3491. #endif

  3492.     r->read_event_handler = ngx_http_block_reading;

  3493.     if (rc == NGX_DECLINED) {
  3494.         return;
  3495.     }

  3496.     r->connection->log->action = "sending to client";

  3497.     if (!u->header_sent
  3498.         || rc == NGX_HTTP_REQUEST_TIME_OUT
  3499.         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST)
  3500.     {
  3501.         ngx_http_finalize_request(r, rc);
  3502.         return;
  3503.     }

  3504.     flush = 0;

  3505.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  3506.         rc = NGX_ERROR;
  3507.         flush = 1;
  3508.     }

  3509.     if (r->header_only
  3510.         || (u->pipe && u->pipe->downstream_error))
  3511.     {
  3512.         ngx_http_finalize_request(r, rc);
  3513.         return;
  3514.     }

  3515.     if (rc == 0) {

  3516.         if (ngx_http_upstream_process_trailers(r, u) != NGX_OK) {
  3517.             ngx_http_finalize_request(r, NGX_ERROR);
  3518.             return;
  3519.         }

  3520.         rc = ngx_http_send_special(r, NGX_HTTP_LAST);

  3521.     } else if (flush) {
  3522.         r->keepalive = 0;
  3523.         rc = ngx_http_send_special(r, NGX_HTTP_FLUSH);
  3524.     }

  3525.     ngx_http_finalize_request(r, rc);
  3526. }


  3527. static ngx_int_t
  3528. ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
  3529.     ngx_uint_t offset)
  3530. {
  3531.     ngx_table_elt_t  **ph;

  3532.     ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);

  3533.     if (*ph) {
  3534.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  3535.                       "upstream sent duplicate header line: \"%V: %V\", "
  3536.                       "previous value: \"%V: %V\", ignored",
  3537.                       &h->key, &h->value,
  3538.                       &(*ph)->key, &(*ph)->value);
  3539.         h->hash = 0;
  3540.         return NGX_OK;
  3541.     }

  3542.     *ph = h;
  3543.     h->next = NULL;

  3544.     return NGX_OK;
  3545. }


  3546. static ngx_int_t
  3547. ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
  3548.     ngx_table_elt_t *h, ngx_uint_t offset)
  3549. {
  3550.     ngx_table_elt_t  **ph;

  3551.     ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);

  3552.     while (*ph) { ph = &(*ph)->next; }

  3553.     *ph = h;
  3554.     h->next = NULL;

  3555.     return NGX_OK;
  3556. }


  3557. static ngx_int_t
  3558. ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
  3559.     ngx_uint_t offset)
  3560. {
  3561.     return NGX_OK;
  3562. }


  3563. static ngx_int_t
  3564. ngx_http_upstream_process_content_length(ngx_http_request_t *r,
  3565.     ngx_table_elt_t *h, ngx_uint_t offset)
  3566. {
  3567.     ngx_http_upstream_t  *u;

  3568.     u = r->upstream;

  3569.     if (u->headers_in.content_length) {
  3570.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3571.                       "upstream sent duplicate header line: \"%V: %V\", "
  3572.                       "previous value: \"%V: %V\"",
  3573.                       &h->key, &h->value,
  3574.                       &u->headers_in.content_length->key,
  3575.                       &u->headers_in.content_length->value);
  3576.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3577.     }

  3578.     if (u->headers_in.transfer_encoding) {
  3579.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3580.                       "upstream sent \"Content-Length\" and "
  3581.                       "\"Transfer-Encoding\" headers at the same time");
  3582.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3583.     }

  3584.     h->next = NULL;
  3585.     u->headers_in.content_length = h;
  3586.     u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);

  3587.     if (u->headers_in.content_length_n == NGX_ERROR) {
  3588.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3589.                       "upstream sent invalid \"Content-Length\" header: "
  3590.                       "\"%V: %V\"", &h->key, &h->value);
  3591.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3592.     }

  3593.     return NGX_OK;
  3594. }


  3595. static ngx_int_t
  3596. ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
  3597.     ngx_table_elt_t *h, ngx_uint_t offset)
  3598. {
  3599.     ngx_http_upstream_t  *u;

  3600.     u = r->upstream;

  3601.     if (u->headers_in.last_modified) {
  3602.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  3603.                       "upstream sent duplicate header line: \"%V: %V\", "
  3604.                       "previous value: \"%V: %V\", ignored",
  3605.                       &h->key, &h->value,
  3606.                       &u->headers_in.last_modified->key,
  3607.                       &u->headers_in.last_modified->value);
  3608.         h->hash = 0;
  3609.         return NGX_OK;
  3610.     }

  3611.     h->next = NULL;
  3612.     u->headers_in.last_modified = h;
  3613.     u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data,
  3614.                                                            h->value.len);

  3615.     return NGX_OK;
  3616. }


  3617. static ngx_int_t
  3618. ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
  3619.     ngx_uint_t offset)
  3620. {
  3621.     ngx_table_elt_t      **ph;
  3622.     ngx_http_upstream_t   *u;

  3623.     u = r->upstream;
  3624.     ph = &u->headers_in.set_cookie;

  3625.     while (*ph) { ph = &(*ph)->next; }

  3626.     *ph = h;
  3627.     h->next = NULL;

  3628. #if (NGX_HTTP_CACHE)
  3629.     if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
  3630.         u->cacheable = 0;
  3631.     }
  3632. #endif

  3633.     return NGX_OK;
  3634. }


  3635. static ngx_int_t
  3636. ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
  3637.     ngx_table_elt_t *h, ngx_uint_t offset)
  3638. {
  3639.     ngx_table_elt_t      **ph;
  3640.     ngx_http_upstream_t   *u;

  3641.     u = r->upstream;
  3642.     ph = &u->headers_in.cache_control;

  3643.     while (*ph) { ph = &(*ph)->next; }

  3644.     *ph = h;
  3645.     h->next = NULL;

  3646. #if (NGX_HTTP_CACHE)
  3647.     {
  3648.     u_char     *p, *start, *last;
  3649.     ngx_int_t   n;

  3650.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
  3651.         return NGX_OK;
  3652.     }

  3653.     if (r->cache == NULL) {
  3654.         return NGX_OK;
  3655.     }

  3656.     start = h->value.data;
  3657.     last = start + h->value.len;

  3658.     if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
  3659.         goto extensions;
  3660.     }

  3661.     if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL
  3662.         || ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL
  3663.         || ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL)
  3664.     {
  3665.         u->headers_in.no_cache = 1;
  3666.         return NGX_OK;
  3667.     }

  3668.     p = ngx_strlcasestrn(start, last, (u_char *) "s-maxage=", 9 - 1);
  3669.     offset = 9;

  3670.     if (p == NULL) {
  3671.         p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1);
  3672.         offset = 8;
  3673.     }

  3674.     if (p) {
  3675.         n = 0;

  3676.         for (p += offset; p < last; p++) {
  3677.             if (*p == ',' || *p == ';' || *p == ' ') {
  3678.                 break;
  3679.             }

  3680.             if (*p >= '0' && *p <= '9') {
  3681.                 n = n * 10 + (*p - '0');
  3682.                 continue;
  3683.             }

  3684.             u->cacheable = 0;
  3685.             return NGX_OK;
  3686.         }

  3687.         if (n == 0) {
  3688.             u->headers_in.no_cache = 1;
  3689.             return NGX_OK;
  3690.         }

  3691.         r->cache->valid_sec = ngx_time() + n;
  3692.         u->headers_in.expired = 0;
  3693.     }

  3694. extensions:

  3695.     p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=",
  3696.                          23 - 1);

  3697.     if (p) {
  3698.         n = 0;

  3699.         for (p += 23; p < last; p++) {
  3700.             if (*p == ',' || *p == ';' || *p == ' ') {
  3701.                 break;
  3702.             }

  3703.             if (*p >= '0' && *p <= '9') {
  3704.                 n = n * 10 + (*p - '0');
  3705.                 continue;
  3706.             }

  3707.             u->cacheable = 0;
  3708.             return NGX_OK;
  3709.         }

  3710.         r->cache->updating_sec = n;
  3711.         r->cache->error_sec = n;
  3712.     }

  3713.     p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1);

  3714.     if (p) {
  3715.         n = 0;

  3716.         for (p += 15; p < last; p++) {
  3717.             if (*p == ',' || *p == ';' || *p == ' ') {
  3718.                 break;
  3719.             }

  3720.             if (*p >= '0' && *p <= '9') {
  3721.                 n = n * 10 + (*p - '0');
  3722.                 continue;
  3723.             }

  3724.             u->cacheable = 0;
  3725.             return NGX_OK;
  3726.         }

  3727.         r->cache->error_sec = n;
  3728.     }
  3729.     }
  3730. #endif

  3731.     return NGX_OK;
  3732. }


  3733. static ngx_int_t
  3734. ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
  3735.     ngx_uint_t offset)
  3736. {
  3737.     ngx_http_upstream_t  *u;

  3738.     u = r->upstream;

  3739.     if (u->headers_in.expires) {
  3740.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  3741.                       "upstream sent duplicate header line: \"%V: %V\", "
  3742.                       "previous value: \"%V: %V\", ignored",
  3743.                       &h->key, &h->value,
  3744.                       &u->headers_in.expires->key,
  3745.                       &u->headers_in.expires->value);
  3746.         h->hash = 0;
  3747.         return NGX_OK;
  3748.     }

  3749.     u->headers_in.expires = h;
  3750.     h->next = NULL;

  3751. #if (NGX_HTTP_CACHE)
  3752.     {
  3753.     time_t  expires;

  3754.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES) {
  3755.         return NGX_OK;
  3756.     }

  3757.     if (r->cache == NULL) {
  3758.         return NGX_OK;
  3759.     }

  3760.     if (r->cache->valid_sec != 0) {
  3761.         return NGX_OK;
  3762.     }

  3763.     expires = ngx_parse_http_time(h->value.data, h->value.len);

  3764.     if (expires == NGX_ERROR || expires < ngx_time()) {
  3765.         u->headers_in.expired = 1;
  3766.         return NGX_OK;
  3767.     }

  3768.     r->cache->valid_sec = expires;
  3769.     }
  3770. #endif

  3771.     return NGX_OK;
  3772. }


  3773. static ngx_int_t
  3774. ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
  3775.     ngx_table_elt_t *h, ngx_uint_t offset)
  3776. {
  3777.     ngx_http_upstream_t  *u;

  3778.     u = r->upstream;

  3779.     if (u->headers_in.x_accel_expires) {
  3780.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  3781.                       "upstream sent duplicate header line: \"%V: %V\", "
  3782.                       "previous value: \"%V: %V\", ignored",
  3783.                       &h->key, &h->value,
  3784.                       &u->headers_in.x_accel_expires->key,
  3785.                       &u->headers_in.x_accel_expires->value);
  3786.         h->hash = 0;
  3787.         return NGX_OK;
  3788.     }

  3789.     u->headers_in.x_accel_expires = h;
  3790.     h->next = NULL;

  3791. #if (NGX_HTTP_CACHE)
  3792.     {
  3793.     u_char     *p;
  3794.     size_t      len;
  3795.     ngx_int_t   n;

  3796.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES) {
  3797.         return NGX_OK;
  3798.     }

  3799.     if (r->cache == NULL) {
  3800.         return NGX_OK;
  3801.     }

  3802.     len = h->value.len;
  3803.     p = h->value.data;

  3804.     if (p[0] != '@') {
  3805.         n = ngx_atoi(p, len);

  3806.         switch (n) {
  3807.         case 0:
  3808.             u->cacheable = 0;
  3809.             /* fall through */

  3810.         case NGX_ERROR:
  3811.             return NGX_OK;

  3812.         default:
  3813.             r->cache->valid_sec = ngx_time() + n;
  3814.             u->headers_in.no_cache = 0;
  3815.             u->headers_in.expired = 0;
  3816.             return NGX_OK;
  3817.         }
  3818.     }

  3819.     p++;
  3820.     len--;

  3821.     n = ngx_atoi(p, len);

  3822.     if (n != NGX_ERROR) {
  3823.         r->cache->valid_sec = n;
  3824.         u->headers_in.no_cache = 0;
  3825.         u->headers_in.expired = 0;
  3826.     }
  3827.     }
  3828. #endif

  3829.     return NGX_OK;
  3830. }


  3831. static ngx_int_t
  3832. ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
  3833.     ngx_uint_t offset)
  3834. {
  3835.     ngx_int_t             n;
  3836.     ngx_http_upstream_t  *u;

  3837.     u = r->upstream;

  3838.     if (u->headers_in.x_accel_limit_rate) {
  3839.         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
  3840.                       "upstream sent duplicate header line: \"%V: %V\", "
  3841.                       "previous value: \"%V: %V\", ignored",
  3842.                       &h->key, &h->value,
  3843.                       &u->headers_in.x_accel_limit_rate->key,
  3844.                       &u->headers_in.x_accel_limit_rate->value);
  3845.         h->hash = 0;
  3846.         return NGX_OK;
  3847.     }

  3848.     u->headers_in.x_accel_limit_rate = h;
  3849.     h->next = NULL;

  3850.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) {
  3851.         return NGX_OK;
  3852.     }

  3853.     n = ngx_atoi(h->value.data, h->value.len);

  3854.     if (n != NGX_ERROR) {
  3855.         r->limit_rate = (size_t) n;
  3856.         r->limit_rate_set = 1;
  3857.     }

  3858.     return NGX_OK;
  3859. }


  3860. static ngx_int_t
  3861. ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
  3862.     ngx_uint_t offset)
  3863. {
  3864.     u_char                c0, c1, c2;
  3865.     ngx_http_upstream_t  *u;

  3866.     u = r->upstream;

  3867.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) {
  3868.         return NGX_OK;
  3869.     }

  3870.     if (u->conf->change_buffering) {

  3871.         if (h->value.len == 2) {
  3872.             c0 = ngx_tolower(h->value.data[0]);
  3873.             c1 = ngx_tolower(h->value.data[1]);

  3874.             if (c0 == 'n' && c1 == 'o') {
  3875.                 u->buffering = 0;
  3876.             }

  3877.         } else if (h->value.len == 3) {
  3878.             c0 = ngx_tolower(h->value.data[0]);
  3879.             c1 = ngx_tolower(h->value.data[1]);
  3880.             c2 = ngx_tolower(h->value.data[2]);

  3881.             if (c0 == 'y' && c1 == 'e' && c2 == 's') {
  3882.                 u->buffering = 1;
  3883.             }
  3884.         }
  3885.     }

  3886.     return NGX_OK;
  3887. }


  3888. static ngx_int_t
  3889. ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
  3890.     ngx_uint_t offset)
  3891. {
  3892.     ngx_http_upstream_t  *u;

  3893.     u = r->upstream;

  3894.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
  3895.         return NGX_OK;
  3896.     }

  3897.     r->headers_out.override_charset = &h->value;

  3898.     return NGX_OK;
  3899. }


  3900. static ngx_int_t
  3901. ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
  3902.     ngx_uint_t offset)
  3903. {
  3904.     ngx_table_elt_t      **ph;
  3905.     ngx_http_upstream_t   *u;

  3906.     u = r->upstream;
  3907.     ph = &u->headers_in.connection;

  3908.     while (*ph) { ph = &(*ph)->next; }

  3909.     *ph = h;
  3910.     h->next = NULL;

  3911.     if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
  3912.                          (u_char *) "close", 5 - 1)
  3913.         != NULL)
  3914.     {
  3915.         u->headers_in.connection_close = 1;
  3916.     }

  3917.     return NGX_OK;
  3918. }


  3919. static ngx_int_t
  3920. ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
  3921.     ngx_table_elt_t *h, ngx_uint_t offset)
  3922. {
  3923.     ngx_http_upstream_t  *u;

  3924.     u = r->upstream;

  3925.     if (u->headers_in.transfer_encoding) {
  3926.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3927.                       "upstream sent duplicate header line: \"%V: %V\", "
  3928.                       "previous value: \"%V: %V\"",
  3929.                       &h->key, &h->value,
  3930.                       &u->headers_in.transfer_encoding->key,
  3931.                       &u->headers_in.transfer_encoding->value);
  3932.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3933.     }

  3934.     if (u->headers_in.content_length) {
  3935.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3936.                       "upstream sent \"Content-Length\" and "
  3937.                       "\"Transfer-Encoding\" headers at the same time");
  3938.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3939.     }

  3940.     u->headers_in.transfer_encoding = h;
  3941.     h->next = NULL;

  3942.     if (h->value.len == 7
  3943.         && ngx_strncasecmp(h->value.data, (u_char *) "chunked", 7) == 0)
  3944.     {
  3945.         u->headers_in.chunked = 1;

  3946.     } else {
  3947.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3948.                       "upstream sent unknown \"Transfer-Encoding\": \"%V\"",
  3949.                       &h->value);
  3950.         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  3951.     }

  3952.     return NGX_OK;
  3953. }


  3954. static ngx_int_t
  3955. ngx_http_upstream_process_vary(ngx_http_request_t *r,
  3956.     ngx_table_elt_t *h, ngx_uint_t offset)
  3957. {
  3958.     ngx_table_elt_t      **ph;
  3959.     ngx_http_upstream_t   *u;

  3960.     u = r->upstream;
  3961.     ph = &u->headers_in.vary;

  3962.     while (*ph) { ph = &(*ph)->next; }

  3963.     *ph = h;
  3964.     h->next = NULL;

  3965. #if (NGX_HTTP_CACHE)
  3966.     {
  3967.     u_char     *p;
  3968.     size_t      len;
  3969.     ngx_str_t   vary;

  3970.     if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_VARY) {
  3971.         return NGX_OK;
  3972.     }

  3973.     if (r->cache == NULL || !u->cacheable) {
  3974.         return NGX_OK;
  3975.     }

  3976.     if (h->value.len == 1 && h->value.data[0] == '*') {
  3977.         u->cacheable = 0;
  3978.         return NGX_OK;
  3979.     }

  3980.     if (u->headers_in.vary->next) {

  3981.         len = 0;

  3982.         for (h = u->headers_in.vary; h; h = h->next) {
  3983.             len += h->value.len + 2;
  3984.         }

  3985.         len -= 2;

  3986.         p = ngx_pnalloc(r->pool, len);
  3987.         if (p == NULL) {
  3988.             return NGX_ERROR;
  3989.         }

  3990.         vary.len = len;
  3991.         vary.data = p;

  3992.         for (h = u->headers_in.vary; h; h = h->next) {
  3993.             p = ngx_copy(p, h->value.data, h->value.len);

  3994.             if (h->next == NULL) {
  3995.                 break;
  3996.             }

  3997.             *p++ = ','; *p++ = ' ';
  3998.         }

  3999.     } else {
  4000.         vary = h->value;
  4001.     }

  4002.     if (vary.len > NGX_HTTP_CACHE_VARY_LEN) {
  4003.         u->cacheable = 0;
  4004.     }

  4005.     r->cache->vary = vary;
  4006.     }
  4007. #endif

  4008.     return NGX_OK;
  4009. }


  4010. static ngx_int_t
  4011. ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
  4012.     ngx_uint_t offset)
  4013. {
  4014.     ngx_table_elt_t  *ho, **ph;

  4015.     ho = ngx_list_push(&r->headers_out.headers);
  4016.     if (ho == NULL) {
  4017.         return NGX_ERROR;
  4018.     }

  4019.     *ho = *h;

  4020.     if (offset) {
  4021.         ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
  4022.         *ph = ho;
  4023.         ho->next = NULL;
  4024.     }

  4025.     return NGX_OK;
  4026. }


  4027. static ngx_int_t
  4028. ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
  4029.     ngx_table_elt_t *h, ngx_uint_t offset)
  4030. {
  4031.     ngx_table_elt_t  *ho, **ph;

  4032.     ho = ngx_list_push(&r->headers_out.headers);
  4033.     if (ho == NULL) {
  4034.         return NGX_ERROR;
  4035.     }

  4036.     *ho = *h;

  4037.     ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);

  4038.     while (*ph) { ph = &(*ph)->next; }

  4039.     *ph = ho;
  4040.     ho->next = NULL;

  4041.     return NGX_OK;
  4042. }


  4043. static ngx_int_t
  4044. ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
  4045.     ngx_uint_t offset)
  4046. {
  4047.     u_char  *p, *last;

  4048.     r->headers_out.content_type_len = h->value.len;
  4049.     r->headers_out.content_type = h->value;
  4050.     r->headers_out.content_type_lowcase = NULL;

  4051.     for (p = h->value.data; *p; p++) {

  4052.         if (*p != ';') {
  4053.             continue;
  4054.         }

  4055.         last = p;

  4056.         while (*++p == ' ') { /* void */ }

  4057.         if (*p == '\0') {
  4058.             return NGX_OK;
  4059.         }

  4060.         if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
  4061.             continue;
  4062.         }

  4063.         p += 8;

  4064.         r->headers_out.content_type_len = last - h->value.data;

  4065.         if (*p == '"') {
  4066.             p++;
  4067.         }

  4068.         last = h->value.data + h->value.len;

  4069.         if (*(last - 1) == '"') {
  4070.             last--;
  4071.         }

  4072.         r->headers_out.charset.len = last - p;
  4073.         r->headers_out.charset.data = p;

  4074.         return NGX_OK;
  4075.     }

  4076.     return NGX_OK;
  4077. }


  4078. static ngx_int_t
  4079. ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
  4080.     ngx_uint_t offset)
  4081. {
  4082.     ngx_table_elt_t  *ho;

  4083.     ho = ngx_list_push(&r->headers_out.headers);
  4084.     if (ho == NULL) {
  4085.         return NGX_ERROR;
  4086.     }

  4087.     *ho = *h;
  4088.     ho->next = NULL;

  4089.     r->headers_out.last_modified = ho;
  4090.     r->headers_out.last_modified_time =
  4091.                                     r->upstream->headers_in.last_modified_time;

  4092.     return NGX_OK;
  4093. }


  4094. static ngx_int_t
  4095. ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
  4096.     ngx_uint_t offset)
  4097. {
  4098.     ngx_int_t         rc;
  4099.     ngx_table_elt_t  *ho;

  4100.     ho = ngx_list_push(&r->headers_out.headers);
  4101.     if (ho == NULL) {
  4102.         return NGX_ERROR;
  4103.     }

  4104.     *ho = *h;
  4105.     ho->next = NULL;

  4106.     if (r->upstream->rewrite_redirect) {
  4107.         rc = r->upstream->rewrite_redirect(r, ho, 0);

  4108.         if (rc == NGX_DECLINED) {
  4109.             return NGX_OK;
  4110.         }

  4111.         if (rc == NGX_OK) {
  4112.             r->headers_out.location = ho;

  4113.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  4114.                            "rewritten location: \"%V\"", &ho->value);
  4115.         }

  4116.         return rc;
  4117.     }

  4118.     if (ho->value.data[0] != '/') {
  4119.         r->headers_out.location = ho;
  4120.     }

  4121.     /*
  4122.      * we do not set r->headers_out.location here to avoid handling
  4123.      * relative redirects in ngx_http_header_filter()
  4124.      */

  4125.     return NGX_OK;
  4126. }


  4127. static ngx_int_t
  4128. ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
  4129.     ngx_uint_t offset)
  4130. {
  4131.     u_char           *p;
  4132.     ngx_int_t         rc;
  4133.     ngx_table_elt_t  *ho;

  4134.     ho = ngx_list_push(&r->headers_out.headers);
  4135.     if (ho == NULL) {
  4136.         return NGX_ERROR;
  4137.     }

  4138.     *ho = *h;
  4139.     ho->next = NULL;

  4140.     if (r->upstream->rewrite_redirect) {

  4141.         p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1);

  4142.         if (p) {
  4143.             rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);

  4144.         } else {
  4145.             return NGX_OK;
  4146.         }

  4147.         if (rc == NGX_DECLINED) {
  4148.             return NGX_OK;
  4149.         }

  4150.         if (rc == NGX_OK) {
  4151.             r->headers_out.refresh = ho;

  4152.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  4153.                            "rewritten refresh: \"%V\"", &ho->value);
  4154.         }

  4155.         return rc;
  4156.     }

  4157.     r->headers_out.refresh = ho;

  4158.     return NGX_OK;
  4159. }


  4160. static ngx_int_t
  4161. ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
  4162.     ngx_uint_t offset)
  4163. {
  4164.     ngx_int_t         rc;
  4165.     ngx_table_elt_t  *ho;

  4166.     ho = ngx_list_push(&r->headers_out.headers);
  4167.     if (ho == NULL) {
  4168.         return NGX_ERROR;
  4169.     }

  4170.     *ho = *h;
  4171.     ho->next = NULL;

  4172.     if (r->upstream->rewrite_cookie) {
  4173.         rc = r->upstream->rewrite_cookie(r, ho);

  4174.         if (rc == NGX_DECLINED) {
  4175.             return NGX_OK;
  4176.         }

  4177. #if (NGX_DEBUG)
  4178.         if (rc == NGX_OK) {
  4179.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  4180.                            "rewritten cookie: \"%V\"", &ho->value);
  4181.         }
  4182. #endif

  4183.         return rc;
  4184.     }

  4185.     return NGX_OK;
  4186. }


  4187. static ngx_int_t
  4188. ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
  4189.     ngx_table_elt_t *h, ngx_uint_t offset)
  4190. {
  4191.     ngx_table_elt_t  *ho;

  4192.     if (r->upstream->conf->force_ranges) {
  4193.         return NGX_OK;
  4194.     }

  4195. #if (NGX_HTTP_CACHE)

  4196.     if (r->cached) {
  4197.         r->allow_ranges = 1;
  4198.         return NGX_OK;
  4199.     }

  4200.     if (r->upstream->cacheable) {
  4201.         r->allow_ranges = 1;
  4202.         r->single_range = 1;
  4203.         return NGX_OK;
  4204.     }

  4205. #endif

  4206.     ho = ngx_list_push(&r->headers_out.headers);
  4207.     if (ho == NULL) {
  4208.         return NGX_ERROR;
  4209.     }

  4210.     *ho = *h;
  4211.     ho->next = NULL;

  4212.     r->headers_out.accept_ranges = ho;

  4213.     return NGX_OK;
  4214. }


  4215. static ngx_int_t
  4216. ngx_http_upstream_add_variables(ngx_conf_t *cf)
  4217. {
  4218.     ngx_http_variable_t  *var, *v;

  4219.     for (v = ngx_http_upstream_vars; v->name.len; v++) {
  4220.         var = ngx_http_add_variable(cf, &v->name, v->flags);
  4221.         if (var == NULL) {
  4222.             return NGX_ERROR;
  4223.         }

  4224.         var->get_handler = v->get_handler;
  4225.         var->data = v->data;
  4226.     }

  4227.     return NGX_OK;
  4228. }


  4229. static ngx_int_t
  4230. ngx_http_upstream_addr_variable(ngx_http_request_t *r,
  4231.     ngx_http_variable_value_t *v, uintptr_t data)
  4232. {
  4233.     u_char                     *p;
  4234.     size_t                      len;
  4235.     ngx_uint_t                  i;
  4236.     ngx_http_upstream_state_t  *state;

  4237.     v->valid = 1;
  4238.     v->no_cacheable = 0;
  4239.     v->not_found = 0;

  4240.     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
  4241.         v->not_found = 1;
  4242.         return NGX_OK;
  4243.     }

  4244.     len = 0;
  4245.     state = r->upstream_states->elts;

  4246.     for (i = 0; i < r->upstream_states->nelts; i++) {
  4247.         if (state[i].peer) {
  4248.             len += state[i].peer->len + 2;

  4249.         } else {
  4250.             len += 3;
  4251.         }
  4252.     }

  4253.     p = ngx_pnalloc(r->pool, len);
  4254.     if (p == NULL) {
  4255.         return NGX_ERROR;
  4256.     }

  4257.     v->data = p;

  4258.     i = 0;

  4259.     for ( ;; ) {
  4260.         if (state[i].peer) {
  4261.             p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len);
  4262.         }

  4263.         if (++i == r->upstream_states->nelts) {
  4264.             break;
  4265.         }

  4266.         if (state[i].peer) {
  4267.             *p++ = ',';
  4268.             *p++ = ' ';

  4269.         } else {
  4270.             *p++ = ' ';
  4271.             *p++ = ':';
  4272.             *p++ = ' ';

  4273.             if (++i == r->upstream_states->nelts) {
  4274.                 break;
  4275.             }

  4276.             continue;
  4277.         }
  4278.     }

  4279.     v->len = p - v->data;

  4280.     return NGX_OK;
  4281. }


  4282. static ngx_int_t
  4283. ngx_http_upstream_status_variable(ngx_http_request_t *r,
  4284.     ngx_http_variable_value_t *v, uintptr_t data)
  4285. {
  4286.     u_char                     *p;
  4287.     size_t                      len;
  4288.     ngx_uint_t                  i;
  4289.     ngx_http_upstream_state_t  *state;

  4290.     v->valid = 1;
  4291.     v->no_cacheable = 0;
  4292.     v->not_found = 0;

  4293.     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
  4294.         v->not_found = 1;
  4295.         return NGX_OK;
  4296.     }

  4297.     len = r->upstream_states->nelts * (3 + 2);

  4298.     p = ngx_pnalloc(r->pool, len);
  4299.     if (p == NULL) {
  4300.         return NGX_ERROR;
  4301.     }

  4302.     v->data = p;

  4303.     i = 0;
  4304.     state = r->upstream_states->elts;

  4305.     for ( ;; ) {
  4306.         if (state[i].status) {
  4307.             p = ngx_sprintf(p, "%ui", state[i].status);

  4308.         } else {
  4309.             *p++ = '-';
  4310.         }

  4311.         if (++i == r->upstream_states->nelts) {
  4312.             break;
  4313.         }

  4314.         if (state[i].peer) {
  4315.             *p++ = ',';
  4316.             *p++ = ' ';

  4317.         } else {
  4318.             *p++ = ' ';
  4319.             *p++ = ':';
  4320.             *p++ = ' ';

  4321.             if (++i == r->upstream_states->nelts) {
  4322.                 break;
  4323.             }

  4324.             continue;
  4325.         }
  4326.     }

  4327.     v->len = p - v->data;

  4328.     return NGX_OK;
  4329. }


  4330. static ngx_int_t
  4331. ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
  4332.     ngx_http_variable_value_t *v, uintptr_t data)
  4333. {
  4334.     u_char                     *p;
  4335.     size_t                      len;
  4336.     ngx_uint_t                  i;
  4337.     ngx_msec_int_t              ms;
  4338.     ngx_http_upstream_state_t  *state;

  4339.     v->valid = 1;
  4340.     v->no_cacheable = 0;
  4341.     v->not_found = 0;

  4342.     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
  4343.         v->not_found = 1;
  4344.         return NGX_OK;
  4345.     }

  4346.     len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2);

  4347.     p = ngx_pnalloc(r->pool, len);
  4348.     if (p == NULL) {
  4349.         return NGX_ERROR;
  4350.     }

  4351.     v->data = p;

  4352.     i = 0;
  4353.     state = r->upstream_states->elts;

  4354.     for ( ;; ) {

  4355.         if (data == 1) {
  4356.             ms = state[i].header_time;

  4357.         } else if (data == 2) {
  4358.             ms = state[i].connect_time;

  4359.         } else {
  4360.             ms = state[i].response_time;
  4361.         }

  4362.         if (ms != -1) {
  4363.             ms = ngx_max(ms, 0);
  4364.             p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);

  4365.         } else {
  4366.             *p++ = '-';
  4367.         }

  4368.         if (++i == r->upstream_states->nelts) {
  4369.             break;
  4370.         }

  4371.         if (state[i].peer) {
  4372.             *p++ = ',';
  4373.             *p++ = ' ';

  4374.         } else {
  4375.             *p++ = ' ';
  4376.             *p++ = ':';
  4377.             *p++ = ' ';

  4378.             if (++i == r->upstream_states->nelts) {
  4379.                 break;
  4380.             }

  4381.             continue;
  4382.         }
  4383.     }

  4384.     v->len = p - v->data;

  4385.     return NGX_OK;
  4386. }


  4387. static ngx_int_t
  4388. ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
  4389.     ngx_http_variable_value_t *v, uintptr_t data)
  4390. {
  4391.     u_char                     *p;
  4392.     size_t                      len;
  4393.     ngx_uint_t                  i;
  4394.     ngx_http_upstream_state_t  *state;

  4395.     v->valid = 1;
  4396.     v->no_cacheable = 0;
  4397.     v->not_found = 0;

  4398.     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
  4399.         v->not_found = 1;
  4400.         return NGX_OK;
  4401.     }

  4402.     len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2);

  4403.     p = ngx_pnalloc(r->pool, len);
  4404.     if (p == NULL) {
  4405.         return NGX_ERROR;
  4406.     }

  4407.     v->data = p;

  4408.     i = 0;
  4409.     state = r->upstream_states->elts;

  4410.     for ( ;; ) {

  4411.         if (data == 1) {
  4412.             p = ngx_sprintf(p, "%O", state[i].bytes_received);

  4413.         } else if (data == 2) {
  4414.             p = ngx_sprintf(p, "%O", state[i].bytes_sent);

  4415.         } else {
  4416.             p = ngx_sprintf(p, "%O", state[i].response_length);
  4417.         }

  4418.         if (++i == r->upstream_states->nelts) {
  4419.             break;
  4420.         }

  4421.         if (state[i].peer) {
  4422.             *p++ = ',';
  4423.             *p++ = ' ';

  4424.         } else {
  4425.             *p++ = ' ';
  4426.             *p++ = ':';
  4427.             *p++ = ' ';

  4428.             if (++i == r->upstream_states->nelts) {
  4429.                 break;
  4430.             }

  4431.             continue;
  4432.         }
  4433.     }

  4434.     v->len = p - v->data;

  4435.     return NGX_OK;
  4436. }


  4437. static ngx_int_t
  4438. ngx_http_upstream_header_variable(ngx_http_request_t *r,
  4439.     ngx_http_variable_value_t *v, uintptr_t data)
  4440. {
  4441.     if (r->upstream == NULL) {
  4442.         v->not_found = 1;
  4443.         return NGX_OK;
  4444.     }

  4445.     return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
  4446.                                          &r->upstream->headers_in.headers.part,
  4447.                                          sizeof("upstream_http_") - 1);
  4448. }


  4449. static ngx_int_t
  4450. ngx_http_upstream_trailer_variable(ngx_http_request_t *r,
  4451.     ngx_http_variable_value_t *v, uintptr_t data)
  4452. {
  4453.     if (r->upstream == NULL) {
  4454.         v->not_found = 1;
  4455.         return NGX_OK;
  4456.     }

  4457.     return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
  4458.                                         &r->upstream->headers_in.trailers.part,
  4459.                                         sizeof("upstream_trailer_") - 1);
  4460. }


  4461. static ngx_int_t
  4462. ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
  4463.     ngx_http_variable_value_t *v, uintptr_t data)
  4464. {
  4465.     ngx_str_t  *name = (ngx_str_t *) data;

  4466.     ngx_str_t   cookie, s;

  4467.     if (r->upstream == NULL) {
  4468.         v->not_found = 1;
  4469.         return NGX_OK;
  4470.     }

  4471.     s.len = name->len - (sizeof("upstream_cookie_") - 1);
  4472.     s.data = name->data + sizeof("upstream_cookie_") - 1;

  4473.     if (ngx_http_parse_set_cookie_lines(r, r->upstream->headers_in.set_cookie,
  4474.                                         &s, &cookie)
  4475.         == NULL)
  4476.     {
  4477.         v->not_found = 1;
  4478.         return NGX_OK;
  4479.     }

  4480.     v->len = cookie.len;
  4481.     v->valid = 1;
  4482.     v->no_cacheable = 0;
  4483.     v->not_found = 0;
  4484.     v->data = cookie.data;

  4485.     return NGX_OK;
  4486. }


  4487. #if (NGX_HTTP_CACHE)

  4488. static ngx_int_t
  4489. ngx_http_upstream_cache_status(ngx_http_request_t *r,
  4490.     ngx_http_variable_value_t *v, uintptr_t data)
  4491. {
  4492.     ngx_uint_t  n;

  4493.     if (r->upstream == NULL || r->upstream->cache_status == 0) {
  4494.         v->not_found = 1;
  4495.         return NGX_OK;
  4496.     }

  4497.     n = r->upstream->cache_status - 1;

  4498.     v->valid = 1;
  4499.     v->no_cacheable = 0;
  4500.     v->not_found = 0;
  4501.     v->len = ngx_http_cache_status[n].len;
  4502.     v->data = ngx_http_cache_status[n].data;

  4503.     return NGX_OK;
  4504. }


  4505. static ngx_int_t
  4506. ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
  4507.     ngx_http_variable_value_t *v, uintptr_t data)
  4508. {
  4509.     u_char  *p;

  4510.     if (r->upstream == NULL
  4511.         || !r->upstream->conf->cache_revalidate
  4512.         || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
  4513.         || r->cache->last_modified == -1)
  4514.     {
  4515.         v->not_found = 1;
  4516.         return NGX_OK;
  4517.     }

  4518.     p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
  4519.     if (p == NULL) {
  4520.         return NGX_ERROR;
  4521.     }

  4522.     v->len = ngx_http_time(p, r->cache->last_modified) - p;
  4523.     v->valid = 1;
  4524.     v->no_cacheable = 0;
  4525.     v->not_found = 0;
  4526.     v->data = p;

  4527.     return NGX_OK;
  4528. }


  4529. static ngx_int_t
  4530. ngx_http_upstream_cache_etag(ngx_http_request_t *r,
  4531.     ngx_http_variable_value_t *v, uintptr_t data)
  4532. {
  4533.     if (r->upstream == NULL
  4534.         || !r->upstream->conf->cache_revalidate
  4535.         || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
  4536.         || r->cache->etag.len == 0)
  4537.     {
  4538.         v->not_found = 1;
  4539.         return NGX_OK;
  4540.     }

  4541.     v->valid = 1;
  4542.     v->no_cacheable = 0;
  4543.     v->not_found = 0;
  4544.     v->len = r->cache->etag.len;
  4545.     v->data = r->cache->etag.data;

  4546.     return NGX_OK;
  4547. }

  4548. #endif


  4549. static char *
  4550. ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
  4551. {
  4552.     char                          *rv;
  4553.     void                          *mconf;
  4554.     ngx_str_t                     *value;
  4555.     ngx_url_t                      u;
  4556.     ngx_uint_t                     m;
  4557.     ngx_conf_t                     pcf;
  4558.     ngx_http_module_t             *module;
  4559.     ngx_http_conf_ctx_t           *ctx, *http_ctx;
  4560.     ngx_http_upstream_srv_conf_t  *uscf;

  4561.     ngx_memzero(&u, sizeof(ngx_url_t));

  4562.     value = cf->args->elts;
  4563.     u.host = value[1];
  4564.     u.no_resolve = 1;
  4565.     u.no_port = 1;

  4566.     uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE
  4567.                                          |NGX_HTTP_UPSTREAM_MODIFY
  4568.                                          |NGX_HTTP_UPSTREAM_WEIGHT
  4569.                                          |NGX_HTTP_UPSTREAM_MAX_CONNS
  4570.                                          |NGX_HTTP_UPSTREAM_MAX_FAILS
  4571.                                          |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
  4572.                                          |NGX_HTTP_UPSTREAM_DOWN
  4573.                                          |NGX_HTTP_UPSTREAM_BACKUP);
  4574.     if (uscf == NULL) {
  4575.         return NGX_CONF_ERROR;
  4576.     }


  4577.     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
  4578.     if (ctx == NULL) {
  4579.         return NGX_CONF_ERROR;
  4580.     }

  4581.     http_ctx = cf->ctx;
  4582.     ctx->main_conf = http_ctx->main_conf;

  4583.     /* the upstream{}'s srv_conf */

  4584.     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  4585.     if (ctx->srv_conf == NULL) {
  4586.         return NGX_CONF_ERROR;
  4587.     }

  4588.     ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;

  4589.     uscf->srv_conf = ctx->srv_conf;


  4590.     /* the upstream{}'s loc_conf */

  4591.     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
  4592.     if (ctx->loc_conf == NULL) {
  4593.         return NGX_CONF_ERROR;
  4594.     }

  4595.     for (m = 0; cf->cycle->modules[m]; m++) {
  4596.         if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
  4597.             continue;
  4598.         }

  4599.         module = cf->cycle->modules[m]->ctx;

  4600.         if (module->create_srv_conf) {
  4601.             mconf = module->create_srv_conf(cf);
  4602.             if (mconf == NULL) {
  4603.                 return NGX_CONF_ERROR;
  4604.             }

  4605.             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
  4606.         }

  4607.         if (module->create_loc_conf) {
  4608.             mconf = module->create_loc_conf(cf);
  4609.             if (mconf == NULL) {
  4610.                 return NGX_CONF_ERROR;
  4611.             }

  4612.             ctx->loc_conf[cf->cycle->modules[m]->ctx_index] = mconf;
  4613.         }
  4614.     }

  4615.     uscf->servers = ngx_array_create(cf->pool, 4,
  4616.                                      sizeof(ngx_http_upstream_server_t));
  4617.     if (uscf->servers == NULL) {
  4618.         return NGX_CONF_ERROR;
  4619.     }


  4620.     /* parse inside upstream{} */

  4621.     pcf = *cf;
  4622.     cf->ctx = ctx;
  4623.     cf->cmd_type = NGX_HTTP_UPS_CONF;

  4624.     rv = ngx_conf_parse(cf, NULL);

  4625.     *cf = pcf;

  4626.     if (rv != NGX_CONF_OK) {
  4627.         return rv;
  4628.     }

  4629.     if (uscf->servers->nelts == 0) {
  4630.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4631.                            "no servers are inside upstream");
  4632.         return NGX_CONF_ERROR;
  4633.     }

  4634.     return rv;
  4635. }


  4636. static char *
  4637. ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  4638. {
  4639.     ngx_http_upstream_srv_conf_t  *uscf = conf;

  4640.     time_t                       fail_timeout;
  4641.     ngx_str_t                   *value, s;
  4642.     ngx_url_t                    u;
  4643.     ngx_int_t                    weight, max_conns, max_fails;
  4644.     ngx_uint_t                   i;
  4645. #if (NGX_HTTP_UPSTREAM_ZONE)
  4646.     ngx_uint_t                   resolve;
  4647. #endif
  4648.     ngx_http_upstream_server_t  *us;

  4649.     us = ngx_array_push(uscf->servers);
  4650.     if (us == NULL) {
  4651.         return NGX_CONF_ERROR;
  4652.     }

  4653.     ngx_memzero(us, sizeof(ngx_http_upstream_server_t));

  4654.     value = cf->args->elts;

  4655.     weight = 1;
  4656.     max_conns = 0;
  4657.     max_fails = 1;
  4658.     fail_timeout = 10;
  4659. #if (NGX_HTTP_UPSTREAM_ZONE)
  4660.     resolve = 0;
  4661. #endif

  4662.     for (i = 2; i < cf->args->nelts; i++) {

  4663.         if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {

  4664.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) {
  4665.                 goto not_supported;
  4666.             }

  4667.             weight = ngx_atoi(&value[i].data[7], value[i].len - 7);

  4668.             if (weight == NGX_ERROR || weight == 0) {
  4669.                 goto invalid;
  4670.             }

  4671.             continue;
  4672.         }

  4673.         if (ngx_strncmp(value[i].data, "max_conns=", 10) == 0) {

  4674.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_CONNS)) {
  4675.                 goto not_supported;
  4676.             }

  4677.             max_conns = ngx_atoi(&value[i].data[10], value[i].len - 10);

  4678.             if (max_conns == NGX_ERROR) {
  4679.                 goto invalid;
  4680.             }

  4681.             continue;
  4682.         }

  4683.         if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {

  4684.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
  4685.                 goto not_supported;
  4686.             }

  4687.             max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);

  4688.             if (max_fails == NGX_ERROR) {
  4689.                 goto invalid;
  4690.             }

  4691.             continue;
  4692.         }

  4693.         if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {

  4694.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) {
  4695.                 goto not_supported;
  4696.             }

  4697.             s.len = value[i].len - 13;
  4698.             s.data = &value[i].data[13];

  4699.             fail_timeout = ngx_parse_time(&s, 1);

  4700.             if (fail_timeout == (time_t) NGX_ERROR) {
  4701.                 goto invalid;
  4702.             }

  4703.             continue;
  4704.         }

  4705.         if (ngx_strcmp(value[i].data, "backup") == 0) {

  4706.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) {
  4707.                 goto not_supported;
  4708.             }

  4709.             us->backup = 1;

  4710.             continue;
  4711.         }

  4712.         if (ngx_strcmp(value[i].data, "down") == 0) {

  4713.             if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
  4714.                 goto not_supported;
  4715.             }

  4716.             us->down = 1;

  4717.             continue;
  4718.         }

  4719. #if (NGX_HTTP_UPSTREAM_ZONE)
  4720.         if (ngx_strcmp(value[i].data, "resolve") == 0) {
  4721.             resolve = 1;
  4722.             continue;
  4723.         }

  4724.         if (ngx_strncmp(value[i].data, "service=", 8) == 0) {

  4725.             us->service.len = value[i].len - 8;
  4726.             us->service.data = &value[i].data[8];

  4727.             if (us->service.len == 0) {
  4728.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "service is empty");
  4729.                 return NGX_CONF_ERROR;
  4730.             }

  4731.             continue;
  4732.         }
  4733. #endif

  4734.         goto invalid;
  4735.     }

  4736.     ngx_memzero(&u, sizeof(ngx_url_t));

  4737.     u.url = value[1];
  4738.     u.default_port = 80;

  4739. #if (NGX_HTTP_UPSTREAM_ZONE)
  4740.     if (resolve) {
  4741.         /* resolve at run time */
  4742.         u.no_resolve = 1;
  4743.     }

  4744.     if (us->service.len && !resolve) {
  4745.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4746.                            "service upstream \"%V\" requires "
  4747.                            "\"resolve\" parameter",
  4748.                            &u.url);
  4749.         return NGX_CONF_ERROR;
  4750.     }

  4751. #endif

  4752.     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  4753.         if (u.err) {
  4754.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4755.                                "%s in upstream \"%V\"", u.err, &u.url);
  4756.         }

  4757.         return NGX_CONF_ERROR;
  4758.     }

  4759.     us->name = u.url;

  4760. #if (NGX_HTTP_UPSTREAM_ZONE)

  4761.     if (us->service.len && !u.no_port) {
  4762.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4763.                            "service upstream \"%V\" may not have port",
  4764.                            &us->name);

  4765.         return NGX_CONF_ERROR;
  4766.     }

  4767.     if (us->service.len && u.naddrs) {
  4768.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4769.                            "service upstream \"%V\" requires domain name",
  4770.                            &us->name);

  4771.         return NGX_CONF_ERROR;
  4772.     }

  4773.     if (resolve && u.naddrs == 0) {
  4774.         ngx_addr_t  *addr;

  4775.         /* save port */

  4776.         addr = ngx_pcalloc(cf->pool, sizeof(ngx_addr_t));
  4777.         if (addr == NULL) {
  4778.             return NGX_CONF_ERROR;
  4779.         }

  4780.         addr->sockaddr = ngx_palloc(cf->pool, u.socklen);
  4781.         if (addr->sockaddr == NULL) {
  4782.             return NGX_CONF_ERROR;
  4783.         }

  4784.         ngx_memcpy(addr->sockaddr, &u.sockaddr, u.socklen);

  4785.         addr->socklen = u.socklen;

  4786.         us->addrs = addr;
  4787.         us->naddrs = 1;

  4788.         us->host = u.host;

  4789.     } else {
  4790.         us->addrs = u.addrs;
  4791.         us->naddrs = u.naddrs;
  4792.     }

  4793. #else

  4794.     us->addrs = u.addrs;
  4795.     us->naddrs = u.naddrs;

  4796. #endif

  4797.     us->weight = weight;
  4798.     us->max_conns = max_conns;
  4799.     us->max_fails = max_fails;
  4800.     us->fail_timeout = fail_timeout;

  4801.     return NGX_CONF_OK;

  4802. invalid:

  4803.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4804.                        "invalid parameter \"%V\"", &value[i]);

  4805.     return NGX_CONF_ERROR;

  4806. not_supported:

  4807.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4808.                        "balancing method does not support parameter \"%V\"",
  4809.                        &value[i]);

  4810.     return NGX_CONF_ERROR;
  4811. }


  4812. #if (NGX_HTTP_UPSTREAM_ZONE)

  4813. static char *
  4814. ngx_http_upstream_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  4815. {
  4816.     ngx_http_upstream_srv_conf_t  *uscf = conf;

  4817.     ngx_str_t  *value;

  4818.     if (uscf->resolver) {
  4819.         return "is duplicate";
  4820.     }

  4821.     value = cf->args->elts;

  4822.     uscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
  4823.     if (uscf->resolver == NULL) {
  4824.         return NGX_CONF_ERROR;
  4825.     }

  4826.     return NGX_CONF_OK;
  4827. }

  4828. #endif


  4829. ngx_http_upstream_srv_conf_t *
  4830. ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
  4831. {
  4832.     ngx_uint_t                      i;
  4833.     ngx_http_upstream_server_t     *us;
  4834.     ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
  4835.     ngx_http_upstream_main_conf_t  *umcf;

  4836.     if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {

  4837.         if (ngx_parse_url(cf->pool, u) != NGX_OK) {
  4838.             if (u->err) {
  4839.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4840.                                    "%s in upstream \"%V\"", u->err, &u->url);
  4841.             }

  4842.             return NULL;
  4843.         }
  4844.     }

  4845.     umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);

  4846.     uscfp = umcf->upstreams.elts;

  4847.     for (i = 0; i < umcf->upstreams.nelts; i++) {

  4848.         if (uscfp[i]->host.len != u->host.len
  4849.             || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
  4850.                != 0)
  4851.         {
  4852.             continue;
  4853.         }

  4854.         if ((flags & NGX_HTTP_UPSTREAM_CREATE)
  4855.              && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
  4856.         {
  4857.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4858.                                "duplicate upstream \"%V\"", &u->host);
  4859.             return NULL;
  4860.         }

  4861.         if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) {
  4862.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4863.                                "upstream \"%V\" may not have port %d",
  4864.                                &u->host, u->port);
  4865.             return NULL;
  4866.         }

  4867.         if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) {
  4868.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  4869.                           "upstream \"%V\" may not have port %d in %s:%ui",
  4870.                           &u->host, uscfp[i]->port,
  4871.                           uscfp[i]->file_name, uscfp[i]->line);
  4872.             return NULL;
  4873.         }

  4874.         if (uscfp[i]->port && u->port
  4875.             && uscfp[i]->port != u->port)
  4876.         {
  4877.             continue;
  4878.         }

  4879.         if (flags & NGX_HTTP_UPSTREAM_CREATE) {
  4880.             uscfp[i]->flags = flags;
  4881.             uscfp[i]->port = 0;
  4882.         }

  4883.         return uscfp[i];
  4884.     }

  4885.     uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
  4886.     if (uscf == NULL) {
  4887.         return NULL;
  4888.     }

  4889.     uscf->flags = flags;
  4890.     uscf->host = u->host;
  4891.     uscf->file_name = cf->conf_file->file.name.data;
  4892.     uscf->line = cf->conf_file->line;
  4893.     uscf->port = u->port;
  4894.     uscf->no_port = u->no_port;
  4895. #if (NGX_HTTP_UPSTREAM_ZONE)
  4896.     uscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
  4897. #endif

  4898.     if (u->naddrs == 1 && (u->port || u->family == AF_UNIX)) {
  4899.         uscf->servers = ngx_array_create(cf->pool, 1,
  4900.                                          sizeof(ngx_http_upstream_server_t));
  4901.         if (uscf->servers == NULL) {
  4902.             return NULL;
  4903.         }

  4904.         us = ngx_array_push(uscf->servers);
  4905.         if (us == NULL) {
  4906.             return NULL;
  4907.         }

  4908.         ngx_memzero(us, sizeof(ngx_http_upstream_server_t));

  4909.         us->addrs = u->addrs;
  4910.         us->naddrs = 1;
  4911.     }

  4912.     uscfp = ngx_array_push(&umcf->upstreams);
  4913.     if (uscfp == NULL) {
  4914.         return NULL;
  4915.     }

  4916.     *uscfp = uscf;

  4917.     return uscf;
  4918. }


  4919. char *
  4920. ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  4921.     void *conf)
  4922. {
  4923.     char  *p = conf;

  4924.     ngx_int_t                           rc;
  4925.     ngx_str_t                          *value;
  4926.     ngx_http_complex_value_t            cv;
  4927.     ngx_http_upstream_local_t         **plocal, *local;
  4928.     ngx_http_compile_complex_value_t    ccv;

  4929.     plocal = (ngx_http_upstream_local_t **) (p + cmd->offset);

  4930.     if (*plocal != NGX_CONF_UNSET_PTR) {
  4931.         return "is duplicate";
  4932.     }

  4933.     value = cf->args->elts;

  4934.     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) {
  4935.         *plocal = NULL;
  4936.         return NGX_CONF_OK;
  4937.     }

  4938.     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

  4939.     ccv.cf = cf;
  4940.     ccv.value = &value[1];
  4941.     ccv.complex_value = &cv;

  4942.     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  4943.         return NGX_CONF_ERROR;
  4944.     }

  4945.     local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
  4946.     if (local == NULL) {
  4947.         return NGX_CONF_ERROR;
  4948.     }

  4949.     *plocal = local;

  4950.     if (cv.lengths) {
  4951.         local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  4952.         if (local->value == NULL) {
  4953.             return NGX_CONF_ERROR;
  4954.         }

  4955.         *local->value = cv;

  4956.     } else {
  4957.         local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
  4958.         if (local->addr == NULL) {
  4959.             return NGX_CONF_ERROR;
  4960.         }

  4961.         rc = ngx_parse_addr_port(cf->pool, local->addr, value[1].data,
  4962.                                  value[1].len);

  4963.         switch (rc) {
  4964.         case NGX_OK:
  4965.             local->addr->name = value[1];
  4966.             break;

  4967.         case NGX_DECLINED:
  4968.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4969.                                "invalid address \"%V\"", &value[1]);
  4970.             /* fall through */

  4971.         default:
  4972.             return NGX_CONF_ERROR;
  4973.         }
  4974.     }

  4975.     if (cf->args->nelts > 2) {
  4976.         if (ngx_strcmp(value[2].data, "transparent") == 0) {
  4977. #if (NGX_HAVE_TRANSPARENT_PROXY)
  4978.             ngx_core_conf_t  *ccf;

  4979.             ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
  4980.                                                    ngx_core_module);

  4981.             ccf->transparent = 1;
  4982.             local->transparent = 1;
  4983. #else
  4984.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4985.                                "transparent proxying is not supported "
  4986.                                "on this platform, ignored");
  4987. #endif
  4988.         } else {
  4989.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  4990.                                "invalid parameter \"%V\"", &value[2]);
  4991.             return NGX_CONF_ERROR;
  4992.         }
  4993.     }

  4994.     return NGX_CONF_OK;
  4995. }


  4996. static ngx_int_t
  4997. ngx_http_upstream_set_local(ngx_http_request_t *r, ngx_http_upstream_t *u,
  4998.     ngx_http_upstream_local_t *local)
  4999. {
  5000.     ngx_int_t    rc;
  5001.     ngx_str_t    val;
  5002.     ngx_addr_t  *addr;

  5003.     if (local == NULL) {
  5004.         u->peer.local = NULL;
  5005.         return NGX_OK;
  5006.     }

  5007. #if (NGX_HAVE_TRANSPARENT_PROXY)
  5008.     u->peer.transparent = local->transparent;
  5009. #endif

  5010.     if (local->value == NULL) {
  5011.         u->peer.local = local->addr;
  5012.         return NGX_OK;
  5013.     }

  5014.     if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
  5015.         return NGX_ERROR;
  5016.     }

  5017.     if (val.len == 0) {
  5018.         return NGX_OK;
  5019.     }

  5020.     addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
  5021.     if (addr == NULL) {
  5022.         return NGX_ERROR;
  5023.     }

  5024.     rc = ngx_parse_addr_port(r->pool, addr, val.data, val.len);
  5025.     if (rc == NGX_ERROR) {
  5026.         return NGX_ERROR;
  5027.     }

  5028.     if (rc != NGX_OK) {
  5029.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  5030.                       "invalid local address \"%V\"", &val);
  5031.         return NGX_OK;
  5032.     }

  5033.     addr->name = val;
  5034.     u->peer.local = addr;

  5035.     return NGX_OK;
  5036. }


  5037. char *
  5038. ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  5039.     void *conf)
  5040. {
  5041.     char  *p = conf;

  5042.     ngx_str_t                   *value;
  5043.     ngx_array_t                **a;
  5044.     ngx_http_upstream_param_t   *param;

  5045.     a = (ngx_array_t **) (p + cmd->offset);

  5046.     if (*a == NULL) {
  5047.         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
  5048.         if (*a == NULL) {
  5049.             return NGX_CONF_ERROR;
  5050.         }
  5051.     }

  5052.     param = ngx_array_push(*a);
  5053.     if (param == NULL) {
  5054.         return NGX_CONF_ERROR;
  5055.     }

  5056.     value = cf->args->elts;

  5057.     param->key = value[1];
  5058.     param->value = value[2];
  5059.     param->skip_empty = 0;

  5060.     if (cf->args->nelts == 4) {
  5061.         if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
  5062.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  5063.                                "invalid parameter \"%V\"", &value[3]);
  5064.             return NGX_CONF_ERROR;
  5065.         }

  5066.         param->skip_empty = 1;
  5067.     }

  5068.     return NGX_CONF_OK;
  5069. }


  5070. ngx_int_t
  5071. ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
  5072.     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
  5073.     ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
  5074. {
  5075.     ngx_str_t       *h;
  5076.     ngx_uint_t       i, j;
  5077.     ngx_array_t      hide_headers;
  5078.     ngx_hash_key_t  *hk;

  5079.     if (conf->hide_headers == NGX_CONF_UNSET_PTR
  5080.         && conf->pass_headers == NGX_CONF_UNSET_PTR)
  5081.     {
  5082.         conf->hide_headers = prev->hide_headers;
  5083.         conf->pass_headers = prev->pass_headers;

  5084.         conf->hide_headers_hash = prev->hide_headers_hash;

  5085.         if (conf->hide_headers_hash.buckets) {
  5086.             return NGX_OK;
  5087.         }

  5088.     } else {
  5089.         if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
  5090.             conf->hide_headers = prev->hide_headers;
  5091.         }

  5092.         if (conf->pass_headers == NGX_CONF_UNSET_PTR) {
  5093.             conf->pass_headers = prev->pass_headers;
  5094.         }
  5095.     }

  5096.     if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
  5097.         != NGX_OK)
  5098.     {
  5099.         return NGX_ERROR;
  5100.     }

  5101.     for (h = default_hide_headers; h->len; h++) {
  5102.         hk = ngx_array_push(&hide_headers);
  5103.         if (hk == NULL) {
  5104.             return NGX_ERROR;
  5105.         }

  5106.         hk->key = *h;
  5107.         hk->key_hash = ngx_hash_key_lc(h->data, h->len);
  5108.         hk->value = (void *) 1;
  5109.     }

  5110.     if (conf->hide_headers != NGX_CONF_UNSET_PTR) {

  5111.         h = conf->hide_headers->elts;

  5112.         for (i = 0; i < conf->hide_headers->nelts; i++) {

  5113.             hk = hide_headers.elts;

  5114.             for (j = 0; j < hide_headers.nelts; j++) {
  5115.                 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
  5116.                     goto exist;
  5117.                 }
  5118.             }

  5119.             hk = ngx_array_push(&hide_headers);
  5120.             if (hk == NULL) {
  5121.                 return NGX_ERROR;
  5122.             }

  5123.             hk->key = h[i];
  5124.             hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
  5125.             hk->value = (void *) 1;

  5126.         exist:

  5127.             continue;
  5128.         }
  5129.     }

  5130.     if (conf->pass_headers != NGX_CONF_UNSET_PTR) {

  5131.         h = conf->pass_headers->elts;
  5132.         hk = hide_headers.elts;

  5133.         for (i = 0; i < conf->pass_headers->nelts; i++) {
  5134.             for (j = 0; j < hide_headers.nelts; j++) {

  5135.                 if (hk[j].key.data == NULL) {
  5136.                     continue;
  5137.                 }

  5138.                 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
  5139.                     hk[j].key.data = NULL;
  5140.                     break;
  5141.                 }
  5142.             }
  5143.         }
  5144.     }

  5145.     hash->hash = &conf->hide_headers_hash;
  5146.     hash->key = ngx_hash_key_lc;
  5147.     hash->pool = cf->pool;
  5148.     hash->temp_pool = NULL;

  5149.     if (ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
  5150.         return NGX_ERROR;
  5151.     }

  5152.     /*
  5153.      * special handling to preserve conf->hide_headers_hash
  5154.      * in the "http" section to inherit it to all servers
  5155.      */

  5156.     if (prev->hide_headers_hash.buckets == NULL
  5157.         && conf->hide_headers == prev->hide_headers
  5158.         && conf->pass_headers == prev->pass_headers)
  5159.     {
  5160.         prev->hide_headers_hash = conf->hide_headers_hash;
  5161.     }

  5162.     return NGX_OK;
  5163. }


  5164. static void *
  5165. ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
  5166. {
  5167.     ngx_http_upstream_main_conf_t  *umcf;

  5168.     umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
  5169.     if (umcf == NULL) {
  5170.         return NULL;
  5171.     }

  5172.     if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
  5173.                        sizeof(ngx_http_upstream_srv_conf_t *))
  5174.         != NGX_OK)
  5175.     {
  5176.         return NULL;
  5177.     }

  5178.     return umcf;
  5179. }


  5180. static char *
  5181. ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
  5182. {
  5183.     ngx_http_upstream_main_conf_t  *umcf = conf;

  5184.     ngx_uint_t                      i;
  5185.     ngx_array_t                     headers_in;
  5186.     ngx_hash_key_t                 *hk;
  5187.     ngx_hash_init_t                 hash;
  5188.     ngx_http_upstream_init_pt       init;
  5189.     ngx_http_upstream_header_t     *header;
  5190.     ngx_http_upstream_srv_conf_t  **uscfp;

  5191.     uscfp = umcf->upstreams.elts;

  5192.     for (i = 0; i < umcf->upstreams.nelts; i++) {

  5193.         init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
  5194.                                             ngx_http_upstream_init_round_robin;

  5195.         if (init(cf, uscfp[i]) != NGX_OK) {
  5196.             return NGX_CONF_ERROR;
  5197.         }
  5198.     }


  5199.     /* upstream_headers_in_hash */

  5200.     if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
  5201.         != NGX_OK)
  5202.     {
  5203.         return NGX_CONF_ERROR;
  5204.     }

  5205.     for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
  5206.         hk = ngx_array_push(&headers_in);
  5207.         if (hk == NULL) {
  5208.             return NGX_CONF_ERROR;
  5209.         }

  5210.         hk->key = header->name;
  5211.         hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
  5212.         hk->value = header;
  5213.     }

  5214.     hash.hash = &umcf->headers_in_hash;
  5215.     hash.key = ngx_hash_key_lc;
  5216.     hash.max_size = 512;
  5217.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  5218.     hash.name = "upstream_headers_in_hash";
  5219.     hash.pool = cf->pool;
  5220.     hash.temp_pool = NULL;

  5221.     if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
  5222.         return NGX_CONF_ERROR;
  5223.     }

  5224.     return NGX_CONF_OK;
  5225. }