Back to home page

Nginx displayed by LXR

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