Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 typedef struct {
0014     ngx_array_t                    caches;  /* ngx_http_file_cache_t * */
0015 } ngx_http_proxy_main_conf_t;
0016 
0017 
0018 typedef struct ngx_http_proxy_rewrite_s  ngx_http_proxy_rewrite_t;
0019 
0020 typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
0021     ngx_table_elt_t *h, size_t prefix, size_t len,
0022     ngx_http_proxy_rewrite_t *pr);
0023 
0024 struct ngx_http_proxy_rewrite_s {
0025     ngx_http_proxy_rewrite_pt      handler;
0026 
0027     union {
0028         ngx_http_complex_value_t   complex;
0029 #if (NGX_PCRE)
0030         ngx_http_regex_t          *regex;
0031 #endif
0032     } pattern;
0033 
0034     ngx_http_complex_value_t       replacement;
0035 };
0036 
0037 
0038 typedef struct {
0039     ngx_str_t                      key_start;
0040     ngx_str_t                      schema;
0041     ngx_str_t                      host_header;
0042     ngx_str_t                      port;
0043     ngx_str_t                      uri;
0044 } ngx_http_proxy_vars_t;
0045 
0046 
0047 typedef struct {
0048     ngx_array_t                   *flushes;
0049     ngx_array_t                   *lengths;
0050     ngx_array_t                   *values;
0051     ngx_hash_t                     hash;
0052 } ngx_http_proxy_headers_t;
0053 
0054 
0055 typedef struct {
0056     ngx_http_upstream_conf_t       upstream;
0057 
0058     ngx_array_t                   *body_flushes;
0059     ngx_array_t                   *body_lengths;
0060     ngx_array_t                   *body_values;
0061     ngx_str_t                      body_source;
0062 
0063     ngx_http_proxy_headers_t       headers;
0064 #if (NGX_HTTP_CACHE)
0065     ngx_http_proxy_headers_t       headers_cache;
0066 #endif
0067     ngx_array_t                   *headers_source;
0068 
0069     ngx_array_t                   *proxy_lengths;
0070     ngx_array_t                   *proxy_values;
0071 
0072     ngx_array_t                   *redirects;
0073     ngx_array_t                   *cookie_domains;
0074     ngx_array_t                   *cookie_paths;
0075 
0076     ngx_http_complex_value_t      *method;
0077     ngx_str_t                      location;
0078     ngx_str_t                      url;
0079 
0080 #if (NGX_HTTP_CACHE)
0081     ngx_http_complex_value_t       cache_key;
0082 #endif
0083 
0084     ngx_http_proxy_vars_t          vars;
0085 
0086     ngx_flag_t                     redirect;
0087 
0088     ngx_uint_t                     http_version;
0089 
0090     ngx_uint_t                     headers_hash_max_size;
0091     ngx_uint_t                     headers_hash_bucket_size;
0092 
0093 #if (NGX_HTTP_SSL)
0094     ngx_uint_t                     ssl;
0095     ngx_uint_t                     ssl_protocols;
0096     ngx_str_t                      ssl_ciphers;
0097     ngx_uint_t                     ssl_verify_depth;
0098     ngx_str_t                      ssl_trusted_certificate;
0099     ngx_str_t                      ssl_crl;
0100     ngx_str_t                      ssl_certificate;
0101     ngx_str_t                      ssl_certificate_key;
0102     ngx_array_t                   *ssl_passwords;
0103 #endif
0104 } ngx_http_proxy_loc_conf_t;
0105 
0106 
0107 typedef struct {
0108     ngx_http_status_t              status;
0109     ngx_http_chunked_t             chunked;
0110     ngx_http_proxy_vars_t          vars;
0111     off_t                          internal_body_length;
0112 
0113     ngx_chain_t                   *free;
0114     ngx_chain_t                   *busy;
0115 
0116     unsigned                       head:1;
0117     unsigned                       internal_chunked:1;
0118     unsigned                       header_sent:1;
0119 } ngx_http_proxy_ctx_t;
0120 
0121 
0122 static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
0123     ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
0124 #if (NGX_HTTP_CACHE)
0125 static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
0126 #endif
0127 static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
0128 static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
0129 static ngx_int_t ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in);
0130 static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
0131 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
0132 static ngx_int_t ngx_http_proxy_input_filter_init(void *data);
0133 static ngx_int_t ngx_http_proxy_copy_filter(ngx_event_pipe_t *p,
0134     ngx_buf_t *buf);
0135 static ngx_int_t ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p,
0136     ngx_buf_t *buf);
0137 static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
0138     ssize_t bytes);
0139 static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
0140     ssize_t bytes);
0141 static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
0142 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
0143     ngx_int_t rc);
0144 
0145 static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
0146     ngx_http_variable_value_t *v, uintptr_t data);
0147 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
0148     ngx_http_variable_value_t *v, uintptr_t data);
0149 static ngx_int_t
0150     ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
0151     ngx_http_variable_value_t *v, uintptr_t data);
0152 static ngx_int_t
0153     ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
0154     ngx_http_variable_value_t *v, uintptr_t data);
0155 static ngx_int_t ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
0156     ngx_http_variable_value_t *v, uintptr_t data);
0157 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
0158     ngx_table_elt_t *h, size_t prefix);
0159 static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
0160     ngx_table_elt_t *h);
0161 static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
0162     ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
0163 static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
0164     ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
0165 
0166 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
0167 static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf);
0168 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
0169 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
0170     void *parent, void *child);
0171 static ngx_int_t ngx_http_proxy_init_headers(ngx_conf_t *cf,
0172     ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_headers_t *headers,
0173     ngx_keyval_t *default_headers);
0174 
0175 static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
0176     void *conf);
0177 static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
0178     void *conf);
0179 static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
0180     void *conf);
0181 static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
0182     void *conf);
0183 static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
0184     void *conf);
0185 #if (NGX_HTTP_CACHE)
0186 static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
0187     void *conf);
0188 static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
0189     void *conf);
0190 #endif
0191 #if (NGX_HTTP_SSL)
0192 static char *ngx_http_proxy_ssl_password_file(ngx_conf_t *cf,
0193     ngx_command_t *cmd, void *conf);
0194 #endif
0195 
0196 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
0197 
0198 static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
0199     ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
0200 
0201 #if (NGX_HTTP_SSL)
0202 static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
0203     ngx_http_proxy_loc_conf_t *plcf);
0204 #endif
0205 static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
0206 
0207 
0208 static ngx_conf_post_t  ngx_http_proxy_lowat_post =
0209     { ngx_http_proxy_lowat_check };
0210 
0211 
0212 static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
0213     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
0214     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
0215     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
0216     { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
0217     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
0218     { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
0219     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
0220     { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
0221     { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
0222     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
0223     { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
0224     { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
0225     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
0226     { ngx_null_string, 0 }
0227 };
0228 
0229 
0230 #if (NGX_HTTP_SSL)
0231 
0232 static ngx_conf_bitmask_t  ngx_http_proxy_ssl_protocols[] = {
0233     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
0234     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
0235     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
0236     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
0237     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
0238     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
0239     { ngx_null_string, 0 }
0240 };
0241 
0242 #endif
0243 
0244 
0245 static ngx_conf_enum_t  ngx_http_proxy_http_version[] = {
0246     { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
0247     { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
0248     { ngx_null_string, 0 }
0249 };
0250 
0251 
0252 ngx_module_t  ngx_http_proxy_module;
0253 
0254 
0255 static ngx_command_t  ngx_http_proxy_commands[] = {
0256 
0257     { ngx_string("proxy_pass"),
0258       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
0259       ngx_http_proxy_pass,
0260       NGX_HTTP_LOC_CONF_OFFSET,
0261       0,
0262       NULL },
0263 
0264     { ngx_string("proxy_redirect"),
0265       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
0266       ngx_http_proxy_redirect,
0267       NGX_HTTP_LOC_CONF_OFFSET,
0268       0,
0269       NULL },
0270 
0271     { ngx_string("proxy_cookie_domain"),
0272       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
0273       ngx_http_proxy_cookie_domain,
0274       NGX_HTTP_LOC_CONF_OFFSET,
0275       0,
0276       NULL },
0277 
0278     { ngx_string("proxy_cookie_path"),
0279       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
0280       ngx_http_proxy_cookie_path,
0281       NGX_HTTP_LOC_CONF_OFFSET,
0282       0,
0283       NULL },
0284 
0285     { ngx_string("proxy_store"),
0286       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0287       ngx_http_proxy_store,
0288       NGX_HTTP_LOC_CONF_OFFSET,
0289       0,
0290       NULL },
0291 
0292     { ngx_string("proxy_store_access"),
0293       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
0294       ngx_conf_set_access_slot,
0295       NGX_HTTP_LOC_CONF_OFFSET,
0296       offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access),
0297       NULL },
0298 
0299     { ngx_string("proxy_buffering"),
0300       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0301       ngx_conf_set_flag_slot,
0302       NGX_HTTP_LOC_CONF_OFFSET,
0303       offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
0304       NULL },
0305 
0306     { ngx_string("proxy_request_buffering"),
0307       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0308       ngx_conf_set_flag_slot,
0309       NGX_HTTP_LOC_CONF_OFFSET,
0310       offsetof(ngx_http_proxy_loc_conf_t, upstream.request_buffering),
0311       NULL },
0312 
0313     { ngx_string("proxy_ignore_client_abort"),
0314       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0315       ngx_conf_set_flag_slot,
0316       NGX_HTTP_LOC_CONF_OFFSET,
0317       offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
0318       NULL },
0319 
0320     { ngx_string("proxy_bind"),
0321       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
0322       ngx_http_upstream_bind_set_slot,
0323       NGX_HTTP_LOC_CONF_OFFSET,
0324       offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
0325       NULL },
0326 
0327     { ngx_string("proxy_socket_keepalive"),
0328       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0329       ngx_conf_set_flag_slot,
0330       NGX_HTTP_LOC_CONF_OFFSET,
0331       offsetof(ngx_http_proxy_loc_conf_t, upstream.socket_keepalive),
0332       NULL },
0333 
0334     { ngx_string("proxy_connect_timeout"),
0335       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0336       ngx_conf_set_msec_slot,
0337       NGX_HTTP_LOC_CONF_OFFSET,
0338       offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
0339       NULL },
0340 
0341     { ngx_string("proxy_send_timeout"),
0342       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0343       ngx_conf_set_msec_slot,
0344       NGX_HTTP_LOC_CONF_OFFSET,
0345       offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
0346       NULL },
0347 
0348     { ngx_string("proxy_send_lowat"),
0349       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0350       ngx_conf_set_size_slot,
0351       NGX_HTTP_LOC_CONF_OFFSET,
0352       offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
0353       &ngx_http_proxy_lowat_post },
0354 
0355     { ngx_string("proxy_intercept_errors"),
0356       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0357       ngx_conf_set_flag_slot,
0358       NGX_HTTP_LOC_CONF_OFFSET,
0359       offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors),
0360       NULL },
0361 
0362     { ngx_string("proxy_set_header"),
0363       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
0364       ngx_conf_set_keyval_slot,
0365       NGX_HTTP_LOC_CONF_OFFSET,
0366       offsetof(ngx_http_proxy_loc_conf_t, headers_source),
0367       NULL },
0368 
0369     { ngx_string("proxy_headers_hash_max_size"),
0370       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0371       ngx_conf_set_num_slot,
0372       NGX_HTTP_LOC_CONF_OFFSET,
0373       offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size),
0374       NULL },
0375 
0376     { ngx_string("proxy_headers_hash_bucket_size"),
0377       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0378       ngx_conf_set_num_slot,
0379       NGX_HTTP_LOC_CONF_OFFSET,
0380       offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size),
0381       NULL },
0382 
0383     { ngx_string("proxy_set_body"),
0384       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0385       ngx_conf_set_str_slot,
0386       NGX_HTTP_LOC_CONF_OFFSET,
0387       offsetof(ngx_http_proxy_loc_conf_t, body_source),
0388       NULL },
0389 
0390     { ngx_string("proxy_method"),
0391       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0392       ngx_http_set_complex_value_slot,
0393       NGX_HTTP_LOC_CONF_OFFSET,
0394       offsetof(ngx_http_proxy_loc_conf_t, method),
0395       NULL },
0396 
0397     { ngx_string("proxy_pass_request_headers"),
0398       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0399       ngx_conf_set_flag_slot,
0400       NGX_HTTP_LOC_CONF_OFFSET,
0401       offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
0402       NULL },
0403 
0404     { ngx_string("proxy_pass_request_body"),
0405       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0406       ngx_conf_set_flag_slot,
0407       NGX_HTTP_LOC_CONF_OFFSET,
0408       offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
0409       NULL },
0410 
0411     { ngx_string("proxy_buffer_size"),
0412       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0413       ngx_conf_set_size_slot,
0414       NGX_HTTP_LOC_CONF_OFFSET,
0415       offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size),
0416       NULL },
0417 
0418     { ngx_string("proxy_read_timeout"),
0419       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0420       ngx_conf_set_msec_slot,
0421       NGX_HTTP_LOC_CONF_OFFSET,
0422       offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
0423       NULL },
0424 
0425     { ngx_string("proxy_buffers"),
0426       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
0427       ngx_conf_set_bufs_slot,
0428       NGX_HTTP_LOC_CONF_OFFSET,
0429       offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
0430       NULL },
0431 
0432     { ngx_string("proxy_busy_buffers_size"),
0433       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0434       ngx_conf_set_size_slot,
0435       NGX_HTTP_LOC_CONF_OFFSET,
0436       offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
0437       NULL },
0438 
0439     { ngx_string("proxy_force_ranges"),
0440       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0441       ngx_conf_set_flag_slot,
0442       NGX_HTTP_LOC_CONF_OFFSET,
0443       offsetof(ngx_http_proxy_loc_conf_t, upstream.force_ranges),
0444       NULL },
0445 
0446     { ngx_string("proxy_limit_rate"),
0447       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0448       ngx_conf_set_size_slot,
0449       NGX_HTTP_LOC_CONF_OFFSET,
0450       offsetof(ngx_http_proxy_loc_conf_t, upstream.limit_rate),
0451       NULL },
0452 
0453 #if (NGX_HTTP_CACHE)
0454 
0455     { ngx_string("proxy_cache"),
0456       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0457       ngx_http_proxy_cache,
0458       NGX_HTTP_LOC_CONF_OFFSET,
0459       0,
0460       NULL },
0461 
0462     { ngx_string("proxy_cache_key"),
0463       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0464       ngx_http_proxy_cache_key,
0465       NGX_HTTP_LOC_CONF_OFFSET,
0466       0,
0467       NULL },
0468 
0469     { ngx_string("proxy_cache_path"),
0470       NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
0471       ngx_http_file_cache_set_slot,
0472       NGX_HTTP_MAIN_CONF_OFFSET,
0473       offsetof(ngx_http_proxy_main_conf_t, caches),
0474       &ngx_http_proxy_module },
0475 
0476     { ngx_string("proxy_cache_bypass"),
0477       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0478       ngx_http_set_predicate_slot,
0479       NGX_HTTP_LOC_CONF_OFFSET,
0480       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
0481       NULL },
0482 
0483     { ngx_string("proxy_no_cache"),
0484       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0485       ngx_http_set_predicate_slot,
0486       NGX_HTTP_LOC_CONF_OFFSET,
0487       offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
0488       NULL },
0489 
0490     { ngx_string("proxy_cache_valid"),
0491       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0492       ngx_http_file_cache_valid_set_slot,
0493       NGX_HTTP_LOC_CONF_OFFSET,
0494       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
0495       NULL },
0496 
0497     { ngx_string("proxy_cache_min_uses"),
0498       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0499       ngx_conf_set_num_slot,
0500       NGX_HTTP_LOC_CONF_OFFSET,
0501       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
0502       NULL },
0503 
0504     { ngx_string("proxy_cache_max_range_offset"),
0505       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0506       ngx_conf_set_off_slot,
0507       NGX_HTTP_LOC_CONF_OFFSET,
0508       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_max_range_offset),
0509       NULL },
0510 
0511     { ngx_string("proxy_cache_use_stale"),
0512       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0513       ngx_conf_set_bitmask_slot,
0514       NGX_HTTP_LOC_CONF_OFFSET,
0515       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
0516       &ngx_http_proxy_next_upstream_masks },
0517 
0518     { ngx_string("proxy_cache_methods"),
0519       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0520       ngx_conf_set_bitmask_slot,
0521       NGX_HTTP_LOC_CONF_OFFSET,
0522       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
0523       &ngx_http_upstream_cache_method_mask },
0524 
0525     { ngx_string("proxy_cache_lock"),
0526       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0527       ngx_conf_set_flag_slot,
0528       NGX_HTTP_LOC_CONF_OFFSET,
0529       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
0530       NULL },
0531 
0532     { ngx_string("proxy_cache_lock_timeout"),
0533       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0534       ngx_conf_set_msec_slot,
0535       NGX_HTTP_LOC_CONF_OFFSET,
0536       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
0537       NULL },
0538 
0539     { ngx_string("proxy_cache_lock_age"),
0540       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0541       ngx_conf_set_msec_slot,
0542       NGX_HTTP_LOC_CONF_OFFSET,
0543       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_age),
0544       NULL },
0545 
0546     { ngx_string("proxy_cache_revalidate"),
0547       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0548       ngx_conf_set_flag_slot,
0549       NGX_HTTP_LOC_CONF_OFFSET,
0550       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_revalidate),
0551       NULL },
0552 
0553     { ngx_string("proxy_cache_convert_head"),
0554       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0555       ngx_conf_set_flag_slot,
0556       NGX_HTTP_LOC_CONF_OFFSET,
0557       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_convert_head),
0558       NULL },
0559 
0560     { ngx_string("proxy_cache_background_update"),
0561       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0562       ngx_conf_set_flag_slot,
0563       NGX_HTTP_LOC_CONF_OFFSET,
0564       offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_background_update),
0565       NULL },
0566 
0567 #endif
0568 
0569     { ngx_string("proxy_temp_path"),
0570       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
0571       ngx_conf_set_path_slot,
0572       NGX_HTTP_LOC_CONF_OFFSET,
0573       offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
0574       NULL },
0575 
0576     { ngx_string("proxy_max_temp_file_size"),
0577       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0578       ngx_conf_set_size_slot,
0579       NGX_HTTP_LOC_CONF_OFFSET,
0580       offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf),
0581       NULL },
0582 
0583     { ngx_string("proxy_temp_file_write_size"),
0584       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0585       ngx_conf_set_size_slot,
0586       NGX_HTTP_LOC_CONF_OFFSET,
0587       offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf),
0588       NULL },
0589 
0590     { ngx_string("proxy_next_upstream"),
0591       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0592       ngx_conf_set_bitmask_slot,
0593       NGX_HTTP_LOC_CONF_OFFSET,
0594       offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
0595       &ngx_http_proxy_next_upstream_masks },
0596 
0597     { ngx_string("proxy_next_upstream_tries"),
0598       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0599       ngx_conf_set_num_slot,
0600       NGX_HTTP_LOC_CONF_OFFSET,
0601       offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_tries),
0602       NULL },
0603 
0604     { ngx_string("proxy_next_upstream_timeout"),
0605       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0606       ngx_conf_set_msec_slot,
0607       NGX_HTTP_LOC_CONF_OFFSET,
0608       offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout),
0609       NULL },
0610 
0611     { ngx_string("proxy_pass_header"),
0612       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0613       ngx_conf_set_str_array_slot,
0614       NGX_HTTP_LOC_CONF_OFFSET,
0615       offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
0616       NULL },
0617 
0618     { ngx_string("proxy_hide_header"),
0619       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0620       ngx_conf_set_str_array_slot,
0621       NGX_HTTP_LOC_CONF_OFFSET,
0622       offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
0623       NULL },
0624 
0625     { ngx_string("proxy_ignore_headers"),
0626       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0627       ngx_conf_set_bitmask_slot,
0628       NGX_HTTP_LOC_CONF_OFFSET,
0629       offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
0630       &ngx_http_upstream_ignore_headers_masks },
0631 
0632     { ngx_string("proxy_http_version"),
0633       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0634       ngx_conf_set_enum_slot,
0635       NGX_HTTP_LOC_CONF_OFFSET,
0636       offsetof(ngx_http_proxy_loc_conf_t, http_version),
0637       &ngx_http_proxy_http_version },
0638 
0639 #if (NGX_HTTP_SSL)
0640 
0641     { ngx_string("proxy_ssl_session_reuse"),
0642       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0643       ngx_conf_set_flag_slot,
0644       NGX_HTTP_LOC_CONF_OFFSET,
0645       offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
0646       NULL },
0647 
0648     { ngx_string("proxy_ssl_protocols"),
0649       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0650       ngx_conf_set_bitmask_slot,
0651       NGX_HTTP_LOC_CONF_OFFSET,
0652       offsetof(ngx_http_proxy_loc_conf_t, ssl_protocols),
0653       &ngx_http_proxy_ssl_protocols },
0654 
0655     { ngx_string("proxy_ssl_ciphers"),
0656       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0657       ngx_conf_set_str_slot,
0658       NGX_HTTP_LOC_CONF_OFFSET,
0659       offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers),
0660       NULL },
0661 
0662     { ngx_string("proxy_ssl_name"),
0663       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0664       ngx_http_set_complex_value_slot,
0665       NGX_HTTP_LOC_CONF_OFFSET,
0666       offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_name),
0667       NULL },
0668 
0669     { ngx_string("proxy_ssl_server_name"),
0670       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0671       ngx_conf_set_flag_slot,
0672       NGX_HTTP_LOC_CONF_OFFSET,
0673       offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_server_name),
0674       NULL },
0675 
0676     { ngx_string("proxy_ssl_verify"),
0677       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0678       ngx_conf_set_flag_slot,
0679       NGX_HTTP_LOC_CONF_OFFSET,
0680       offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify),
0681       NULL },
0682 
0683     { ngx_string("proxy_ssl_verify_depth"),
0684       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0685       ngx_conf_set_num_slot,
0686       NGX_HTTP_LOC_CONF_OFFSET,
0687       offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth),
0688       NULL },
0689 
0690     { ngx_string("proxy_ssl_trusted_certificate"),
0691       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0692       ngx_conf_set_str_slot,
0693       NGX_HTTP_LOC_CONF_OFFSET,
0694       offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate),
0695       NULL },
0696 
0697     { ngx_string("proxy_ssl_crl"),
0698       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0699       ngx_conf_set_str_slot,
0700       NGX_HTTP_LOC_CONF_OFFSET,
0701       offsetof(ngx_http_proxy_loc_conf_t, ssl_crl),
0702       NULL },
0703 
0704     { ngx_string("proxy_ssl_certificate"),
0705       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0706       ngx_conf_set_str_slot,
0707       NGX_HTTP_LOC_CONF_OFFSET,
0708       offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
0709       NULL },
0710 
0711     { ngx_string("proxy_ssl_certificate_key"),
0712       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0713       ngx_conf_set_str_slot,
0714       NGX_HTTP_LOC_CONF_OFFSET,
0715       offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
0716       NULL },
0717 
0718     { ngx_string("proxy_ssl_password_file"),
0719       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0720       ngx_http_proxy_ssl_password_file,
0721       NGX_HTTP_LOC_CONF_OFFSET,
0722       0,
0723       NULL },
0724 
0725 #endif
0726 
0727       ngx_null_command
0728 };
0729 
0730 
0731 static ngx_http_module_t  ngx_http_proxy_module_ctx = {
0732     ngx_http_proxy_add_variables,          /* preconfiguration */
0733     NULL,                                  /* postconfiguration */
0734 
0735     ngx_http_proxy_create_main_conf,       /* create main configuration */
0736     NULL,                                  /* init main configuration */
0737 
0738     NULL,                                  /* create server configuration */
0739     NULL,                                  /* merge server configuration */
0740 
0741     ngx_http_proxy_create_loc_conf,        /* create location configuration */
0742     ngx_http_proxy_merge_loc_conf          /* merge location configuration */
0743 };
0744 
0745 
0746 ngx_module_t  ngx_http_proxy_module = {
0747     NGX_MODULE_V1,
0748     &ngx_http_proxy_module_ctx,            /* module context */
0749     ngx_http_proxy_commands,               /* module directives */
0750     NGX_HTTP_MODULE,                       /* module type */
0751     NULL,                                  /* init master */
0752     NULL,                                  /* init module */
0753     NULL,                                  /* init process */
0754     NULL,                                  /* init thread */
0755     NULL,                                  /* exit thread */
0756     NULL,                                  /* exit process */
0757     NULL,                                  /* exit master */
0758     NGX_MODULE_V1_PADDING
0759 };
0760 
0761 
0762 static char  ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
0763 static char  ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
0764 
0765 
0766 static ngx_keyval_t  ngx_http_proxy_headers[] = {
0767     { ngx_string("Host"), ngx_string("$proxy_host") },
0768     { ngx_string("Connection"), ngx_string("close") },
0769     { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
0770     { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
0771     { ngx_string("TE"), ngx_string("") },
0772     { ngx_string("Keep-Alive"), ngx_string("") },
0773     { ngx_string("Expect"), ngx_string("") },
0774     { ngx_string("Upgrade"), ngx_string("") },
0775     { ngx_null_string, ngx_null_string }
0776 };
0777 
0778 
0779 static ngx_str_t  ngx_http_proxy_hide_headers[] = {
0780     ngx_string("Date"),
0781     ngx_string("Server"),
0782     ngx_string("X-Pad"),
0783     ngx_string("X-Accel-Expires"),
0784     ngx_string("X-Accel-Redirect"),
0785     ngx_string("X-Accel-Limit-Rate"),
0786     ngx_string("X-Accel-Buffering"),
0787     ngx_string("X-Accel-Charset"),
0788     ngx_null_string
0789 };
0790 
0791 
0792 #if (NGX_HTTP_CACHE)
0793 
0794 static ngx_keyval_t  ngx_http_proxy_cache_headers[] = {
0795     { ngx_string("Host"), ngx_string("$proxy_host") },
0796     { ngx_string("Connection"), ngx_string("close") },
0797     { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
0798     { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
0799     { ngx_string("TE"), ngx_string("") },
0800     { ngx_string("Keep-Alive"), ngx_string("") },
0801     { ngx_string("Expect"), ngx_string("") },
0802     { ngx_string("Upgrade"), ngx_string("") },
0803     { ngx_string("If-Modified-Since"),
0804       ngx_string("$upstream_cache_last_modified") },
0805     { ngx_string("If-Unmodified-Since"), ngx_string("") },
0806     { ngx_string("If-None-Match"), ngx_string("$upstream_cache_etag") },
0807     { ngx_string("If-Match"), ngx_string("") },
0808     { ngx_string("Range"), ngx_string("") },
0809     { ngx_string("If-Range"), ngx_string("") },
0810     { ngx_null_string, ngx_null_string }
0811 };
0812 
0813 #endif
0814 
0815 
0816 static ngx_http_variable_t  ngx_http_proxy_vars[] = {
0817 
0818     { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
0819       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
0820 
0821     { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
0822       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
0823 
0824     { ngx_string("proxy_add_x_forwarded_for"), NULL,
0825       ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
0826 
0827 #if 0
0828     { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
0829 #endif
0830 
0831     { ngx_string("proxy_internal_body_length"), NULL,
0832       ngx_http_proxy_internal_body_length_variable, 0,
0833       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
0834 
0835     { ngx_string("proxy_internal_chunked"), NULL,
0836       ngx_http_proxy_internal_chunked_variable, 0,
0837       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
0838 
0839       ngx_http_null_variable
0840 };
0841 
0842 
0843 static ngx_path_init_t  ngx_http_proxy_temp_path = {
0844     ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
0845 };
0846 
0847 
0848 static ngx_int_t
0849 ngx_http_proxy_handler(ngx_http_request_t *r)
0850 {
0851     ngx_int_t                    rc;
0852     ngx_http_upstream_t         *u;
0853     ngx_http_proxy_ctx_t        *ctx;
0854     ngx_http_proxy_loc_conf_t   *plcf;
0855 #if (NGX_HTTP_CACHE)
0856     ngx_http_proxy_main_conf_t  *pmcf;
0857 #endif
0858 
0859     if (ngx_http_upstream_create(r) != NGX_OK) {
0860         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0861     }
0862 
0863     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
0864     if (ctx == NULL) {
0865         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0866     }
0867 
0868     ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
0869 
0870     plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
0871 
0872     u = r->upstream;
0873 
0874     if (plcf->proxy_lengths == NULL) {
0875         ctx->vars = plcf->vars;
0876         u->schema = plcf->vars.schema;
0877 #if (NGX_HTTP_SSL)
0878         u->ssl = (plcf->upstream.ssl != NULL);
0879 #endif
0880 
0881     } else {
0882         if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
0883             return NGX_HTTP_INTERNAL_SERVER_ERROR;
0884         }
0885     }
0886 
0887     u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
0888 
0889     u->conf = &plcf->upstream;
0890 
0891 #if (NGX_HTTP_CACHE)
0892     pmcf = ngx_http_get_module_main_conf(r, ngx_http_proxy_module);
0893 
0894     u->caches = &pmcf->caches;
0895     u->create_key = ngx_http_proxy_create_key;
0896 #endif
0897 
0898     u->create_request = ngx_http_proxy_create_request;
0899     u->reinit_request = ngx_http_proxy_reinit_request;
0900     u->process_header = ngx_http_proxy_process_status_line;
0901     u->abort_request = ngx_http_proxy_abort_request;
0902     u->finalize_request = ngx_http_proxy_finalize_request;
0903     r->state = 0;
0904 
0905     if (plcf->redirects) {
0906         u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
0907     }
0908 
0909     if (plcf->cookie_domains || plcf->cookie_paths) {
0910         u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
0911     }
0912 
0913     u->buffering = plcf->upstream.buffering;
0914 
0915     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
0916     if (u->pipe == NULL) {
0917         return NGX_HTTP_INTERNAL_SERVER_ERROR;
0918     }
0919 
0920     u->pipe->input_filter = ngx_http_proxy_copy_filter;
0921     u->pipe->input_ctx = r;
0922 
0923     u->input_filter_init = ngx_http_proxy_input_filter_init;
0924     u->input_filter = ngx_http_proxy_non_buffered_copy_filter;
0925     u->input_filter_ctx = r;
0926 
0927     u->accel = 1;
0928 
0929     if (!plcf->upstream.request_buffering
0930         && plcf->body_values == NULL && plcf->upstream.pass_request_body
0931         && (!r->headers_in.chunked
0932             || plcf->http_version == NGX_HTTP_VERSION_11))
0933     {
0934         r->request_body_no_buffering = 1;
0935     }
0936 
0937     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
0938 
0939     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
0940         return rc;
0941     }
0942 
0943     return NGX_DONE;
0944 }
0945 
0946 
0947 static ngx_int_t
0948 ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
0949     ngx_http_proxy_loc_conf_t *plcf)
0950 {
0951     u_char               *p;
0952     size_t                add;
0953     u_short               port;
0954     ngx_str_t             proxy;
0955     ngx_url_t             url;
0956     ngx_http_upstream_t  *u;
0957 
0958     if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
0959                             plcf->proxy_values->elts)
0960         == NULL)
0961     {
0962         return NGX_ERROR;
0963     }
0964 
0965     if (proxy.len > 7
0966         && ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0)
0967     {
0968         add = 7;
0969         port = 80;
0970 
0971 #if (NGX_HTTP_SSL)
0972 
0973     } else if (proxy.len > 8
0974                && ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0)
0975     {
0976         add = 8;
0977         port = 443;
0978         r->upstream->ssl = 1;
0979 
0980 #endif
0981 
0982     } else {
0983         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
0984                       "invalid URL prefix in \"%V\"", &proxy);
0985         return NGX_ERROR;
0986     }
0987 
0988     u = r->upstream;
0989 
0990     u->schema.len = add;
0991     u->schema.data = proxy.data;
0992 
0993     ngx_memzero(&url, sizeof(ngx_url_t));
0994 
0995     url.url.len = proxy.len - add;
0996     url.url.data = proxy.data + add;
0997     url.default_port = port;
0998     url.uri_part = 1;
0999     url.no_resolve = 1;
1000 
1001     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
1002         if (url.err) {
1003             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1004                           "%s in upstream \"%V\"", url.err, &url.url);
1005         }
1006 
1007         return NGX_ERROR;
1008     }
1009 
1010     if (url.uri.len) {
1011         if (url.uri.data[0] == '?') {
1012             p = ngx_pnalloc(r->pool, url.uri.len + 1);
1013             if (p == NULL) {
1014                 return NGX_ERROR;
1015             }
1016 
1017             *p++ = '/';
1018             ngx_memcpy(p, url.uri.data, url.uri.len);
1019 
1020             url.uri.len++;
1021             url.uri.data = p - 1;
1022         }
1023     }
1024 
1025     ctx->vars.key_start = u->schema;
1026 
1027     ngx_http_proxy_set_vars(&url, &ctx->vars);
1028 
1029     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
1030     if (u->resolved == NULL) {
1031         return NGX_ERROR;
1032     }
1033 
1034     if (url.addrs) {
1035         u->resolved->sockaddr = url.addrs[0].sockaddr;
1036         u->resolved->socklen = url.addrs[0].socklen;
1037         u->resolved->name = url.addrs[0].name;
1038         u->resolved->naddrs = 1;
1039     }
1040 
1041     u->resolved->host = url.host;
1042     u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
1043     u->resolved->no_port = url.no_port;
1044 
1045     return NGX_OK;
1046 }
1047 
1048 
1049 #if (NGX_HTTP_CACHE)
1050 
1051 static ngx_int_t
1052 ngx_http_proxy_create_key(ngx_http_request_t *r)
1053 {
1054     size_t                      len, loc_len;
1055     u_char                     *p;
1056     uintptr_t                   escape;
1057     ngx_str_t                  *key;
1058     ngx_http_upstream_t        *u;
1059     ngx_http_proxy_ctx_t       *ctx;
1060     ngx_http_proxy_loc_conf_t  *plcf;
1061 
1062     u = r->upstream;
1063 
1064     plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1065 
1066     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1067 
1068     key = ngx_array_push(&r->cache->keys);
1069     if (key == NULL) {
1070         return NGX_ERROR;
1071     }
1072 
1073     if (plcf->cache_key.value.data) {
1074 
1075         if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
1076             return NGX_ERROR;
1077         }
1078 
1079         return NGX_OK;
1080     }
1081 
1082     *key = ctx->vars.key_start;
1083 
1084     key = ngx_array_push(&r->cache->keys);
1085     if (key == NULL) {
1086         return NGX_ERROR;
1087     }
1088 
1089     if (plcf->proxy_lengths && ctx->vars.uri.len) {
1090 
1091         *key = ctx->vars.uri;
1092         u->uri = ctx->vars.uri;
1093 
1094         return NGX_OK;
1095 
1096     } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri) {
1097         *key = r->unparsed_uri;
1098         u->uri = r->unparsed_uri;
1099 
1100         return NGX_OK;
1101     }
1102 
1103     loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
1104 
1105     if (r->quoted_uri || r->space_in_uri || r->internal) {
1106         escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
1107                                     r->uri.len - loc_len, NGX_ESCAPE_URI);
1108     } else {
1109         escape = 0;
1110     }
1111 
1112     len = ctx->vars.uri.len + r->uri.len - loc_len + escape
1113           + sizeof("?") - 1 + r->args.len;
1114 
1115     p = ngx_pnalloc(r->pool, len);
1116     if (p == NULL) {
1117         return NGX_ERROR;
1118     }
1119 
1120     key->data = p;
1121 
1122     if (r->valid_location) {
1123         p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
1124     }
1125 
1126     if (escape) {
1127         ngx_escape_uri(p, r->uri.data + loc_len,
1128                        r->uri.len - loc_len, NGX_ESCAPE_URI);
1129         p += r->uri.len - loc_len + escape;
1130 
1131     } else {
1132         p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
1133     }
1134 
1135     if (r->args.len > 0) {
1136         *p++ = '?';
1137         p = ngx_copy(p, r->args.data, r->args.len);
1138     }
1139 
1140     key->len = p - key->data;
1141     u->uri = *key;
1142 
1143     return NGX_OK;
1144 }
1145 
1146 #endif
1147 
1148 
1149 static ngx_int_t
1150 ngx_http_proxy_create_request(ngx_http_request_t *r)
1151 {
1152     size_t                        len, uri_len, loc_len, body_len,
1153                                   key_len, val_len;
1154     uintptr_t                     escape;
1155     ngx_buf_t                    *b;
1156     ngx_str_t                     method;
1157     ngx_uint_t                    i, unparsed_uri;
1158     ngx_chain_t                  *cl, *body;
1159     ngx_list_part_t              *part;
1160     ngx_table_elt_t              *header;
1161     ngx_http_upstream_t          *u;
1162     ngx_http_proxy_ctx_t         *ctx;
1163     ngx_http_script_code_pt       code;
1164     ngx_http_proxy_headers_t     *headers;
1165     ngx_http_script_engine_t      e, le;
1166     ngx_http_proxy_loc_conf_t    *plcf;
1167     ngx_http_script_len_code_pt   lcode;
1168 
1169     u = r->upstream;
1170 
1171     plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1172 
1173 #if (NGX_HTTP_CACHE)
1174     headers = u->cacheable ? &plcf->headers_cache : &plcf->headers;
1175 #else
1176     headers = &plcf->headers;
1177 #endif
1178 
1179     if (u->method.len) {
1180         /* HEAD was changed to GET to cache response */
1181         method = u->method;
1182 
1183     } else if (plcf->method) {
1184         if (ngx_http_complex_value(r, plcf->method, &method) != NGX_OK) {
1185             return NGX_ERROR;
1186         }
1187 
1188     } else {
1189         method = r->method_name;
1190     }
1191 
1192     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1193 
1194     if (method.len == 4
1195         && ngx_strncasecmp(method.data, (u_char *) "HEAD", 4) == 0)
1196     {
1197         ctx->head = 1;
1198     }
1199 
1200     len = method.len + 1 + sizeof(ngx_http_proxy_version) - 1
1201           + sizeof(CRLF) - 1;
1202 
1203     escape = 0;
1204     loc_len = 0;
1205     unparsed_uri = 0;
1206 
1207     if (plcf->proxy_lengths && ctx->vars.uri.len) {
1208         uri_len = ctx->vars.uri.len;
1209 
1210     } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri) {
1211         unparsed_uri = 1;
1212         uri_len = r->unparsed_uri.len;
1213 
1214     } else {
1215         loc_len = (r->valid_location && ctx->vars.uri.len) ?
1216                       plcf->location.len : 0;
1217 
1218         if (r->quoted_uri || r->space_in_uri || r->internal) {
1219             escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
1220                                         r->uri.len - loc_len, NGX_ESCAPE_URI);
1221         }
1222 
1223         uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
1224                   + sizeof("?") - 1 + r->args.len;
1225     }
1226 
1227     if (uri_len == 0) {
1228         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1229                       "zero length URI to proxy");
1230         return NGX_ERROR;
1231     }
1232 
1233     len += uri_len;
1234 
1235     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1236 
1237     ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
1238     ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
1239 
1240     if (plcf->body_lengths) {
1241         le.ip = plcf->body_lengths->elts;
1242         le.request = r;
1243         le.flushed = 1;
1244         body_len = 0;
1245 
1246         while (*(uintptr_t *) le.ip) {
1247             lcode = *(ngx_http_script_len_code_pt *) le.ip;
1248             body_len += lcode(&le);
1249         }
1250 
1251         ctx->internal_body_length = body_len;
1252         len += body_len;
1253 
1254     } else if (r->headers_in.chunked && r->reading_body) {
1255         ctx->internal_body_length = -1;
1256         ctx->internal_chunked = 1;
1257 
1258     } else {
1259         ctx->internal_body_length = r->headers_in.content_length_n;
1260     }
1261 
1262     le.ip = headers->lengths->elts;
1263     le.request = r;
1264     le.flushed = 1;
1265 
1266     while (*(uintptr_t *) le.ip) {
1267 
1268         lcode = *(ngx_http_script_len_code_pt *) le.ip;
1269         key_len = lcode(&le);
1270 
1271         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
1272             lcode = *(ngx_http_script_len_code_pt *) le.ip;
1273         }
1274         le.ip += sizeof(uintptr_t);
1275 
1276         if (val_len == 0) {
1277             continue;
1278         }
1279 
1280         len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1;
1281     }
1282 
1283 
1284     if (plcf->upstream.pass_request_headers) {
1285         part = &r->headers_in.headers.part;
1286         header = part->elts;
1287 
1288         for (i = 0; /* void */; i++) {
1289 
1290             if (i >= part->nelts) {
1291                 if (part->next == NULL) {
1292                     break;
1293                 }
1294 
1295                 part = part->next;
1296                 header = part->elts;
1297                 i = 0;
1298             }
1299 
1300             if (ngx_hash_find(&headers->hash, header[i].hash,
1301                               header[i].lowcase_key, header[i].key.len))
1302             {
1303                 continue;
1304             }
1305 
1306             len += header[i].key.len + sizeof(": ") - 1
1307                 + header[i].value.len + sizeof(CRLF) - 1;
1308         }
1309     }
1310 
1311 
1312     b = ngx_create_temp_buf(r->pool, len);
1313     if (b == NULL) {
1314         return NGX_ERROR;
1315     }
1316 
1317     cl = ngx_alloc_chain_link(r->pool);
1318     if (cl == NULL) {
1319         return NGX_ERROR;
1320     }
1321 
1322     cl->buf = b;
1323 
1324 
1325     /* the request line */
1326 
1327     b->last = ngx_copy(b->last, method.data, method.len);
1328     *b->last++ = ' ';
1329 
1330     u->uri.data = b->last;
1331 
1332     if (plcf->proxy_lengths && ctx->vars.uri.len) {
1333         b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
1334 
1335     } else if (unparsed_uri) {
1336         b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
1337 
1338     } else {
1339         if (r->valid_location) {
1340             b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
1341         }
1342 
1343         if (escape) {
1344             ngx_escape_uri(b->last, r->uri.data + loc_len,
1345                            r->uri.len - loc_len, NGX_ESCAPE_URI);
1346             b->last += r->uri.len - loc_len + escape;
1347 
1348         } else {
1349             b->last = ngx_copy(b->last, r->uri.data + loc_len,
1350                                r->uri.len - loc_len);
1351         }
1352 
1353         if (r->args.len > 0) {
1354             *b->last++ = '?';
1355             b->last = ngx_copy(b->last, r->args.data, r->args.len);
1356         }
1357     }
1358 
1359     u->uri.len = b->last - u->uri.data;
1360 
1361     if (plcf->http_version == NGX_HTTP_VERSION_11) {
1362         b->last = ngx_cpymem(b->last, ngx_http_proxy_version_11,
1363                              sizeof(ngx_http_proxy_version_11) - 1);
1364 
1365     } else {
1366         b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
1367                              sizeof(ngx_http_proxy_version) - 1);
1368     }
1369 
1370     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1371 
1372     e.ip = headers->values->elts;
1373     e.pos = b->last;
1374     e.request = r;
1375     e.flushed = 1;
1376 
1377     le.ip = headers->lengths->elts;
1378 
1379     while (*(uintptr_t *) le.ip) {
1380 
1381         lcode = *(ngx_http_script_len_code_pt *) le.ip;
1382         (void) lcode(&le);
1383 
1384         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
1385             lcode = *(ngx_http_script_len_code_pt *) le.ip;
1386         }
1387         le.ip += sizeof(uintptr_t);
1388 
1389         if (val_len == 0) {
1390             e.skip = 1;
1391 
1392             while (*(uintptr_t *) e.ip) {
1393                 code = *(ngx_http_script_code_pt *) e.ip;
1394                 code((ngx_http_script_engine_t *) &e);
1395             }
1396             e.ip += sizeof(uintptr_t);
1397 
1398             e.skip = 0;
1399 
1400             continue;
1401         }
1402 
1403         code = *(ngx_http_script_code_pt *) e.ip;
1404         code((ngx_http_script_engine_t *) &e);
1405 
1406         *e.pos++ = ':'; *e.pos++ = ' ';
1407 
1408         while (*(uintptr_t *) e.ip) {
1409             code = *(ngx_http_script_code_pt *) e.ip;
1410             code((ngx_http_script_engine_t *) &e);
1411         }
1412         e.ip += sizeof(uintptr_t);
1413 
1414         *e.pos++ = CR; *e.pos++ = LF;
1415     }
1416 
1417     b->last = e.pos;
1418 
1419 
1420     if (plcf->upstream.pass_request_headers) {
1421         part = &r->headers_in.headers.part;
1422         header = part->elts;
1423 
1424         for (i = 0; /* void */; i++) {
1425 
1426             if (i >= part->nelts) {
1427                 if (part->next == NULL) {
1428                     break;
1429                 }
1430 
1431                 part = part->next;
1432                 header = part->elts;
1433                 i = 0;
1434             }
1435 
1436             if (ngx_hash_find(&headers->hash, header[i].hash,
1437                               header[i].lowcase_key, header[i].key.len))
1438             {
1439                 continue;
1440             }
1441 
1442             b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
1443 
1444             *b->last++ = ':'; *b->last++ = ' ';
1445 
1446             b->last = ngx_copy(b->last, header[i].value.data,
1447                                header[i].value.len);
1448 
1449             *b->last++ = CR; *b->last++ = LF;
1450 
1451             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1452                            "http proxy header: \"%V: %V\"",
1453                            &header[i].key, &header[i].value);
1454         }
1455     }
1456 
1457 
1458     /* add "\r\n" at the header end */
1459     *b->last++ = CR; *b->last++ = LF;
1460 
1461     if (plcf->body_values) {
1462         e.ip = plcf->body_values->elts;
1463         e.pos = b->last;
1464         e.skip = 0;
1465 
1466         while (*(uintptr_t *) e.ip) {
1467             code = *(ngx_http_script_code_pt *) e.ip;
1468             code((ngx_http_script_engine_t *) &e);
1469         }
1470 
1471         b->last = e.pos;
1472     }
1473 
1474     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1475                    "http proxy header:%N\"%*s\"",
1476                    (size_t) (b->last - b->pos), b->pos);
1477 
1478     if (r->request_body_no_buffering) {
1479 
1480         u->request_bufs = cl;
1481 
1482         if (ctx->internal_chunked) {
1483             u->output.output_filter = ngx_http_proxy_body_output_filter;
1484             u->output.filter_ctx = r;
1485         }
1486 
1487     } else if (plcf->body_values == NULL && plcf->upstream.pass_request_body) {
1488 
1489         body = u->request_bufs;
1490         u->request_bufs = cl;
1491 
1492         while (body) {
1493             b = ngx_alloc_buf(r->pool);
1494             if (b == NULL) {
1495                 return NGX_ERROR;
1496             }
1497 
1498             ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
1499 
1500             cl->next = ngx_alloc_chain_link(r->pool);
1501             if (cl->next == NULL) {
1502                 return NGX_ERROR;
1503             }
1504 
1505             cl = cl->next;
1506             cl->buf = b;
1507 
1508             body = body->next;
1509         }
1510 
1511     } else {
1512         u->request_bufs = cl;
1513     }
1514 
1515     b->flush = 1;
1516     cl->next = NULL;
1517 
1518     return NGX_OK;
1519 }
1520 
1521 
1522 static ngx_int_t
1523 ngx_http_proxy_reinit_request(ngx_http_request_t *r)
1524 {
1525     ngx_http_proxy_ctx_t  *ctx;
1526 
1527     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1528 
1529     if (ctx == NULL) {
1530         return NGX_OK;
1531     }
1532 
1533     ctx->status.code = 0;
1534     ctx->status.count = 0;
1535     ctx->status.start = NULL;
1536     ctx->status.end = NULL;
1537     ctx->chunked.state = 0;
1538 
1539     r->upstream->process_header = ngx_http_proxy_process_status_line;
1540     r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
1541     r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter;
1542     r->state = 0;
1543 
1544     return NGX_OK;
1545 }
1546 
1547 
1548 static ngx_int_t
1549 ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in)
1550 {
1551     ngx_http_request_t  *r = data;
1552 
1553     off_t                  size;
1554     u_char                *chunk;
1555     ngx_int_t              rc;
1556     ngx_buf_t             *b;
1557     ngx_chain_t           *out, *cl, *tl, **ll, **fl;
1558     ngx_http_proxy_ctx_t  *ctx;
1559 
1560     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1561                    "proxy output filter");
1562 
1563     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1564 
1565     if (in == NULL) {
1566         out = in;
1567         goto out;
1568     }
1569 
1570     out = NULL;
1571     ll = &out;
1572 
1573     if (!ctx->header_sent) {
1574         /* first buffer contains headers, pass it unmodified */
1575 
1576         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1577                        "proxy output header");
1578 
1579         ctx->header_sent = 1;
1580 
1581         tl = ngx_alloc_chain_link(r->pool);
1582         if (tl == NULL) {
1583             return NGX_ERROR;
1584         }
1585 
1586         tl->buf = in->buf;
1587         *ll = tl;
1588         ll = &tl->next;
1589 
1590         in = in->next;
1591 
1592         if (in == NULL) {
1593             tl->next = NULL;
1594             goto out;
1595         }
1596     }
1597 
1598     size = 0;
1599     cl = in;
1600     fl = ll;
1601 
1602     for ( ;; ) {
1603         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1604                        "proxy output chunk: %O", ngx_buf_size(cl->buf));
1605 
1606         size += ngx_buf_size(cl->buf);
1607 
1608         if (cl->buf->flush
1609             || cl->buf->sync
1610             || ngx_buf_in_memory(cl->buf)
1611             || cl->buf->in_file)
1612         {
1613             tl = ngx_alloc_chain_link(r->pool);
1614             if (tl == NULL) {
1615                 return NGX_ERROR;
1616             }
1617 
1618             tl->buf = cl->buf;
1619             *ll = tl;
1620             ll = &tl->next;
1621         }
1622 
1623         if (cl->next == NULL) {
1624             break;
1625         }
1626 
1627         cl = cl->next;
1628     }
1629 
1630     if (size) {
1631         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1632         if (tl == NULL) {
1633             return NGX_ERROR;
1634         }
1635 
1636         b = tl->buf;
1637         chunk = b->start;
1638 
1639         if (chunk == NULL) {
1640             /* the "0000000000000000" is 64-bit hexadecimal string */
1641 
1642             chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
1643             if (chunk == NULL) {
1644                 return NGX_ERROR;
1645             }
1646 
1647             b->start = chunk;
1648             b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
1649         }
1650 
1651         b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1652         b->memory = 0;
1653         b->temporary = 1;
1654         b->pos = chunk;
1655         b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
1656 
1657         tl->next = *fl;
1658         *fl = tl;
1659     }
1660 
1661     if (cl->buf->last_buf) {
1662         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1663         if (tl == NULL) {
1664             return NGX_ERROR;
1665         }
1666 
1667         b = tl->buf;
1668 
1669         b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1670         b->temporary = 0;
1671         b->memory = 1;
1672         b->last_buf = 1;
1673         b->pos = (u_char *) CRLF "0" CRLF CRLF;
1674         b->last = b->pos + 7;
1675 
1676         cl->buf->last_buf = 0;
1677 
1678         *ll = tl;
1679 
1680         if (size == 0) {
1681             b->pos += 2;
1682         }
1683 
1684     } else if (size > 0) {
1685         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
1686         if (tl == NULL) {
1687             return NGX_ERROR;
1688         }
1689 
1690         b = tl->buf;
1691 
1692         b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
1693         b->temporary = 0;
1694         b->memory = 1;
1695         b->pos = (u_char *) CRLF;
1696         b->last = b->pos + 2;
1697 
1698         *ll = tl;
1699 
1700     } else {
1701         *ll = NULL;
1702     }
1703 
1704 out:
1705 
1706     rc = ngx_chain_writer(&r->upstream->writer, out);
1707 
1708     ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
1709                             (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter);
1710 
1711     return rc;
1712 }
1713 
1714 
1715 static ngx_int_t
1716 ngx_http_proxy_process_status_line(ngx_http_request_t *r)
1717 {
1718     size_t                 len;
1719     ngx_int_t              rc;
1720     ngx_http_upstream_t   *u;
1721     ngx_http_proxy_ctx_t  *ctx;
1722 
1723     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1724 
1725     if (ctx == NULL) {
1726         return NGX_ERROR;
1727     }
1728 
1729     u = r->upstream;
1730 
1731     rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);
1732 
1733     if (rc == NGX_AGAIN) {
1734         return rc;
1735     }
1736 
1737     if (rc == NGX_ERROR) {
1738 
1739 #if (NGX_HTTP_CACHE)
1740 
1741         if (r->cache) {
1742             r->http_version = NGX_HTTP_VERSION_9;
1743             return NGX_OK;
1744         }
1745 
1746 #endif
1747 
1748         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1749                       "upstream sent no valid HTTP/1.0 header");
1750 
1751 #if 0
1752         if (u->accel) {
1753             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1754         }
1755 #endif
1756 
1757         r->http_version = NGX_HTTP_VERSION_9;
1758         u->state->status = NGX_HTTP_OK;
1759         u->headers_in.connection_close = 1;
1760 
1761         return NGX_OK;
1762     }
1763 
1764     if (u->state && u->state->status == 0) {
1765         u->state->status = ctx->status.code;
1766     }
1767 
1768     u->headers_in.status_n = ctx->status.code;
1769 
1770     len = ctx->status.end - ctx->status.start;
1771     u->headers_in.status_line.len = len;
1772 
1773     u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
1774     if (u->headers_in.status_line.data == NULL) {
1775         return NGX_ERROR;
1776     }
1777 
1778     ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);
1779 
1780     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1781                    "http proxy status %ui \"%V\"",
1782                    u->headers_in.status_n, &u->headers_in.status_line);
1783 
1784     if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
1785         u->headers_in.connection_close = 1;
1786     }
1787 
1788     u->process_header = ngx_http_proxy_process_header;
1789 
1790     return ngx_http_proxy_process_header(r);
1791 }
1792 
1793 
1794 static ngx_int_t
1795 ngx_http_proxy_process_header(ngx_http_request_t *r)
1796 {
1797     ngx_int_t                       rc;
1798     ngx_table_elt_t                *h;
1799     ngx_http_upstream_t            *u;
1800     ngx_http_proxy_ctx_t           *ctx;
1801     ngx_http_upstream_header_t     *hh;
1802     ngx_http_upstream_main_conf_t  *umcf;
1803 
1804     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1805 
1806     for ( ;; ) {
1807 
1808         rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
1809 
1810         if (rc == NGX_OK) {
1811 
1812             /* a header line has been parsed successfully */
1813 
1814             h = ngx_list_push(&r->upstream->headers_in.headers);
1815             if (h == NULL) {
1816                 return NGX_ERROR;
1817             }
1818 
1819             h->hash = r->header_hash;
1820 
1821             h->key.len = r->header_name_end - r->header_name_start;
1822             h->value.len = r->header_end - r->header_start;
1823 
1824             h->key.data = ngx_pnalloc(r->pool,
1825                                h->key.len + 1 + h->value.len + 1 + h->key.len);
1826             if (h->key.data == NULL) {
1827                 h->hash = 0;
1828                 return NGX_ERROR;
1829             }
1830 
1831             h->value.data = h->key.data + h->key.len + 1;
1832             h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
1833 
1834             ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
1835             h->key.data[h->key.len] = '\0';
1836             ngx_memcpy(h->value.data, r->header_start, h->value.len);
1837             h->value.data[h->value.len] = '\0';
1838 
1839             if (h->key.len == r->lowcase_index) {
1840                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1841 
1842             } else {
1843                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1844             }
1845 
1846             hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
1847                                h->lowcase_key, h->key.len);
1848 
1849             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1850                 return NGX_ERROR;
1851             }
1852 
1853             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1854                            "http proxy header: \"%V: %V\"",
1855                            &h->key, &h->value);
1856 
1857             continue;
1858         }
1859 
1860         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1861 
1862             /* a whole header has been parsed successfully */
1863 
1864             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1865                            "http proxy header done");
1866 
1867             /*
1868              * if no "Server" and "Date" in header line,
1869              * then add the special empty headers
1870              */
1871 
1872             if (r->upstream->headers_in.server == NULL) {
1873                 h = ngx_list_push(&r->upstream->headers_in.headers);
1874                 if (h == NULL) {
1875                     return NGX_ERROR;
1876                 }
1877 
1878                 h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
1879                                     ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
1880 
1881                 ngx_str_set(&h->key, "Server");
1882                 ngx_str_null(&h->value);
1883                 h->lowcase_key = (u_char *) "server";
1884             }
1885 
1886             if (r->upstream->headers_in.date == NULL) {
1887                 h = ngx_list_push(&r->upstream->headers_in.headers);
1888                 if (h == NULL) {
1889                     return NGX_ERROR;
1890                 }
1891 
1892                 h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
1893 
1894                 ngx_str_set(&h->key, "Date");
1895                 ngx_str_null(&h->value);
1896                 h->lowcase_key = (u_char *) "date";
1897             }
1898 
1899             /* clear content length if response is chunked */
1900 
1901             u = r->upstream;
1902 
1903             if (u->headers_in.chunked) {
1904                 u->headers_in.content_length_n = -1;
1905             }
1906 
1907             /*
1908              * set u->keepalive if response has no body; this allows to keep
1909              * connections alive in case of r->header_only or X-Accel-Redirect
1910              */
1911 
1912             ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1913 
1914             if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1915                 || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1916                 || ctx->head
1917                 || (!u->headers_in.chunked
1918                     && u->headers_in.content_length_n == 0))
1919             {
1920                 u->keepalive = !u->headers_in.connection_close;
1921             }
1922 
1923             if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS) {
1924                 u->keepalive = 0;
1925 
1926                 if (r->headers_in.upgrade) {
1927                     u->upgrade = 1;
1928                 }
1929             }
1930 
1931             return NGX_OK;
1932         }
1933 
1934         if (rc == NGX_AGAIN) {
1935             return NGX_AGAIN;
1936         }
1937 
1938         /* there was error while a header line parsing */
1939 
1940         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1941                       "upstream sent invalid header");
1942 
1943         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1944     }
1945 }
1946 
1947 
1948 static ngx_int_t
1949 ngx_http_proxy_input_filter_init(void *data)
1950 {
1951     ngx_http_request_t    *r = data;
1952     ngx_http_upstream_t   *u;
1953     ngx_http_proxy_ctx_t  *ctx;
1954 
1955     u = r->upstream;
1956     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1957 
1958     if (ctx == NULL) {
1959         return NGX_ERROR;
1960     }
1961 
1962     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1963                    "http proxy filter init s:%ui h:%d c:%d l:%O",
1964                    u->headers_in.status_n, ctx->head, u->headers_in.chunked,
1965                    u->headers_in.content_length_n);
1966 
1967     /* as per RFC2616, 4.4 Message Length */
1968 
1969     if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1970         || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1971         || ctx->head)
1972     {
1973         /* 1xx, 204, and 304 and replies to HEAD requests */
1974         /* no 1xx since we don't send Expect and Upgrade */
1975 
1976         u->pipe->length = 0;
1977         u->length = 0;
1978         u->keepalive = !u->headers_in.connection_close;
1979 
1980     } else if (u->headers_in.chunked) {
1981         /* chunked */
1982 
1983         u->pipe->input_filter = ngx_http_proxy_chunked_filter;
1984         u->pipe->length = 3; /* "0" LF LF */
1985 
1986         u->input_filter = ngx_http_proxy_non_buffered_chunked_filter;
1987         u->length = 1;
1988 
1989     } else if (u->headers_in.content_length_n == 0) {
1990         /* empty body: special case as filter won't be called */
1991 
1992         u->pipe->length = 0;
1993         u->length = 0;
1994         u->keepalive = !u->headers_in.connection_close;
1995 
1996     } else {
1997         /* content length or connection close */
1998 
1999         u->pipe->length = u->headers_in.content_length_n;
2000         u->length = u->headers_in.content_length_n;
2001     }
2002 
2003     return NGX_OK;
2004 }
2005 
2006 
2007 static ngx_int_t
2008 ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
2009 {
2010     ngx_buf_t           *b;
2011     ngx_chain_t         *cl;
2012     ngx_http_request_t  *r;
2013 
2014     if (buf->pos == buf->last) {
2015         return NGX_OK;
2016     }
2017 
2018     cl = ngx_chain_get_free_buf(p->pool, &p->free);
2019     if (cl == NULL) {
2020         return NGX_ERROR;
2021     }
2022 
2023     b = cl->buf;
2024 
2025     ngx_memcpy(b, buf, sizeof(ngx_buf_t));
2026     b->shadow = buf;
2027     b->tag = p->tag;
2028     b->last_shadow = 1;
2029     b->recycled = 1;
2030     buf->shadow = b;
2031 
2032     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
2033 
2034     if (p->in) {
2035         *p->last_in = cl;
2036     } else {
2037         p->in = cl;
2038     }
2039     p->last_in = &cl->next;
2040 
2041     if (p->length == -1) {
2042         return NGX_OK;
2043     }
2044 
2045     p->length -= b->last - b->pos;
2046 
2047     if (p->length == 0) {
2048         r = p->input_ctx;
2049         p->upstream_done = 1;
2050         r->upstream->keepalive = !r->upstream->headers_in.connection_close;
2051 
2052     } else if (p->length < 0) {
2053         r = p->input_ctx;
2054         p->upstream_done = 1;
2055 
2056         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
2057                       "upstream sent more data than specified in "
2058                       "\"Content-Length\" header");
2059     }
2060 
2061     return NGX_OK;
2062 }
2063 
2064 
2065 static ngx_int_t
2066 ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
2067 {
2068     ngx_int_t              rc;
2069     ngx_buf_t             *b, **prev;
2070     ngx_chain_t           *cl;
2071     ngx_http_request_t    *r;
2072     ngx_http_proxy_ctx_t  *ctx;
2073 
2074     if (buf->pos == buf->last) {
2075         return NGX_OK;
2076     }
2077 
2078     r = p->input_ctx;
2079     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2080 
2081     if (ctx == NULL) {
2082         return NGX_ERROR;
2083     }
2084 
2085     b = NULL;
2086     prev = &buf->shadow;
2087 
2088     for ( ;; ) {
2089 
2090         rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2091 
2092         if (rc == NGX_OK) {
2093 
2094             /* a chunk has been parsed successfully */
2095 
2096             cl = ngx_chain_get_free_buf(p->pool, &p->free);
2097             if (cl == NULL) {
2098                 return NGX_ERROR;
2099             }
2100 
2101             b = cl->buf;
2102 
2103             ngx_memzero(b, sizeof(ngx_buf_t));
2104 
2105             b->pos = buf->pos;
2106             b->start = buf->start;
2107             b->end = buf->end;
2108             b->tag = p->tag;
2109             b->temporary = 1;
2110             b->recycled = 1;
2111 
2112             *prev = b;
2113             prev = &b->shadow;
2114 
2115             if (p->in) {
2116                 *p->last_in = cl;
2117             } else {
2118                 p->in = cl;
2119             }
2120             p->last_in = &cl->next;
2121 
2122             /* STUB */ b->num = buf->num;
2123 
2124             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
2125                            "input buf #%d %p", b->num, b->pos);
2126 
2127             if (buf->last - buf->pos >= ctx->chunked.size) {
2128 
2129                 buf->pos += (size_t) ctx->chunked.size;
2130                 b->last = buf->pos;
2131                 ctx->chunked.size = 0;
2132 
2133                 continue;
2134             }
2135 
2136             ctx->chunked.size -= buf->last - buf->pos;
2137             buf->pos = buf->last;
2138             b->last = buf->last;
2139 
2140             continue;
2141         }
2142 
2143         if (rc == NGX_DONE) {
2144 
2145             /* a whole response has been parsed successfully */
2146 
2147             p->upstream_done = 1;
2148             r->upstream->keepalive = !r->upstream->headers_in.connection_close;
2149 
2150             break;
2151         }
2152 
2153         if (rc == NGX_AGAIN) {
2154 
2155             /* set p->length, minimal amount of data we want to see */
2156 
2157             p->length = ctx->chunked.length;
2158 
2159             break;
2160         }
2161 
2162         /* invalid response */
2163 
2164         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2165                       "upstream sent invalid chunked response");
2166 
2167         return NGX_ERROR;
2168     }
2169 
2170     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2171                    "http proxy chunked state %ui, length %O",
2172                    ctx->chunked.state, p->length);
2173 
2174     if (b) {
2175         b->shadow = buf;
2176         b->last_shadow = 1;
2177 
2178         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
2179                        "input buf %p %z", b->pos, b->last - b->pos);
2180 
2181         return NGX_OK;
2182     }
2183 
2184     /* there is no data record in the buf, add it to free chain */
2185 
2186     if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
2187         return NGX_ERROR;
2188     }
2189 
2190     return NGX_OK;
2191 }
2192 
2193 
2194 static ngx_int_t
2195 ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
2196 {
2197     ngx_http_request_t   *r = data;
2198 
2199     ngx_buf_t            *b;
2200     ngx_chain_t          *cl, **ll;
2201     ngx_http_upstream_t  *u;
2202 
2203     u = r->upstream;
2204 
2205     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2206         ll = &cl->next;
2207     }
2208 
2209     cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2210     if (cl == NULL) {
2211         return NGX_ERROR;
2212     }
2213 
2214     *ll = cl;
2215 
2216     cl->buf->flush = 1;
2217     cl->buf->memory = 1;
2218 
2219     b = &u->buffer;
2220 
2221     cl->buf->pos = b->last;
2222     b->last += bytes;
2223     cl->buf->last = b->last;
2224     cl->buf->tag = u->output.tag;
2225 
2226     if (u->length == -1) {
2227         return NGX_OK;
2228     }
2229 
2230     u->length -= bytes;
2231 
2232     if (u->length == 0) {
2233         u->keepalive = !u->headers_in.connection_close;
2234     }
2235 
2236     return NGX_OK;
2237 }
2238 
2239 
2240 static ngx_int_t
2241 ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
2242 {
2243     ngx_http_request_t   *r = data;
2244 
2245     ngx_int_t              rc;
2246     ngx_buf_t             *b, *buf;
2247     ngx_chain_t           *cl, **ll;
2248     ngx_http_upstream_t   *u;
2249     ngx_http_proxy_ctx_t  *ctx;
2250 
2251     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2252 
2253     if (ctx == NULL) {
2254         return NGX_ERROR;
2255     }
2256 
2257     u = r->upstream;
2258     buf = &u->buffer;
2259 
2260     buf->pos = buf->last;
2261     buf->last += bytes;
2262 
2263     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2264         ll = &cl->next;
2265     }
2266 
2267     for ( ;; ) {
2268 
2269         rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2270 
2271         if (rc == NGX_OK) {
2272 
2273             /* a chunk has been parsed successfully */
2274 
2275             cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2276             if (cl == NULL) {
2277                 return NGX_ERROR;
2278             }
2279 
2280             *ll = cl;
2281             ll = &cl->next;
2282 
2283             b = cl->buf;
2284 
2285             b->flush = 1;
2286             b->memory = 1;
2287 
2288             b->pos = buf->pos;
2289             b->tag = u->output.tag;
2290 
2291             if (buf->last - buf->pos >= ctx->chunked.size) {
2292                 buf->pos += (size_t) ctx->chunked.size;
2293                 b->last = buf->pos;
2294                 ctx->chunked.size = 0;
2295 
2296             } else {
2297                 ctx->chunked.size -= buf->last - buf->pos;
2298                 buf->pos = buf->last;
2299                 b->last = buf->last;
2300             }
2301 
2302             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2303                            "http proxy out buf %p %z",
2304                            b->pos, b->last - b->pos);
2305 
2306             continue;
2307         }
2308 
2309         if (rc == NGX_DONE) {
2310 
2311             /* a whole response has been parsed successfully */
2312 
2313             u->keepalive = !u->headers_in.connection_close;
2314             u->length = 0;
2315 
2316             break;
2317         }
2318 
2319         if (rc == NGX_AGAIN) {
2320             break;
2321         }
2322 
2323         /* invalid response */
2324 
2325         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2326                       "upstream sent invalid chunked response");
2327 
2328         return NGX_ERROR;
2329     }
2330 
2331     return NGX_OK;
2332 }
2333 
2334 
2335 static void
2336 ngx_http_proxy_abort_request(ngx_http_request_t *r)
2337 {
2338     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2339                    "abort http proxy request");
2340 
2341     return;
2342 }
2343 
2344 
2345 static void
2346 ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2347 {
2348     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2349                    "finalize http proxy request");
2350 
2351     return;
2352 }
2353 
2354 
2355 static ngx_int_t
2356 ngx_http_proxy_host_variable(ngx_http_request_t *r,
2357     ngx_http_variable_value_t *v, uintptr_t data)
2358 {
2359     ngx_http_proxy_ctx_t  *ctx;
2360 
2361     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2362 
2363     if (ctx == NULL) {
2364         v->not_found = 1;
2365         return NGX_OK;
2366     }
2367 
2368     v->len = ctx->vars.host_header.len;
2369     v->valid = 1;
2370     v->no_cacheable = 0;
2371     v->not_found = 0;
2372     v->data = ctx->vars.host_header.data;
2373 
2374     return NGX_OK;
2375 }
2376 
2377 
2378 static ngx_int_t
2379 ngx_http_proxy_port_variable(ngx_http_request_t *r,
2380     ngx_http_variable_value_t *v, uintptr_t data)
2381 {
2382     ngx_http_proxy_ctx_t  *ctx;
2383 
2384     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2385 
2386     if (ctx == NULL) {
2387         v->not_found = 1;
2388         return NGX_OK;
2389     }
2390 
2391     v->len = ctx->vars.port.len;
2392     v->valid = 1;
2393     v->no_cacheable = 0;
2394     v->not_found = 0;
2395     v->data = ctx->vars.port.data;
2396 
2397     return NGX_OK;
2398 }
2399 
2400 
2401 static ngx_int_t
2402 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
2403     ngx_http_variable_value_t *v, uintptr_t data)
2404 {
2405     size_t             len;
2406     u_char            *p;
2407     ngx_uint_t         i, n;
2408     ngx_table_elt_t  **h;
2409 
2410     v->valid = 1;
2411     v->no_cacheable = 0;
2412     v->not_found = 0;
2413 
2414     n = r->headers_in.x_forwarded_for.nelts;
2415     h = r->headers_in.x_forwarded_for.elts;
2416 
2417     len = 0;
2418 
2419     for (i = 0; i < n; i++) {
2420         len += h[i]->value.len + sizeof(", ") - 1;
2421     }
2422 
2423     if (len == 0) {
2424         v->len = r->connection->addr_text.len;
2425         v->data = r->connection->addr_text.data;
2426         return NGX_OK;
2427     }
2428 
2429     len += r->connection->addr_text.len;
2430 
2431     p = ngx_pnalloc(r->pool, len);
2432     if (p == NULL) {
2433         return NGX_ERROR;
2434     }
2435 
2436     v->len = len;
2437     v->data = p;
2438 
2439     for (i = 0; i < n; i++) {
2440         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
2441         *p++ = ','; *p++ = ' ';
2442     }
2443 
2444     ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
2445 
2446     return NGX_OK;
2447 }
2448 
2449 
2450 static ngx_int_t
2451 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
2452     ngx_http_variable_value_t *v, uintptr_t data)
2453 {
2454     ngx_http_proxy_ctx_t  *ctx;
2455 
2456     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2457 
2458     if (ctx == NULL || ctx->internal_body_length < 0) {
2459         v->not_found = 1;
2460         return NGX_OK;
2461     }
2462 
2463     v->valid = 1;
2464     v->no_cacheable = 0;
2465     v->not_found = 0;
2466 
2467     v->data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
2468 
2469     if (v->data == NULL) {
2470         return NGX_ERROR;
2471     }
2472 
2473     v->len = ngx_sprintf(v->data, "%O", ctx->internal_body_length) - v->data;
2474 
2475     return NGX_OK;
2476 }
2477 
2478 
2479 static ngx_int_t
2480 ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
2481     ngx_http_variable_value_t *v, uintptr_t data)
2482 {
2483     ngx_http_proxy_ctx_t  *ctx;
2484 
2485     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2486 
2487     if (ctx == NULL || !ctx->internal_chunked) {
2488         v->not_found = 1;
2489         return NGX_OK;
2490     }
2491 
2492     v->valid = 1;
2493     v->no_cacheable = 0;
2494     v->not_found = 0;
2495 
2496     v->data = (u_char *) "chunked";
2497     v->len = sizeof("chunked") - 1;
2498 
2499     return NGX_OK;
2500 }
2501 
2502 
2503 static ngx_int_t
2504 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
2505     size_t prefix)
2506 {
2507     size_t                      len;
2508     ngx_int_t                   rc;
2509     ngx_uint_t                  i;
2510     ngx_http_proxy_rewrite_t   *pr;
2511     ngx_http_proxy_loc_conf_t  *plcf;
2512 
2513     plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2514 
2515     pr = plcf->redirects->elts;
2516 
2517     if (pr == NULL) {
2518         return NGX_DECLINED;
2519     }
2520 
2521     len = h->value.len - prefix;
2522 
2523     for (i = 0; i < plcf->redirects->nelts; i++) {
2524         rc = pr[i].handler(r, h, prefix, len, &pr[i]);
2525 
2526         if (rc != NGX_DECLINED) {
2527             return rc;
2528         }
2529     }
2530 
2531     return NGX_DECLINED;
2532 }
2533 
2534 
2535 static ngx_int_t
2536 ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
2537 {
2538     size_t                      prefix;
2539     u_char                     *p;
2540     ngx_int_t                   rc, rv;
2541     ngx_http_proxy_loc_conf_t  *plcf;
2542 
2543     p = (u_char *) ngx_strchr(h->value.data, ';');
2544     if (p == NULL) {
2545         return NGX_DECLINED;
2546     }
2547 
2548     prefix = p + 1 - h->value.data;
2549 
2550     rv = NGX_DECLINED;
2551 
2552     plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2553 
2554     if (plcf->cookie_domains) {
2555         p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
2556 
2557         if (p) {
2558             rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
2559                                                      plcf->cookie_domains);
2560             if (rc == NGX_ERROR) {
2561                 return NGX_ERROR;
2562             }
2563 
2564             if (rc != NGX_DECLINED) {
2565                 rv = rc;
2566             }
2567         }
2568     }
2569 
2570     if (plcf->cookie_paths) {
2571         p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
2572 
2573         if (p) {
2574             rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
2575                                                      plcf->cookie_paths);
2576             if (rc == NGX_ERROR) {
2577                 return NGX_ERROR;
2578             }
2579 
2580             if (rc != NGX_DECLINED) {
2581                 rv = rc;
2582             }
2583         }
2584     }
2585 
2586     return rv;
2587 }
2588 
2589 
2590 static ngx_int_t
2591 ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
2592     u_char *value, ngx_array_t *rewrites)
2593 {
2594     size_t                     len, prefix;
2595     u_char                    *p;
2596     ngx_int_t                  rc;
2597     ngx_uint_t                 i;
2598     ngx_http_proxy_rewrite_t  *pr;
2599 
2600     prefix = value - h->value.data;
2601 
2602     p = (u_char *) ngx_strchr(value, ';');
2603 
2604     len = p ? (size_t) (p - value) : (h->value.len - prefix);
2605 
2606     pr = rewrites->elts;
2607 
2608     for (i = 0; i < rewrites->nelts; i++) {
2609         rc = pr[i].handler(r, h, prefix, len, &pr[i]);
2610 
2611         if (rc != NGX_DECLINED) {
2612             return rc;
2613         }
2614     }
2615 
2616     return NGX_DECLINED;
2617 }
2618 
2619 
2620 static ngx_int_t
2621 ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
2622     ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2623 {
2624     ngx_str_t  pattern, replacement;
2625 
2626     if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
2627         return NGX_ERROR;
2628     }
2629 
2630     if (pattern.len > len
2631         || ngx_rstrncmp(h->value.data + prefix, pattern.data,
2632                         pattern.len) != 0)
2633     {
2634         return NGX_DECLINED;
2635     }
2636 
2637     if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2638         return NGX_ERROR;
2639     }
2640 
2641     return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
2642 }
2643 
2644 
2645 #if (NGX_PCRE)
2646 
2647 static ngx_int_t
2648 ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
2649     size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2650 {
2651     ngx_str_t  pattern, replacement;
2652 
2653     pattern.len = len;
2654     pattern.data = h->value.data + prefix;
2655 
2656     if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
2657         return NGX_DECLINED;
2658     }
2659 
2660     if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2661         return NGX_ERROR;
2662     }
2663 
2664     if (prefix == 0 && h->value.len == len) {
2665         h->value = replacement;
2666         return NGX_OK;
2667     }
2668 
2669     return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
2670 }
2671 
2672 #endif
2673 
2674 
2675 static ngx_int_t
2676 ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
2677     ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2678 {
2679     u_char     *p;
2680     ngx_str_t   pattern, replacement;
2681 
2682     if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
2683         return NGX_ERROR;
2684     }
2685 
2686     p = h->value.data + prefix;
2687 
2688     if (p[0] == '.') {
2689         p++;
2690         prefix++;
2691         len--;
2692     }
2693 
2694     if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) {
2695         return NGX_DECLINED;
2696     }
2697 
2698     if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2699         return NGX_ERROR;
2700     }
2701 
2702     return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
2703 }
2704 
2705 
2706 static ngx_int_t
2707 ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
2708     size_t len, ngx_str_t *replacement)
2709 {
2710     u_char  *p, *data;
2711     size_t   new_len;
2712 
2713     new_len = replacement->len + h->value.len - len;
2714 
2715     if (replacement->len > len) {
2716 
2717         data = ngx_pnalloc(r->pool, new_len + 1);
2718         if (data == NULL) {
2719             return NGX_ERROR;
2720         }
2721 
2722         p = ngx_copy(data, h->value.data, prefix);
2723         p = ngx_copy(p, replacement->data, replacement->len);
2724 
2725         ngx_memcpy(p, h->value.data + prefix + len,
2726                    h->value.len - len - prefix + 1);
2727 
2728         h->value.data = data;
2729 
2730     } else {
2731         p = ngx_copy(h->value.data + prefix, replacement->data,
2732                      replacement->len);
2733 
2734         ngx_memmove(p, h->value.data + prefix + len,
2735                     h->value.len - len - prefix + 1);
2736     }
2737 
2738     h->value.len = new_len;
2739 
2740     return NGX_OK;
2741 }
2742 
2743 
2744 static ngx_int_t
2745 ngx_http_proxy_add_variables(ngx_conf_t *cf)
2746 {
2747     ngx_http_variable_t  *var, *v;
2748 
2749     for (v = ngx_http_proxy_vars; v->name.len; v++) {
2750         var = ngx_http_add_variable(cf, &v->name, v->flags);
2751         if (var == NULL) {
2752             return NGX_ERROR;
2753         }
2754 
2755         var->get_handler = v->get_handler;
2756         var->data = v->data;
2757     }
2758 
2759     return NGX_OK;
2760 }
2761 
2762 
2763 static void *
2764 ngx_http_proxy_create_main_conf(ngx_conf_t *cf)
2765 {
2766     ngx_http_proxy_main_conf_t  *conf;
2767 
2768     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_main_conf_t));
2769     if (conf == NULL) {
2770         return NULL;
2771     }
2772 
2773 #if (NGX_HTTP_CACHE)
2774     if (ngx_array_init(&conf->caches, cf->pool, 4,
2775                        sizeof(ngx_http_file_cache_t *))
2776         != NGX_OK)
2777     {
2778         return NULL;
2779     }
2780 #endif
2781 
2782     return conf;
2783 }
2784 
2785 
2786 static void *
2787 ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
2788 {
2789     ngx_http_proxy_loc_conf_t  *conf;
2790 
2791     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
2792     if (conf == NULL) {
2793         return NULL;
2794     }
2795 
2796     /*
2797      * set by ngx_pcalloc():
2798      *
2799      *     conf->upstream.bufs.num = 0;
2800      *     conf->upstream.ignore_headers = 0;
2801      *     conf->upstream.next_upstream = 0;
2802      *     conf->upstream.cache_zone = NULL;
2803      *     conf->upstream.cache_use_stale = 0;
2804      *     conf->upstream.cache_methods = 0;
2805      *     conf->upstream.temp_path = NULL;
2806      *     conf->upstream.hide_headers_hash = { NULL, 0 };
2807      *     conf->upstream.store_lengths = NULL;
2808      *     conf->upstream.store_values = NULL;
2809      *     conf->upstream.ssl_name = NULL;
2810      *
2811      *     conf->method = NULL;
2812      *     conf->location = NULL;
2813      *     conf->url = { 0, NULL };
2814      *     conf->headers_source = NULL;
2815      *     conf->headers.lengths = NULL;
2816      *     conf->headers.values = NULL;
2817      *     conf->headers.hash = { NULL, 0 };
2818      *     conf->headers_cache.lengths = NULL;
2819      *     conf->headers_cache.values = NULL;
2820      *     conf->headers_cache.hash = { NULL, 0 };
2821      *     conf->body_lengths = NULL;
2822      *     conf->body_values = NULL;
2823      *     conf->body_source = { 0, NULL };
2824      *     conf->redirects = NULL;
2825      *     conf->ssl = 0;
2826      *     conf->ssl_protocols = 0;
2827      *     conf->ssl_ciphers = { 0, NULL };
2828      *     conf->ssl_trusted_certificate = { 0, NULL };
2829      *     conf->ssl_crl = { 0, NULL };
2830      *     conf->ssl_certificate = { 0, NULL };
2831      *     conf->ssl_certificate_key = { 0, NULL };
2832      */
2833 
2834     conf->upstream.store = NGX_CONF_UNSET;
2835     conf->upstream.store_access = NGX_CONF_UNSET_UINT;
2836     conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
2837     conf->upstream.buffering = NGX_CONF_UNSET;
2838     conf->upstream.request_buffering = NGX_CONF_UNSET;
2839     conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
2840     conf->upstream.force_ranges = NGX_CONF_UNSET;
2841 
2842     conf->upstream.local = NGX_CONF_UNSET_PTR;
2843     conf->upstream.socket_keepalive = NGX_CONF_UNSET;
2844 
2845     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
2846     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
2847     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
2848     conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
2849 
2850     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
2851     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
2852     conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
2853 
2854     conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
2855     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
2856     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
2857 
2858     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
2859     conf->upstream.pass_request_body = NGX_CONF_UNSET;
2860 
2861 #if (NGX_HTTP_CACHE)
2862     conf->upstream.cache = NGX_CONF_UNSET;
2863     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
2864     conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
2865     conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
2866     conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
2867     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
2868     conf->upstream.cache_lock = NGX_CONF_UNSET;
2869     conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
2870     conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
2871     conf->upstream.cache_revalidate = NGX_CONF_UNSET;
2872     conf->upstream.cache_convert_head = NGX_CONF_UNSET;
2873     conf->upstream.cache_background_update = NGX_CONF_UNSET;
2874 #endif
2875 
2876     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
2877     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
2878 
2879     conf->upstream.intercept_errors = NGX_CONF_UNSET;
2880 
2881 #if (NGX_HTTP_SSL)
2882     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
2883     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
2884     conf->upstream.ssl_verify = NGX_CONF_UNSET;
2885     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
2886     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
2887 #endif
2888 
2889     /* "proxy_cyclic_temp_file" is disabled */
2890     conf->upstream.cyclic_temp_file = 0;
2891 
2892     conf->redirect = NGX_CONF_UNSET;
2893     conf->upstream.change_buffering = 1;
2894 
2895     conf->cookie_domains = NGX_CONF_UNSET_PTR;
2896     conf->cookie_paths = NGX_CONF_UNSET_PTR;
2897 
2898     conf->http_version = NGX_CONF_UNSET_UINT;
2899 
2900     conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
2901     conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
2902 
2903     ngx_str_set(&conf->upstream.module, "proxy");
2904 
2905     return conf;
2906 }
2907 
2908 
2909 static char *
2910 ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2911 {
2912     ngx_http_proxy_loc_conf_t *prev = parent;
2913     ngx_http_proxy_loc_conf_t *conf = child;
2914 
2915     u_char                     *p;
2916     size_t                      size;
2917     ngx_int_t                   rc;
2918     ngx_hash_init_t             hash;
2919     ngx_http_core_loc_conf_t   *clcf;
2920     ngx_http_proxy_rewrite_t   *pr;
2921     ngx_http_script_compile_t   sc;
2922 
2923 #if (NGX_HTTP_CACHE)
2924 
2925     if (conf->upstream.store > 0) {
2926         conf->upstream.cache = 0;
2927     }
2928 
2929     if (conf->upstream.cache > 0) {
2930         conf->upstream.store = 0;
2931     }
2932 
2933 #endif
2934 
2935     if (conf->upstream.store == NGX_CONF_UNSET) {
2936         ngx_conf_merge_value(conf->upstream.store,
2937                               prev->upstream.store, 0);
2938 
2939         conf->upstream.store_lengths = prev->upstream.store_lengths;
2940         conf->upstream.store_values = prev->upstream.store_values;
2941     }
2942 
2943     ngx_conf_merge_uint_value(conf->upstream.store_access,
2944                               prev->upstream.store_access, 0600);
2945 
2946     ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
2947                               prev->upstream.next_upstream_tries, 0);
2948 
2949     ngx_conf_merge_value(conf->upstream.buffering,
2950                               prev->upstream.buffering, 1);
2951 
2952     ngx_conf_merge_value(conf->upstream.request_buffering,
2953                               prev->upstream.request_buffering, 1);
2954 
2955     ngx_conf_merge_value(conf->upstream.ignore_client_abort,
2956                               prev->upstream.ignore_client_abort, 0);
2957 
2958     ngx_conf_merge_value(conf->upstream.force_ranges,
2959                               prev->upstream.force_ranges, 0);
2960 
2961     ngx_conf_merge_ptr_value(conf->upstream.local,
2962                               prev->upstream.local, NULL);
2963 
2964     ngx_conf_merge_value(conf->upstream.socket_keepalive,
2965                               prev->upstream.socket_keepalive, 0);
2966 
2967     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
2968                               prev->upstream.connect_timeout, 60000);
2969 
2970     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
2971                               prev->upstream.send_timeout, 60000);
2972 
2973     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
2974                               prev->upstream.read_timeout, 60000);
2975 
2976     ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
2977                               prev->upstream.next_upstream_timeout, 0);
2978 
2979     ngx_conf_merge_size_value(conf->upstream.send_lowat,
2980                               prev->upstream.send_lowat, 0);
2981 
2982     ngx_conf_merge_size_value(conf->upstream.buffer_size,
2983                               prev->upstream.buffer_size,
2984                               (size_t) ngx_pagesize);
2985 
2986     ngx_conf_merge_size_value(conf->upstream.limit_rate,
2987                               prev->upstream.limit_rate, 0);
2988 
2989     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
2990                               8, ngx_pagesize);
2991 
2992     if (conf->upstream.bufs.num < 2) {
2993         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2994                            "there must be at least 2 \"proxy_buffers\"");
2995         return NGX_CONF_ERROR;
2996     }
2997 
2998 
2999     size = conf->upstream.buffer_size;
3000     if (size < conf->upstream.bufs.size) {
3001         size = conf->upstream.bufs.size;
3002     }
3003 
3004 
3005     ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
3006                               prev->upstream.busy_buffers_size_conf,
3007                               NGX_CONF_UNSET_SIZE);
3008 
3009     if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
3010         conf->upstream.busy_buffers_size = 2 * size;
3011     } else {
3012         conf->upstream.busy_buffers_size =
3013                                          conf->upstream.busy_buffers_size_conf;
3014     }
3015 
3016     if (conf->upstream.busy_buffers_size < size) {
3017         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3018              "\"proxy_busy_buffers_size\" must be equal to or greater than "
3019              "the maximum of the value of \"proxy_buffer_size\" and "
3020              "one of the \"proxy_buffers\"");
3021 
3022         return NGX_CONF_ERROR;
3023     }
3024 
3025     if (conf->upstream.busy_buffers_size
3026         > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
3027     {
3028         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3029              "\"proxy_busy_buffers_size\" must be less than "
3030              "the size of all \"proxy_buffers\" minus one buffer");
3031 
3032         return NGX_CONF_ERROR;
3033     }
3034 
3035 
3036     ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
3037                               prev->upstream.temp_file_write_size_conf,
3038                               NGX_CONF_UNSET_SIZE);
3039 
3040     if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
3041         conf->upstream.temp_file_write_size = 2 * size;
3042     } else {
3043         conf->upstream.temp_file_write_size =
3044                                       conf->upstream.temp_file_write_size_conf;
3045     }
3046 
3047     if (conf->upstream.temp_file_write_size < size) {
3048         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3049              "\"proxy_temp_file_write_size\" must be equal to or greater "
3050              "than the maximum of the value of \"proxy_buffer_size\" and "
3051              "one of the \"proxy_buffers\"");
3052 
3053         return NGX_CONF_ERROR;
3054     }
3055 
3056     ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
3057                               prev->upstream.max_temp_file_size_conf,
3058                               NGX_CONF_UNSET_SIZE);
3059 
3060     if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
3061         conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
3062     } else {
3063         conf->upstream.max_temp_file_size =
3064                                         conf->upstream.max_temp_file_size_conf;
3065     }
3066 
3067     if (conf->upstream.max_temp_file_size != 0
3068         && conf->upstream.max_temp_file_size < size)
3069     {
3070         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3071              "\"proxy_max_temp_file_size\" must be equal to zero to disable "
3072              "temporary files usage or must be equal to or greater than "
3073              "the maximum of the value of \"proxy_buffer_size\" and "
3074              "one of the \"proxy_buffers\"");
3075 
3076         return NGX_CONF_ERROR;
3077     }
3078 
3079 
3080     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
3081                               prev->upstream.ignore_headers,
3082                               NGX_CONF_BITMASK_SET);
3083 
3084 
3085     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
3086                               prev->upstream.next_upstream,
3087                               (NGX_CONF_BITMASK_SET
3088                                |NGX_HTTP_UPSTREAM_FT_ERROR
3089                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
3090 
3091     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
3092         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
3093                                        |NGX_HTTP_UPSTREAM_FT_OFF;
3094     }
3095 
3096     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
3097                               prev->upstream.temp_path,
3098                               &ngx_http_proxy_temp_path)
3099         != NGX_OK)
3100     {
3101         return NGX_CONF_ERROR;
3102     }
3103 
3104 
3105 #if (NGX_HTTP_CACHE)
3106 
3107     if (conf->upstream.cache == NGX_CONF_UNSET) {
3108         ngx_conf_merge_value(conf->upstream.cache,
3109                               prev->upstream.cache, 0);
3110 
3111         conf->upstream.cache_zone = prev->upstream.cache_zone;
3112         conf->upstream.cache_value = prev->upstream.cache_value;
3113     }
3114 
3115     if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
3116         ngx_shm_zone_t  *shm_zone;
3117 
3118         shm_zone = conf->upstream.cache_zone;
3119 
3120         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3121                            "\"proxy_cache\" zone \"%V\" is unknown",
3122                            &shm_zone->shm.name);
3123 
3124         return NGX_CONF_ERROR;
3125     }
3126 
3127     ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
3128                               prev->upstream.cache_min_uses, 1);
3129 
3130     ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
3131                               prev->upstream.cache_max_range_offset,
3132                               NGX_MAX_OFF_T_VALUE);
3133 
3134     ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
3135                               prev->upstream.cache_use_stale,
3136                               (NGX_CONF_BITMASK_SET
3137                                |NGX_HTTP_UPSTREAM_FT_OFF));
3138 
3139     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
3140         conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
3141                                          |NGX_HTTP_UPSTREAM_FT_OFF;
3142     }
3143 
3144     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
3145         conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
3146     }
3147 
3148     if (conf->upstream.cache_methods == 0) {
3149         conf->upstream.cache_methods = prev->upstream.cache_methods;
3150     }
3151 
3152     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
3153 
3154     ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
3155                              prev->upstream.cache_bypass, NULL);
3156 
3157     ngx_conf_merge_ptr_value(conf->upstream.no_cache,
3158                              prev->upstream.no_cache, NULL);
3159 
3160     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
3161                              prev->upstream.cache_valid, NULL);
3162 
3163     if (conf->cache_key.value.data == NULL) {
3164         conf->cache_key = prev->cache_key;
3165     }
3166 
3167     ngx_conf_merge_value(conf->upstream.cache_lock,
3168                               prev->upstream.cache_lock, 0);
3169 
3170     ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
3171                               prev->upstream.cache_lock_timeout, 5000);
3172 
3173     ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
3174                               prev->upstream.cache_lock_age, 5000);
3175 
3176     ngx_conf_merge_value(conf->upstream.cache_revalidate,
3177                               prev->upstream.cache_revalidate, 0);
3178 
3179     ngx_conf_merge_value(conf->upstream.cache_convert_head,
3180                               prev->upstream.cache_convert_head, 1);
3181 
3182     ngx_conf_merge_value(conf->upstream.cache_background_update,
3183                               prev->upstream.cache_background_update, 0);
3184 
3185 #endif
3186 
3187     if (conf->method == NULL) {
3188         conf->method = prev->method;
3189     }
3190 
3191     ngx_conf_merge_value(conf->upstream.pass_request_headers,
3192                               prev->upstream.pass_request_headers, 1);
3193     ngx_conf_merge_value(conf->upstream.pass_request_body,
3194                               prev->upstream.pass_request_body, 1);
3195 
3196     ngx_conf_merge_value(conf->upstream.intercept_errors,
3197                               prev->upstream.intercept_errors, 0);
3198 
3199 #if (NGX_HTTP_SSL)
3200 
3201     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
3202                               prev->upstream.ssl_session_reuse, 1);
3203 
3204     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
3205                                  (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
3206                                   |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
3207 
3208     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
3209                              "DEFAULT");
3210 
3211     if (conf->upstream.ssl_name == NULL) {
3212         conf->upstream.ssl_name = prev->upstream.ssl_name;
3213     }
3214 
3215     ngx_conf_merge_value(conf->upstream.ssl_server_name,
3216                               prev->upstream.ssl_server_name, 0);
3217     ngx_conf_merge_value(conf->upstream.ssl_verify,
3218                               prev->upstream.ssl_verify, 0);
3219     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
3220                               prev->ssl_verify_depth, 1);
3221     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
3222                               prev->ssl_trusted_certificate, "");
3223     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
3224 
3225     ngx_conf_merge_str_value(conf->ssl_certificate,
3226                               prev->ssl_certificate, "");
3227     ngx_conf_merge_str_value(conf->ssl_certificate_key,
3228                               prev->ssl_certificate_key, "");
3229     ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
3230 
3231     if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
3232         return NGX_CONF_ERROR;
3233     }
3234 
3235 #endif
3236 
3237     ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
3238 
3239     if (conf->redirect) {
3240 
3241         if (conf->redirects == NULL) {
3242             conf->redirects = prev->redirects;
3243         }
3244 
3245         if (conf->redirects == NULL && conf->url.data) {
3246 
3247             conf->redirects = ngx_array_create(cf->pool, 1,
3248                                              sizeof(ngx_http_proxy_rewrite_t));
3249             if (conf->redirects == NULL) {
3250                 return NGX_CONF_ERROR;
3251             }
3252 
3253             pr = ngx_array_push(conf->redirects);
3254             if (pr == NULL) {
3255                 return NGX_CONF_ERROR;
3256             }
3257 
3258             ngx_memzero(&pr->pattern.complex,
3259                         sizeof(ngx_http_complex_value_t));
3260 
3261             ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
3262 
3263             pr->handler = ngx_http_proxy_rewrite_complex_handler;
3264 
3265             if (conf->vars.uri.len) {
3266                 pr->pattern.complex.value = conf->url;
3267                 pr->replacement.value = conf->location;
3268 
3269             } else {
3270                 pr->pattern.complex.value.len = conf->url.len
3271                                                 + sizeof("/") - 1;
3272 
3273                 p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
3274                 if (p == NULL) {
3275                     return NGX_CONF_ERROR;
3276                 }
3277 
3278                 pr->pattern.complex.value.data = p;
3279 
3280                 p = ngx_cpymem(p, conf->url.data, conf->url.len);
3281                 *p = '/';
3282 
3283                 ngx_str_set(&pr->replacement.value, "/");
3284             }
3285         }
3286     }
3287 
3288     ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL);
3289 
3290     ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
3291 
3292     ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
3293                               NGX_HTTP_VERSION_10);
3294 
3295     ngx_conf_merge_uint_value(conf->headers_hash_max_size,
3296                               prev->headers_hash_max_size, 512);
3297 
3298     ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
3299                               prev->headers_hash_bucket_size, 64);
3300 
3301     conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
3302                                                ngx_cacheline_size);
3303 
3304     hash.max_size = conf->headers_hash_max_size;
3305     hash.bucket_size = conf->headers_hash_bucket_size;
3306     hash.name = "proxy_headers_hash";
3307 
3308     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
3309             &prev->upstream, ngx_http_proxy_hide_headers, &hash)
3310         != NGX_OK)
3311     {
3312         return NGX_CONF_ERROR;
3313     }
3314 
3315     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
3316 
3317     if (clcf->noname
3318         && conf->upstream.upstream == NULL && conf->proxy_lengths == NULL)
3319     {
3320         conf->upstream.upstream = prev->upstream.upstream;
3321         conf->location = prev->location;
3322         conf->vars = prev->vars;
3323 
3324         conf->proxy_lengths = prev->proxy_lengths;
3325         conf->proxy_values = prev->proxy_values;
3326 
3327 #if (NGX_HTTP_SSL)
3328         conf->upstream.ssl = prev->upstream.ssl;
3329 #endif
3330     }
3331 
3332     if (clcf->lmt_excpt && clcf->handler == NULL
3333         && (conf->upstream.upstream || conf->proxy_lengths))
3334     {
3335         clcf->handler = ngx_http_proxy_handler;
3336     }
3337 
3338     if (conf->body_source.data == NULL) {
3339         conf->body_flushes = prev->body_flushes;
3340         conf->body_source = prev->body_source;
3341         conf->body_lengths = prev->body_lengths;
3342         conf->body_values = prev->body_values;
3343     }
3344 
3345     if (conf->body_source.data && conf->body_lengths == NULL) {
3346 
3347         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3348 
3349         sc.cf = cf;
3350         sc.source = &conf->body_source;
3351         sc.flushes = &conf->body_flushes;
3352         sc.lengths = &conf->body_lengths;
3353         sc.values = &conf->body_values;
3354         sc.complete_lengths = 1;
3355         sc.complete_values = 1;
3356 
3357         if (ngx_http_script_compile(&sc) != NGX_OK) {
3358             return NGX_CONF_ERROR;
3359         }
3360     }
3361 
3362     if (conf->headers_source == NULL) {
3363         conf->headers = prev->headers;
3364 #if (NGX_HTTP_CACHE)
3365         conf->headers_cache = prev->headers_cache;
3366 #endif
3367         conf->headers_source = prev->headers_source;
3368     }
3369 
3370     rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers,
3371                                      ngx_http_proxy_headers);
3372     if (rc != NGX_OK) {
3373         return NGX_CONF_ERROR;
3374     }
3375 
3376 #if (NGX_HTTP_CACHE)
3377 
3378     if (conf->upstream.cache) {
3379         rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers_cache,
3380                                          ngx_http_proxy_cache_headers);
3381         if (rc != NGX_OK) {
3382             return NGX_CONF_ERROR;
3383         }
3384     }
3385 
3386 #endif
3387 
3388     /*
3389      * special handling to preserve conf->headers in the "http" section
3390      * to inherit it to all servers
3391      */
3392 
3393     if (prev->headers.hash.buckets == NULL
3394         && conf->headers_source == prev->headers_source)
3395     {
3396         prev->headers = conf->headers;
3397 #if (NGX_HTTP_CACHE)
3398         prev->headers_cache = conf->headers_cache;
3399 #endif
3400     }
3401 
3402     return NGX_CONF_OK;
3403 }
3404 
3405 
3406 static ngx_int_t
3407 ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
3408     ngx_http_proxy_headers_t *headers, ngx_keyval_t *default_headers)
3409 {
3410     u_char                       *p;
3411     size_t                        size;
3412     uintptr_t                    *code;
3413     ngx_uint_t                    i;
3414     ngx_array_t                   headers_names, headers_merged;
3415     ngx_keyval_t                 *src, *s, *h;
3416     ngx_hash_key_t               *hk;
3417     ngx_hash_init_t               hash;
3418     ngx_http_script_compile_t     sc;
3419     ngx_http_script_copy_code_t  *copy;
3420 
3421     if (headers->hash.buckets) {
3422         return NGX_OK;
3423     }
3424 
3425     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
3426         != NGX_OK)
3427     {
3428         return NGX_ERROR;
3429     }
3430 
3431     if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
3432         != NGX_OK)
3433     {
3434         return NGX_ERROR;
3435     }
3436 
3437     headers->lengths = ngx_array_create(cf->pool, 64, 1);
3438     if (headers->lengths == NULL) {
3439         return NGX_ERROR;
3440     }
3441 
3442     headers->values = ngx_array_create(cf->pool, 512, 1);
3443     if (headers->values == NULL) {
3444         return NGX_ERROR;
3445     }
3446 
3447     if (conf->headers_source) {
3448 
3449         src = conf->headers_source->elts;
3450         for (i = 0; i < conf->headers_source->nelts; i++) {
3451 
3452             s = ngx_array_push(&headers_merged);
3453             if (s == NULL) {
3454                 return NGX_ERROR;
3455             }
3456 
3457             *s = src[i];
3458         }
3459     }
3460 
3461     h = default_headers;
3462 
3463     while (h->key.len) {
3464 
3465         src = headers_merged.elts;
3466         for (i = 0; i < headers_merged.nelts; i++) {
3467             if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
3468                 goto next;
3469             }
3470         }
3471 
3472         s = ngx_array_push(&headers_merged);
3473         if (s == NULL) {
3474             return NGX_ERROR;
3475         }
3476 
3477         *s = *h;
3478 
3479     next:
3480 
3481         h++;
3482     }
3483 
3484 
3485     src = headers_merged.elts;
3486     for (i = 0; i < headers_merged.nelts; i++) {
3487 
3488         hk = ngx_array_push(&headers_names);
3489         if (hk == NULL) {
3490             return NGX_ERROR;
3491         }
3492 
3493         hk->key = src[i].key;
3494         hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
3495         hk->value = (void *) 1;
3496 
3497         if (src[i].value.len == 0) {
3498             continue;
3499         }
3500 
3501         copy = ngx_array_push_n(headers->lengths,
3502                                 sizeof(ngx_http_script_copy_code_t));
3503         if (copy == NULL) {
3504             return NGX_ERROR;
3505         }
3506 
3507         copy->code = (ngx_http_script_code_pt) (void *)
3508                                                  ngx_http_script_copy_len_code;
3509         copy->len = src[i].key.len;
3510 
3511         size = (sizeof(ngx_http_script_copy_code_t)
3512                 + src[i].key.len + sizeof(uintptr_t) - 1)
3513                & ~(sizeof(uintptr_t) - 1);
3514 
3515         copy = ngx_array_push_n(headers->values, size);
3516         if (copy == NULL) {
3517             return NGX_ERROR;
3518         }
3519 
3520         copy->code = ngx_http_script_copy_code;
3521         copy->len = src[i].key.len;
3522 
3523         p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
3524         ngx_memcpy(p, src[i].key.data, src[i].key.len);
3525 
3526         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3527 
3528         sc.cf = cf;
3529         sc.source = &src[i].value;
3530         sc.flushes = &headers->flushes;
3531         sc.lengths = &headers->lengths;
3532         sc.values = &headers->values;
3533 
3534         if (ngx_http_script_compile(&sc) != NGX_OK) {
3535             return NGX_ERROR;
3536         }
3537 
3538         code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
3539         if (code == NULL) {
3540             return NGX_ERROR;
3541         }
3542 
3543         *code = (uintptr_t) NULL;
3544 
3545         code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
3546         if (code == NULL) {
3547             return NGX_ERROR;
3548         }
3549 
3550         *code = (uintptr_t) NULL;
3551     }
3552 
3553     code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
3554     if (code == NULL) {
3555         return NGX_ERROR;
3556     }
3557 
3558     *code = (uintptr_t) NULL;
3559 
3560 
3561     hash.hash = &headers->hash;
3562     hash.key = ngx_hash_key_lc;
3563     hash.max_size = conf->headers_hash_max_size;
3564     hash.bucket_size = conf->headers_hash_bucket_size;
3565     hash.name = "proxy_headers_hash";
3566     hash.pool = cf->pool;
3567     hash.temp_pool = NULL;
3568 
3569     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
3570 }
3571 
3572 
3573 static char *
3574 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3575 {
3576     ngx_http_proxy_loc_conf_t *plcf = conf;
3577 
3578     size_t                      add;
3579     u_short                     port;
3580     ngx_str_t                  *value, *url;
3581     ngx_url_t                   u;
3582     ngx_uint_t                  n;
3583     ngx_http_core_loc_conf_t   *clcf;
3584     ngx_http_script_compile_t   sc;
3585 
3586     if (plcf->upstream.upstream || plcf->proxy_lengths) {
3587         return "is duplicate";
3588     }
3589 
3590     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
3591 
3592     clcf->handler = ngx_http_proxy_handler;
3593 
3594     if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
3595         clcf->auto_redirect = 1;
3596     }
3597 
3598     value = cf->args->elts;
3599 
3600     url = &value[1];
3601 
3602     n = ngx_http_script_variables_count(url);
3603 
3604     if (n) {
3605 
3606         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3607 
3608         sc.cf = cf;
3609         sc.source = url;
3610         sc.lengths = &plcf->proxy_lengths;
3611         sc.values = &plcf->proxy_values;
3612         sc.variables = n;
3613         sc.complete_lengths = 1;
3614         sc.complete_values = 1;
3615 
3616         if (ngx_http_script_compile(&sc) != NGX_OK) {
3617             return NGX_CONF_ERROR;
3618         }
3619 
3620 #if (NGX_HTTP_SSL)
3621         plcf->ssl = 1;
3622 #endif
3623 
3624         return NGX_CONF_OK;
3625     }
3626 
3627     if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
3628         add = 7;
3629         port = 80;
3630 
3631     } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
3632 
3633 #if (NGX_HTTP_SSL)
3634         plcf->ssl = 1;
3635 
3636         add = 8;
3637         port = 443;
3638 #else
3639         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3640                            "https protocol requires SSL support");
3641         return NGX_CONF_ERROR;
3642 #endif
3643 
3644     } else {
3645         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
3646         return NGX_CONF_ERROR;
3647     }
3648 
3649     ngx_memzero(&u, sizeof(ngx_url_t));
3650 
3651     u.url.len = url->len - add;
3652     u.url.data = url->data + add;
3653     u.default_port = port;
3654     u.uri_part = 1;
3655     u.no_resolve = 1;
3656 
3657     plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
3658     if (plcf->upstream.upstream == NULL) {
3659         return NGX_CONF_ERROR;
3660     }
3661 
3662     plcf->vars.schema.len = add;
3663     plcf->vars.schema.data = url->data;
3664     plcf->vars.key_start = plcf->vars.schema;
3665 
3666     ngx_http_proxy_set_vars(&u, &plcf->vars);
3667 
3668     plcf->location = clcf->name;
3669 
3670     if (clcf->named
3671 #if (NGX_PCRE)
3672         || clcf->regex
3673 #endif
3674         || clcf->noname)
3675     {
3676         if (plcf->vars.uri.len) {
3677             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3678                                "\"proxy_pass\" cannot have URI part in "
3679                                "location given by regular expression, "
3680                                "or inside named location, "
3681                                "or inside \"if\" statement, "
3682                                "or inside \"limit_except\" block");
3683             return NGX_CONF_ERROR;
3684         }
3685 
3686         plcf->location.len = 0;
3687     }
3688 
3689     plcf->url = *url;
3690 
3691     return NGX_CONF_OK;
3692 }
3693 
3694 
3695 static char *
3696 ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3697 {
3698     ngx_http_proxy_loc_conf_t *plcf = conf;
3699 
3700     u_char                            *p;
3701     ngx_str_t                         *value;
3702     ngx_http_proxy_rewrite_t          *pr;
3703     ngx_http_compile_complex_value_t   ccv;
3704 
3705     if (plcf->redirect == 0) {
3706         return NGX_CONF_OK;
3707     }
3708 
3709     plcf->redirect = 1;
3710 
3711     value = cf->args->elts;
3712 
3713     if (cf->args->nelts == 2) {
3714         if (ngx_strcmp(value[1].data, "off") == 0) {
3715             plcf->redirect = 0;
3716             plcf->redirects = NULL;
3717             return NGX_CONF_OK;
3718         }
3719 
3720         if (ngx_strcmp(value[1].data, "false") == 0) {
3721             ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
3722                            "invalid parameter \"false\", use \"off\" instead");
3723             plcf->redirect = 0;
3724             plcf->redirects = NULL;
3725             return NGX_CONF_OK;
3726         }
3727 
3728         if (ngx_strcmp(value[1].data, "default") != 0) {
3729             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3730                                "invalid parameter \"%V\"", &value[1]);
3731             return NGX_CONF_ERROR;
3732         }
3733     }
3734 
3735     if (plcf->redirects == NULL) {
3736         plcf->redirects = ngx_array_create(cf->pool, 1,
3737                                            sizeof(ngx_http_proxy_rewrite_t));
3738         if (plcf->redirects == NULL) {
3739             return NGX_CONF_ERROR;
3740         }
3741     }
3742 
3743     pr = ngx_array_push(plcf->redirects);
3744     if (pr == NULL) {
3745         return NGX_CONF_ERROR;
3746     }
3747 
3748     if (ngx_strcmp(value[1].data, "default") == 0) {
3749         if (plcf->proxy_lengths) {
3750             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3751                                "\"proxy_redirect default\" cannot be used "
3752                                "with \"proxy_pass\" directive with variables");
3753             return NGX_CONF_ERROR;
3754         }
3755 
3756         if (plcf->url.data == NULL) {
3757             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3758                                "\"proxy_redirect default\" should be placed "
3759                                "after the \"proxy_pass\" directive");
3760             return NGX_CONF_ERROR;
3761         }
3762 
3763         pr->handler = ngx_http_proxy_rewrite_complex_handler;
3764 
3765         ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t));
3766 
3767         ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
3768 
3769         if (plcf->vars.uri.len) {
3770             pr->pattern.complex.value = plcf->url;
3771             pr->replacement.value = plcf->location;
3772 
3773         } else {
3774             pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
3775 
3776             p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
3777             if (p == NULL) {
3778                 return NGX_CONF_ERROR;
3779             }
3780 
3781             pr->pattern.complex.value.data = p;
3782 
3783             p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
3784             *p = '/';
3785 
3786             ngx_str_set(&pr->replacement.value, "/");
3787         }
3788 
3789         return NGX_CONF_OK;
3790     }
3791 
3792 
3793     if (value[1].data[0] == '~') {
3794         value[1].len--;
3795         value[1].data++;
3796 
3797         if (value[1].data[0] == '*') {
3798             value[1].len--;
3799             value[1].data++;
3800 
3801             if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3802                 return NGX_CONF_ERROR;
3803             }
3804 
3805         } else {
3806             if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
3807                 return NGX_CONF_ERROR;
3808             }
3809         }
3810 
3811     } else {
3812 
3813         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3814 
3815         ccv.cf = cf;
3816         ccv.value = &value[1];
3817         ccv.complex_value = &pr->pattern.complex;
3818 
3819         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3820             return NGX_CONF_ERROR;
3821         }
3822 
3823         pr->handler = ngx_http_proxy_rewrite_complex_handler;
3824     }
3825 
3826 
3827     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3828 
3829     ccv.cf = cf;
3830     ccv.value = &value[2];
3831     ccv.complex_value = &pr->replacement;
3832 
3833     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3834         return NGX_CONF_ERROR;
3835     }
3836 
3837     return NGX_CONF_OK;
3838 }
3839 
3840 
3841 static char *
3842 ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3843 {
3844     ngx_http_proxy_loc_conf_t *plcf = conf;
3845 
3846     ngx_str_t                         *value;
3847     ngx_http_proxy_rewrite_t          *pr;
3848     ngx_http_compile_complex_value_t   ccv;
3849 
3850     if (plcf->cookie_domains == NULL) {
3851         return NGX_CONF_OK;
3852     }
3853 
3854     value = cf->args->elts;
3855 
3856     if (cf->args->nelts == 2) {
3857 
3858         if (ngx_strcmp(value[1].data, "off") == 0) {
3859             plcf->cookie_domains = NULL;
3860             return NGX_CONF_OK;
3861         }
3862 
3863         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3864                            "invalid parameter \"%V\"", &value[1]);
3865         return NGX_CONF_ERROR;
3866     }
3867 
3868     if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) {
3869         plcf->cookie_domains = ngx_array_create(cf->pool, 1,
3870                                      sizeof(ngx_http_proxy_rewrite_t));
3871         if (plcf->cookie_domains == NULL) {
3872             return NGX_CONF_ERROR;
3873         }
3874     }
3875 
3876     pr = ngx_array_push(plcf->cookie_domains);
3877     if (pr == NULL) {
3878         return NGX_CONF_ERROR;
3879     }
3880 
3881     if (value[1].data[0] == '~') {
3882         value[1].len--;
3883         value[1].data++;
3884 
3885         if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3886             return NGX_CONF_ERROR;
3887         }
3888 
3889     } else {
3890 
3891         if (value[1].data[0] == '.') {
3892             value[1].len--;
3893             value[1].data++;
3894         }
3895 
3896         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3897 
3898         ccv.cf = cf;
3899         ccv.value = &value[1];
3900         ccv.complex_value = &pr->pattern.complex;
3901 
3902         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3903             return NGX_CONF_ERROR;
3904         }
3905 
3906         pr->handler = ngx_http_proxy_rewrite_domain_handler;
3907 
3908         if (value[2].data[0] == '.') {
3909             value[2].len--;
3910             value[2].data++;
3911         }
3912     }
3913 
3914     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3915 
3916     ccv.cf = cf;
3917     ccv.value = &value[2];
3918     ccv.complex_value = &pr->replacement;
3919 
3920     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3921         return NGX_CONF_ERROR;
3922     }
3923 
3924     return NGX_CONF_OK;
3925 }
3926 
3927 
3928 static char *
3929 ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3930 {
3931     ngx_http_proxy_loc_conf_t *plcf = conf;
3932 
3933     ngx_str_t                         *value;
3934     ngx_http_proxy_rewrite_t          *pr;
3935     ngx_http_compile_complex_value_t   ccv;
3936 
3937     if (plcf->cookie_paths == NULL) {
3938         return NGX_CONF_OK;
3939     }
3940 
3941     value = cf->args->elts;
3942 
3943     if (cf->args->nelts == 2) {
3944 
3945         if (ngx_strcmp(value[1].data, "off") == 0) {
3946             plcf->cookie_paths = NULL;
3947             return NGX_CONF_OK;
3948         }
3949 
3950         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3951                            "invalid parameter \"%V\"", &value[1]);
3952         return NGX_CONF_ERROR;
3953     }
3954 
3955     if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) {
3956         plcf->cookie_paths = ngx_array_create(cf->pool, 1,
3957                                      sizeof(ngx_http_proxy_rewrite_t));
3958         if (plcf->cookie_paths == NULL) {
3959             return NGX_CONF_ERROR;
3960         }
3961     }
3962 
3963     pr = ngx_array_push(plcf->cookie_paths);
3964     if (pr == NULL) {
3965         return NGX_CONF_ERROR;
3966     }
3967 
3968     if (value[1].data[0] == '~') {
3969         value[1].len--;
3970         value[1].data++;
3971 
3972         if (value[1].data[0] == '*') {
3973             value[1].len--;
3974             value[1].data++;
3975 
3976             if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3977                 return NGX_CONF_ERROR;
3978             }
3979 
3980         } else {
3981             if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
3982                 return NGX_CONF_ERROR;
3983             }
3984         }
3985 
3986     } else {
3987 
3988         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3989 
3990         ccv.cf = cf;
3991         ccv.value = &value[1];
3992         ccv.complex_value = &pr->pattern.complex;
3993 
3994         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3995             return NGX_CONF_ERROR;
3996         }
3997 
3998         pr->handler = ngx_http_proxy_rewrite_complex_handler;
3999     }
4000 
4001     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4002 
4003     ccv.cf = cf;
4004     ccv.value = &value[2];
4005     ccv.complex_value = &pr->replacement;
4006 
4007     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4008         return NGX_CONF_ERROR;
4009     }
4010 
4011     return NGX_CONF_OK;
4012 }
4013 
4014 
4015 static ngx_int_t
4016 ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
4017     ngx_str_t *regex, ngx_uint_t caseless)
4018 {
4019 #if (NGX_PCRE)
4020     u_char               errstr[NGX_MAX_CONF_ERRSTR];
4021     ngx_regex_compile_t  rc;
4022 
4023     ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
4024 
4025     rc.pattern = *regex;
4026     rc.err.len = NGX_MAX_CONF_ERRSTR;
4027     rc.err.data = errstr;
4028 
4029     if (caseless) {
4030         rc.options = NGX_REGEX_CASELESS;
4031     }
4032 
4033     pr->pattern.regex = ngx_http_regex_compile(cf, &rc);
4034     if (pr->pattern.regex == NULL) {
4035         return NGX_ERROR;
4036     }
4037 
4038     pr->handler = ngx_http_proxy_rewrite_regex_handler;
4039 
4040     return NGX_OK;
4041 
4042 #else
4043 
4044     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4045                        "using regex \"%V\" requires PCRE library", regex);
4046     return NGX_ERROR;
4047 
4048 #endif
4049 }
4050 
4051 
4052 static char *
4053 ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4054 {
4055     ngx_http_proxy_loc_conf_t *plcf = conf;
4056 
4057     ngx_str_t                  *value;
4058     ngx_http_script_compile_t   sc;
4059 
4060     if (plcf->upstream.store != NGX_CONF_UNSET) {
4061         return "is duplicate";
4062     }
4063 
4064     value = cf->args->elts;
4065 
4066     if (ngx_strcmp(value[1].data, "off") == 0) {
4067         plcf->upstream.store = 0;
4068         return NGX_CONF_OK;
4069     }
4070 
4071 #if (NGX_HTTP_CACHE)
4072     if (plcf->upstream.cache > 0) {
4073         return "is incompatible with \"proxy_cache\"";
4074     }
4075 #endif
4076 
4077     plcf->upstream.store = 1;
4078 
4079     if (ngx_strcmp(value[1].data, "on") == 0) {
4080         return NGX_CONF_OK;
4081     }
4082 
4083     /* include the terminating '\0' into script */
4084     value[1].len++;
4085 
4086     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
4087 
4088     sc.cf = cf;
4089     sc.source = &value[1];
4090     sc.lengths = &plcf->upstream.store_lengths;
4091     sc.values = &plcf->upstream.store_values;
4092     sc.variables = ngx_http_script_variables_count(&value[1]);
4093     sc.complete_lengths = 1;
4094     sc.complete_values = 1;
4095 
4096     if (ngx_http_script_compile(&sc) != NGX_OK) {
4097         return NGX_CONF_ERROR;
4098     }
4099 
4100     return NGX_CONF_OK;
4101 }
4102 
4103 
4104 #if (NGX_HTTP_CACHE)
4105 
4106 static char *
4107 ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4108 {
4109     ngx_http_proxy_loc_conf_t *plcf = conf;
4110 
4111     ngx_str_t                         *value;
4112     ngx_http_complex_value_t           cv;
4113     ngx_http_compile_complex_value_t   ccv;
4114 
4115     value = cf->args->elts;
4116 
4117     if (plcf->upstream.cache != NGX_CONF_UNSET) {
4118         return "is duplicate";
4119     }
4120 
4121     if (ngx_strcmp(value[1].data, "off") == 0) {
4122         plcf->upstream.cache = 0;
4123         return NGX_CONF_OK;
4124     }
4125 
4126     if (plcf->upstream.store > 0) {
4127         return "is incompatible with \"proxy_store\"";
4128     }
4129 
4130     plcf->upstream.cache = 1;
4131 
4132     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4133 
4134     ccv.cf = cf;
4135     ccv.value = &value[1];
4136     ccv.complex_value = &cv;
4137 
4138     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4139         return NGX_CONF_ERROR;
4140     }
4141 
4142     if (cv.lengths != NULL) {
4143 
4144         plcf->upstream.cache_value = ngx_palloc(cf->pool,
4145                                              sizeof(ngx_http_complex_value_t));
4146         if (plcf->upstream.cache_value == NULL) {
4147             return NGX_CONF_ERROR;
4148         }
4149 
4150         *plcf->upstream.cache_value = cv;
4151 
4152         return NGX_CONF_OK;
4153     }
4154 
4155     plcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
4156                                                       &ngx_http_proxy_module);
4157     if (plcf->upstream.cache_zone == NULL) {
4158         return NGX_CONF_ERROR;
4159     }
4160 
4161     return NGX_CONF_OK;
4162 }
4163 
4164 
4165 static char *
4166 ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4167 {
4168     ngx_http_proxy_loc_conf_t *plcf = conf;
4169 
4170     ngx_str_t                         *value;
4171     ngx_http_compile_complex_value_t   ccv;
4172 
4173     value = cf->args->elts;
4174 
4175     if (plcf->cache_key.value.data) {
4176         return "is duplicate";
4177     }
4178 
4179     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4180 
4181     ccv.cf = cf;
4182     ccv.value = &value[1];
4183     ccv.complex_value = &plcf->cache_key;
4184 
4185     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4186         return NGX_CONF_ERROR;
4187     }
4188 
4189     return NGX_CONF_OK;
4190 }
4191 
4192 #endif
4193 
4194 
4195 #if (NGX_HTTP_SSL)
4196 
4197 static char *
4198 ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4199 {
4200     ngx_http_proxy_loc_conf_t *plcf = conf;
4201 
4202     ngx_str_t  *value;
4203 
4204     if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
4205         return "is duplicate";
4206     }
4207 
4208     value = cf->args->elts;
4209 
4210     plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
4211 
4212     if (plcf->ssl_passwords == NULL) {
4213         return NGX_CONF_ERROR;
4214     }
4215 
4216     return NGX_CONF_OK;
4217 }
4218 
4219 #endif
4220 
4221 
4222 static char *
4223 ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
4224 {
4225 #if (NGX_FREEBSD)
4226     ssize_t *np = data;
4227 
4228     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4229         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4230                            "\"proxy_send_lowat\" must be less than %d "
4231                            "(sysctl net.inet.tcp.sendspace)",
4232                            ngx_freebsd_net_inet_tcp_sendspace);
4233 
4234         return NGX_CONF_ERROR;
4235     }
4236 
4237 #elif !(NGX_HAVE_SO_SNDLOWAT)
4238     ssize_t *np = data;
4239 
4240     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4241                        "\"proxy_send_lowat\" is not supported, ignored");
4242 
4243     *np = 0;
4244 
4245 #endif
4246 
4247     return NGX_CONF_OK;
4248 }
4249 
4250 
4251 #if (NGX_HTTP_SSL)
4252 
4253 static ngx_int_t
4254 ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
4255 {
4256     ngx_pool_cleanup_t  *cln;
4257 
4258     plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
4259     if (plcf->upstream.ssl == NULL) {
4260         return NGX_ERROR;
4261     }
4262 
4263     plcf->upstream.ssl->log = cf->log;
4264 
4265     if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
4266         != NGX_OK)
4267     {
4268         return NGX_ERROR;
4269     }
4270 
4271     cln = ngx_pool_cleanup_add(cf->pool, 0);
4272     if (cln == NULL) {
4273         ngx_ssl_cleanup_ctx(plcf->upstream.ssl);
4274         return NGX_ERROR;
4275     }
4276 
4277     cln->handler = ngx_ssl_cleanup_ctx;
4278     cln->data = plcf->upstream.ssl;
4279 
4280     if (plcf->ssl_certificate.len) {
4281 
4282         if (plcf->ssl_certificate_key.len == 0) {
4283             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
4284                           "no \"proxy_ssl_certificate_key\" is defined "
4285                           "for certificate \"%V\"", &plcf->ssl_certificate);
4286             return NGX_ERROR;
4287         }
4288 
4289         if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate,
4290                                 &plcf->ssl_certificate_key, plcf->ssl_passwords)
4291             != NGX_OK)
4292         {
4293             return NGX_ERROR;
4294         }
4295     }
4296 
4297     if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
4298         != NGX_OK)
4299     {
4300         return NGX_ERROR;
4301     }
4302 
4303     if (plcf->upstream.ssl_verify) {
4304         if (plcf->ssl_trusted_certificate.len == 0) {
4305             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
4306                       "no proxy_ssl_trusted_certificate for proxy_ssl_verify");
4307             return NGX_ERROR;
4308         }
4309 
4310         if (ngx_ssl_trusted_certificate(cf, plcf->upstream.ssl,
4311                                         &plcf->ssl_trusted_certificate,
4312                                         plcf->ssl_verify_depth)
4313             != NGX_OK)
4314         {
4315             return NGX_ERROR;
4316         }
4317 
4318         if (ngx_ssl_crl(cf, plcf->upstream.ssl, &plcf->ssl_crl) != NGX_OK) {
4319             return NGX_ERROR;
4320         }
4321     }
4322 
4323     if (ngx_ssl_client_session_cache(cf, plcf->upstream.ssl,
4324                                      plcf->upstream.ssl_session_reuse)
4325         != NGX_OK)
4326     {
4327         return NGX_ERROR;
4328     }
4329 
4330     return NGX_OK;
4331 }
4332 
4333 #endif
4334 
4335 
4336 static void
4337 ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
4338 {
4339     if (u->family != AF_UNIX) {
4340 
4341         if (u->no_port || u->port == u->default_port) {
4342 
4343             v->host_header = u->host;
4344 
4345             if (u->default_port == 80) {
4346                 ngx_str_set(&v->port, "80");
4347 
4348             } else {
4349                 ngx_str_set(&v->port, "443");
4350             }
4351 
4352         } else {
4353             v->host_header.len = u->host.len + 1 + u->port_text.len;
4354             v->host_header.data = u->host.data;
4355             v->port = u->port_text;
4356         }
4357 
4358         v->key_start.len += v->host_header.len;
4359 
4360     } else {
4361         ngx_str_set(&v->host_header, "localhost");
4362         ngx_str_null(&v->port);
4363         v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
4364     }
4365 
4366     v->uri = u->uri;
4367 }