Changes between Initial Version and Version 1 of Ticket #13


Ignore:
Timestamp:
09/14/11 01:09:58 (9 years ago)
Author:
Maxim Dounin
Comment:

Please see patch review in nginx-devel@ mailing list.

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #13

    • Property Status newaccepted
    • Property Version 0.8.x
  • Ticket #13 – Description

    initial v1  
    1 Enable verification of the SSL certificate presented to the http_proxy_module.
    2 
    3 
    4 {{{
    5 diff -uNr ../nginx-0.8.55/src/event/ngx_event_openssl.c src/event/ngx_event_openssl.c
    6 --- ../nginx-0.8.55/src/event/ngx_event_openssl.c       2010-07-29 02:30:15.000000000 -0700
    7 +++ src/event/ngx_event_openssl.c       2011-09-13 15:27:08.000000000 -0700
    8 @@ -157,6 +157,12 @@
    9      SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
    10      SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
    11  
    12 +    /* verification options */
    13 +
    14 +    SSL_CTX_load_verify_locations(ssl->ctx, (const char *)ssl->ca_certificate.data, NULL);
    15 +    SSL_CTX_set_verify(ssl->ctx, ssl->verify, NULL);
    16 +    SSL_CTX_set_verify_depth(ssl->ctx, ssl->verify_depth);
    17 +
    18      /* server side options */
    19  
    20      SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
    21 diff -uNr ../nginx-0.8.55/src/event/ngx_event_openssl.h src/event/ngx_event_openssl.h
    22 --- ../nginx-0.8.55/src/event/ngx_event_openssl.h       2010-03-03 08:23:14.000000000 -0800
    23 +++ src/event/ngx_event_openssl.h       2011-09-13 15:27:08.000000000 -0700
    24 @@ -27,6 +27,9 @@
    25  typedef struct {
    26      SSL_CTX                    *ctx;
    27      ngx_log_t                  *log;
    28 +    ngx_uint_t                  verify;
    29 +    ngx_uint_t                  verify_depth;
    30 +    ngx_str_t                   ca_certificate;
    31  } ngx_ssl_t;
    32  
    33  
    34 diff -uNr ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_proxy_module.c
    35 --- ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c    2010-08-03 05:59:14.000000000 -0700
    36 +++ src/http/modules/ngx_http_proxy_module.c    2011-09-13 15:27:08.000000000 -0700
    37 @@ -441,6 +441,27 @@
    38        offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
    39        NULL },
    40  
    41 +      { ngx_string("proxy_ssl_verify"),
    42 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    43 +      ngx_conf_set_num_slot,
    44 +      NGX_HTTP_LOC_CONF_OFFSET,
    45 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify),
    46 +      NULL },
    47 +
    48 +      { ngx_string("proxy_ssl_verify_depth"),
    49 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    50 +      ngx_conf_set_num_slot,
    51 +      NGX_HTTP_LOC_CONF_OFFSET,
    52 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_depth),
    53 +      NULL },
    54 +
    55 +      { ngx_string("proxy_ssl_ca_certificate"),
    56 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    57 +      ngx_conf_set_str_slot,
    58 +      NGX_HTTP_LOC_CONF_OFFSET,
    59 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_ca_certificate),
    60 +      NULL },
    61 +
    62  #endif
    63  
    64        ngx_null_command
    65 @@ -1696,6 +1717,8 @@
    66      conf->upstream.intercept_errors = NGX_CONF_UNSET;
    67  #if (NGX_HTTP_SSL)
    68      conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
    69 +    conf->upstream.ssl_verify = NGX_CONF_UNSET_UINT;
    70 +    conf->upstream.ssl_verify_depth = NGX_CONF_UNSET_UINT;
    71  #endif
    72  
    73      /* "proxy_cyclic_temp_file" is disabled */
    74 @@ -1951,6 +1974,22 @@
    75  #if (NGX_HTTP_SSL)
    76      ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
    77                                prev->upstream.ssl_session_reuse, 1);
    78 +    ngx_conf_merge_uint_value(conf->upstream.ssl_verify,
    79 +                              prev->upstream.ssl_verify, 0);
    80 +    ngx_conf_merge_uint_value(conf->upstream.ssl_verify_depth,
    81 +                              prev->upstream.ssl_verify_depth, 1);
    82 +    ngx_conf_merge_str_value(conf->upstream.ssl_ca_certificate,
    83 +                              prev->upstream.ssl_ca_certificate, "");
    84 +
    85 +    if (conf->upstream.ssl_verify) {
    86 +      if (conf->upstream.ssl_ca_certificate.len == 0) {
    87 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    88 +            "no \"proxy_ssl_ca_certificate\" is defined for "
    89 +            "the \"proxy_ssl_verify\" directive");
    90 +
    91 +        return NGX_CONF_ERROR;
    92 +      }
    93 +    }
    94  #endif
    95  
    96      ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
    97 @@ -2727,6 +2766,12 @@
    98  
    99      plcf->upstream.ssl->log = cf->log;
    100  
    101 +    plcf->upstream.ssl->ca_certificate.len = plcf->upstream.ssl_ca_certificate.len;
    102 +    plcf->upstream.ssl->ca_certificate.data = plcf->upstream.ssl_ca_certificate.data;
    103 +
    104 +    plcf->upstream.ssl->verify = plcf->upstream.ssl_verify;
    105 +    plcf->upstream.ssl->verify_depth = plcf->upstream.ssl_verify_depth;
    106 +
    107      if (ngx_ssl_create(plcf->upstream.ssl,
    108                         NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
    109          != NGX_OK)
    110 diff -uNr ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c.orig src/http/modules/ngx_http_proxy_module.c.orig
    111 --- ../nginx-0.8.55/src/http/modules/ngx_http_proxy_module.c.orig       1969-12-31 16:00:00.000000000 -0800
    112 +++ src/http/modules/ngx_http_proxy_module.c.orig       2010-08-03 05:59:14.000000000 -0700
    113 @@ -0,0 +1,2782 @@
    114 +
    115 +/*
    116 + * Copyright (C) Igor Sysoev
    117 + */
    118 +
    119 +
    120 +#include <ngx_config.h>
    121 +#include <ngx_core.h>
    122 +#include <ngx_http.h>
    123 +
    124 +
    125 +typedef struct ngx_http_proxy_redirect_s  ngx_http_proxy_redirect_t;
    126 +
    127 +typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
    128 +    ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
    129 +
    130 +struct ngx_http_proxy_redirect_s {
    131 +    ngx_http_proxy_redirect_pt     handler;
    132 +    ngx_str_t                      redirect;
    133 +
    134 +    union {
    135 +        ngx_str_t                  text;
    136 +
    137 +        struct {
    138 +            void                  *lengths;
    139 +            void                  *values;
    140 +        } vars;
    141 +
    142 +        void                      *regex;
    143 +    } replacement;
    144 +};
    145 +
    146 +
    147 +typedef struct {
    148 +    ngx_str_t                      key_start;
    149 +    ngx_str_t                      schema;
    150 +    ngx_str_t                      host_header;
    151 +    ngx_str_t                      port;
    152 +    ngx_str_t                      uri;
    153 +} ngx_http_proxy_vars_t;
    154 +
    155 +
    156 +typedef struct {
    157 +    ngx_http_upstream_conf_t       upstream;
    158 +
    159 +    ngx_array_t                   *flushes;
    160 +    ngx_array_t                   *body_set_len;
    161 +    ngx_array_t                   *body_set;
    162 +    ngx_array_t                   *headers_set_len;
    163 +    ngx_array_t                   *headers_set;
    164 +    ngx_hash_t                     headers_set_hash;
    165 +
    166 +    ngx_array_t                   *headers_source;
    167 +
    168 +    ngx_array_t                   *proxy_lengths;
    169 +    ngx_array_t                   *proxy_values;
    170 +
    171 +    ngx_array_t                   *redirects;
    172 +
    173 +    ngx_str_t                      body_source;
    174 +
    175 +    ngx_str_t                      method;
    176 +    ngx_str_t                      location;
    177 +    ngx_str_t                      url;
    178 +
    179 +#if (NGX_HTTP_CACHE)
    180 +    ngx_http_complex_value_t       cache_key;
    181 +#endif
    182 +
    183 +    ngx_http_proxy_vars_t          vars;
    184 +
    185 +    ngx_flag_t                     redirect;
    186 +
    187 +    ngx_uint_t                     headers_hash_max_size;
    188 +    ngx_uint_t                     headers_hash_bucket_size;
    189 +} ngx_http_proxy_loc_conf_t;
    190 +
    191 +
    192 +typedef struct {
    193 +    ngx_http_status_t              status;
    194 +    ngx_http_proxy_vars_t          vars;
    195 +    size_t                         internal_body_length;
    196 +} ngx_http_proxy_ctx_t;
    197 +
    198 +
    199 +static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
    200 +    ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
    201 +#if (NGX_HTTP_CACHE)
    202 +static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
    203 +#endif
    204 +static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
    205 +static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
    206 +static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
    207 +static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
    208 +static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
    209 +static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
    210 +    ngx_int_t rc);
    211 +
    212 +static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
    213 +    ngx_http_variable_value_t *v, uintptr_t data);
    214 +static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
    215 +    ngx_http_variable_value_t *v, uintptr_t data);
    216 +static ngx_int_t
    217 +    ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
    218 +    ngx_http_variable_value_t *v, uintptr_t data);
    219 +static ngx_int_t
    220 +    ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
    221 +    ngx_http_variable_value_t *v, uintptr_t data);
    222 +static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
    223 +    ngx_table_elt_t *h, size_t prefix);
    224 +
    225 +static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
    226 +static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
    227 +static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
    228 +    void *parent, void *child);
    229 +static ngx_int_t ngx_http_proxy_merge_headers(ngx_conf_t *cf,
    230 +    ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
    231 +
    232 +static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
    233 +    void *conf);
    234 +static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
    235 +    void *conf);
    236 +static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
    237 +    void *conf);
    238 +#if (NGX_HTTP_CACHE)
    239 +static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
    240 +    void *conf);
    241 +static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
    242 +    void *conf);
    243 +#endif
    244 +
    245 +static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
    246 +
    247 +#if (NGX_HTTP_SSL)
    248 +static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
    249 +    ngx_http_proxy_loc_conf_t *plcf);
    250 +#endif
    251 +static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
    252 +
    253 +
    254 +static ngx_conf_post_t  ngx_http_proxy_lowat_post =
    255 +    { ngx_http_proxy_lowat_check };
    256 +
    257 +
    258 +static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
    259 +    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
    260 +    { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
    261 +    { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
    262 +    { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
    263 +    { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
    264 +    { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
    265 +    { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
    266 +    { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
    267 +    { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
    268 +    { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
    269 +    { ngx_null_string, 0 }
    270 +};
    271 +
    272 +
    273 +ngx_module_t  ngx_http_proxy_module;
    274 +
    275 +
    276 +static ngx_command_t  ngx_http_proxy_commands[] = {
    277 +
    278 +    { ngx_string("proxy_pass"),
    279 +      NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
    280 +      ngx_http_proxy_pass,
    281 +      NGX_HTTP_LOC_CONF_OFFSET,
    282 +      0,
    283 +      NULL },
    284 +
    285 +    { ngx_string("proxy_redirect"),
    286 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
    287 +      ngx_http_proxy_redirect,
    288 +      NGX_HTTP_LOC_CONF_OFFSET,
    289 +      0,
    290 +      NULL },
    291 +
    292 +    { ngx_string("proxy_store"),
    293 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    294 +      ngx_http_proxy_store,
    295 +      NGX_HTTP_LOC_CONF_OFFSET,
    296 +      0,
    297 +      NULL },
    298 +
    299 +    { ngx_string("proxy_store_access"),
    300 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
    301 +      ngx_conf_set_access_slot,
    302 +      NGX_HTTP_LOC_CONF_OFFSET,
    303 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access),
    304 +      NULL },
    305 +
    306 +    { ngx_string("proxy_buffering"),
    307 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    308 +      ngx_conf_set_flag_slot,
    309 +      NGX_HTTP_LOC_CONF_OFFSET,
    310 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
    311 +      NULL },
    312 +
    313 +    { ngx_string("proxy_ignore_client_abort"),
    314 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    315 +      ngx_conf_set_flag_slot,
    316 +      NGX_HTTP_LOC_CONF_OFFSET,
    317 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
    318 +      NULL },
    319 +
    320 +    { ngx_string("proxy_bind"),
    321 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    322 +      ngx_http_upstream_bind_set_slot,
    323 +      NGX_HTTP_LOC_CONF_OFFSET,
    324 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
    325 +      NULL },
    326 +
    327 +    { ngx_string("proxy_connect_timeout"),
    328 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    329 +      ngx_conf_set_msec_slot,
    330 +      NGX_HTTP_LOC_CONF_OFFSET,
    331 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
    332 +      NULL },
    333 +
    334 +    { ngx_string("proxy_send_timeout"),
    335 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    336 +      ngx_conf_set_msec_slot,
    337 +      NGX_HTTP_LOC_CONF_OFFSET,
    338 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
    339 +      NULL },
    340 +
    341 +    { ngx_string("proxy_send_lowat"),
    342 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    343 +      ngx_conf_set_size_slot,
    344 +      NGX_HTTP_LOC_CONF_OFFSET,
    345 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
    346 +      &ngx_http_proxy_lowat_post },
    347 +
    348 +    { ngx_string("proxy_intercept_errors"),
    349 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    350 +      ngx_conf_set_flag_slot,
    351 +      NGX_HTTP_LOC_CONF_OFFSET,
    352 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors),
    353 +      NULL },
    354 +
    355 +    { ngx_string("proxy_set_header"),
    356 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
    357 +      ngx_conf_set_keyval_slot,
    358 +      NGX_HTTP_LOC_CONF_OFFSET,
    359 +      offsetof(ngx_http_proxy_loc_conf_t, headers_source),
    360 +      NULL },
    361 +
    362 +    { ngx_string("proxy_headers_hash_max_size"),
    363 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    364 +      ngx_conf_set_num_slot,
    365 +      NGX_HTTP_LOC_CONF_OFFSET,
    366 +      offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size),
    367 +      NULL },
    368 +
    369 +    { ngx_string("proxy_headers_hash_bucket_size"),
    370 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    371 +      ngx_conf_set_num_slot,
    372 +      NGX_HTTP_LOC_CONF_OFFSET,
    373 +      offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size),
    374 +      NULL },
    375 +
    376 +    { ngx_string("proxy_set_body"),
    377 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    378 +      ngx_conf_set_str_slot,
    379 +      NGX_HTTP_LOC_CONF_OFFSET,
    380 +      offsetof(ngx_http_proxy_loc_conf_t, body_source),
    381 +      NULL },
    382 +
    383 +    { ngx_string("proxy_method"),
    384 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    385 +      ngx_conf_set_str_slot,
    386 +      NGX_HTTP_LOC_CONF_OFFSET,
    387 +      offsetof(ngx_http_proxy_loc_conf_t, method),
    388 +      NULL },
    389 +
    390 +    { ngx_string("proxy_pass_request_headers"),
    391 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    392 +      ngx_conf_set_flag_slot,
    393 +      NGX_HTTP_LOC_CONF_OFFSET,
    394 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
    395 +      NULL },
    396 +
    397 +    { ngx_string("proxy_pass_request_body"),
    398 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    399 +      ngx_conf_set_flag_slot,
    400 +      NGX_HTTP_LOC_CONF_OFFSET,
    401 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
    402 +      NULL },
    403 +
    404 +    { ngx_string("proxy_buffer_size"),
    405 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    406 +      ngx_conf_set_size_slot,
    407 +      NGX_HTTP_LOC_CONF_OFFSET,
    408 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size),
    409 +      NULL },
    410 +
    411 +    { ngx_string("proxy_read_timeout"),
    412 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    413 +      ngx_conf_set_msec_slot,
    414 +      NGX_HTTP_LOC_CONF_OFFSET,
    415 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
    416 +      NULL },
    417 +
    418 +    { ngx_string("proxy_buffers"),
    419 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
    420 +      ngx_conf_set_bufs_slot,
    421 +      NGX_HTTP_LOC_CONF_OFFSET,
    422 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
    423 +      NULL },
    424 +
    425 +    { ngx_string("proxy_busy_buffers_size"),
    426 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    427 +      ngx_conf_set_size_slot,
    428 +      NGX_HTTP_LOC_CONF_OFFSET,
    429 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
    430 +      NULL },
    431 +
    432 +#if (NGX_HTTP_CACHE)
    433 +
    434 +    { ngx_string("proxy_cache"),
    435 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    436 +      ngx_http_proxy_cache,
    437 +      NGX_HTTP_LOC_CONF_OFFSET,
    438 +      0,
    439 +      NULL },
    440 +
    441 +    { ngx_string("proxy_cache_key"),
    442 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    443 +      ngx_http_proxy_cache_key,
    444 +      NGX_HTTP_LOC_CONF_OFFSET,
    445 +      0,
    446 +      NULL },
    447 +
    448 +    { ngx_string("proxy_cache_path"),
    449 +      NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
    450 +      ngx_http_file_cache_set_slot,
    451 +      0,
    452 +      0,
    453 +      &ngx_http_proxy_module },
    454 +
    455 +    { ngx_string("proxy_cache_bypass"),
    456 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    457 +      ngx_http_set_predicate_slot,
    458 +      NGX_HTTP_LOC_CONF_OFFSET,
    459 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
    460 +      NULL },
    461 +
    462 +    { ngx_string("proxy_no_cache"),
    463 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    464 +      ngx_http_set_predicate_slot,
    465 +      NGX_HTTP_LOC_CONF_OFFSET,
    466 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
    467 +      NULL },
    468 +
    469 +    { ngx_string("proxy_cache_valid"),
    470 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    471 +      ngx_http_file_cache_valid_set_slot,
    472 +      NGX_HTTP_LOC_CONF_OFFSET,
    473 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
    474 +      NULL },
    475 +
    476 +    { ngx_string("proxy_cache_min_uses"),
    477 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    478 +      ngx_conf_set_num_slot,
    479 +      NGX_HTTP_LOC_CONF_OFFSET,
    480 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
    481 +      NULL },
    482 +
    483 +    { ngx_string("proxy_cache_use_stale"),
    484 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    485 +      ngx_conf_set_bitmask_slot,
    486 +      NGX_HTTP_LOC_CONF_OFFSET,
    487 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
    488 +      &ngx_http_proxy_next_upstream_masks },
    489 +
    490 +    { ngx_string("proxy_cache_methods"),
    491 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    492 +      ngx_conf_set_bitmask_slot,
    493 +      NGX_HTTP_LOC_CONF_OFFSET,
    494 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
    495 +      &ngx_http_upstream_cache_method_mask },
    496 +
    497 +#endif
    498 +
    499 +    { ngx_string("proxy_temp_path"),
    500 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
    501 +      ngx_conf_set_path_slot,
    502 +      NGX_HTTP_LOC_CONF_OFFSET,
    503 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
    504 +      NULL },
    505 +
    506 +    { ngx_string("proxy_max_temp_file_size"),
    507 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    508 +      ngx_conf_set_size_slot,
    509 +      NGX_HTTP_LOC_CONF_OFFSET,
    510 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf),
    511 +      NULL },
    512 +
    513 +    { ngx_string("proxy_temp_file_write_size"),
    514 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    515 +      ngx_conf_set_size_slot,
    516 +      NGX_HTTP_LOC_CONF_OFFSET,
    517 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf),
    518 +      NULL },
    519 +
    520 +    { ngx_string("proxy_next_upstream"),
    521 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    522 +      ngx_conf_set_bitmask_slot,
    523 +      NGX_HTTP_LOC_CONF_OFFSET,
    524 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
    525 +      &ngx_http_proxy_next_upstream_masks },
    526 +
    527 +    { ngx_string("proxy_pass_header"),
    528 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    529 +      ngx_conf_set_str_array_slot,
    530 +      NGX_HTTP_LOC_CONF_OFFSET,
    531 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
    532 +      NULL },
    533 +
    534 +    { ngx_string("proxy_hide_header"),
    535 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
    536 +      ngx_conf_set_str_array_slot,
    537 +      NGX_HTTP_LOC_CONF_OFFSET,
    538 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
    539 +      NULL },
    540 +
    541 +    { ngx_string("proxy_ignore_headers"),
    542 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
    543 +      ngx_conf_set_bitmask_slot,
    544 +      NGX_HTTP_LOC_CONF_OFFSET,
    545 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
    546 +      &ngx_http_upstream_ignore_headers_masks },
    547 +
    548 +#if (NGX_HTTP_SSL)
    549 +
    550 +    { ngx_string("proxy_ssl_session_reuse"),
    551 +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
    552 +      ngx_conf_set_flag_slot,
    553 +      NGX_HTTP_LOC_CONF_OFFSET,
    554 +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
    555 +      NULL },
    556 +
    557 +#endif
    558 +
    559 +      ngx_null_command
    560 +};
    561 +
    562 +
    563 +static ngx_http_module_t  ngx_http_proxy_module_ctx = {
    564 +    ngx_http_proxy_add_variables,          /* preconfiguration */
    565 +    NULL,                                  /* postconfiguration */
    566 +
    567 +    NULL,                                  /* create main configuration */
    568 +    NULL,                                  /* init main configuration */
    569 +
    570 +    NULL,                                  /* create server configuration */
    571 +    NULL,                                  /* merge server configuration */
    572 +
    573 +    ngx_http_proxy_create_loc_conf,        /* create location configration */
    574 +    ngx_http_proxy_merge_loc_conf          /* merge location configration */
    575 +};
    576 +
    577 +
    578 +ngx_module_t  ngx_http_proxy_module = {
    579 +    NGX_MODULE_V1,
    580 +    &ngx_http_proxy_module_ctx,            /* module context */
    581 +    ngx_http_proxy_commands,               /* module directives */
    582 +    NGX_HTTP_MODULE,                       /* module type */
    583 +    NULL,                                  /* init master */
    584 +    NULL,                                  /* init module */
    585 +    NULL,                                  /* init process */
    586 +    NULL,                                  /* init thread */
    587 +    NULL,                                  /* exit thread */
    588 +    NULL,                                  /* exit process */
    589 +    NULL,                                  /* exit master */
    590 +    NGX_MODULE_V1_PADDING
    591 +};
    592 +
    593 +
    594 +static char  ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
    595 +
    596 +
    597 +static ngx_keyval_t  ngx_http_proxy_headers[] = {
    598 +    { ngx_string("Host"), ngx_string("$proxy_host") },
    599 +    { ngx_string("Connection"), ngx_string("close") },
    600 +    { ngx_string("Keep-Alive"), ngx_string("") },
    601 +    { ngx_string("Expect"), ngx_string("") },
    602 +    { ngx_null_string, ngx_null_string }
    603 +};
    604 +
    605 +
    606 +static ngx_str_t  ngx_http_proxy_hide_headers[] = {
    607 +    ngx_string("Date"),
    608 +    ngx_string("Server"),
    609 +    ngx_string("X-Pad"),
    610 +    ngx_string("X-Accel-Expires"),
    611 +    ngx_string("X-Accel-Redirect"),
    612 +    ngx_string("X-Accel-Limit-Rate"),
    613 +    ngx_string("X-Accel-Buffering"),
    614 +    ngx_string("X-Accel-Charset"),
    615 +    ngx_null_string
    616 +};
    617 +
    618 +
    619 +#if (NGX_HTTP_CACHE)
    620 +
    621 +static ngx_keyval_t  ngx_http_proxy_cache_headers[] = {
    622 +    { ngx_string("Host"), ngx_string("$proxy_host") },
    623 +    { ngx_string("Connection"), ngx_string("close") },
    624 +    { ngx_string("Keep-Alive"), ngx_string("") },
    625 +    { ngx_string("Expect"), ngx_string("") },
    626 +    { ngx_string("If-Modified-Since"), ngx_string("") },
    627 +    { ngx_string("If-Unmodified-Since"), ngx_string("") },
    628 +    { ngx_string("If-None-Match"), ngx_string("") },
    629 +    { ngx_string("If-Match"), ngx_string("") },
    630 +    { ngx_string("Range"), ngx_string("") },
    631 +    { ngx_string("If-Range"), ngx_string("") },
    632 +    { ngx_null_string, ngx_null_string }
    633 +};
    634 +
    635 +#endif
    636 +
    637 +
    638 +static ngx_http_variable_t  ngx_http_proxy_vars[] = {
    639 +
    640 +    { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
    641 +      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
    642 +
    643 +    { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
    644 +      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
    645 +
    646 +    { ngx_string("proxy_add_x_forwarded_for"), NULL,
    647 +      ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
    648 +
    649 +#if 0
    650 +    { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
    651 +#endif
    652 +
    653 +    { ngx_string("proxy_internal_body_length"), NULL,
    654 +      ngx_http_proxy_internal_body_length_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
    655 +
    656 +    { ngx_null_string, NULL, NULL, 0, 0, 0 }
    657 +};
    658 +
    659 +
    660 +static ngx_path_init_t  ngx_http_proxy_temp_path = {
    661 +    ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
    662 +};
    663 +
    664 +
    665 +static ngx_int_t
    666 +ngx_http_proxy_handler(ngx_http_request_t *r)
    667 +{
    668 +    ngx_int_t                   rc;
    669 +    ngx_http_upstream_t        *u;
    670 +    ngx_http_proxy_ctx_t       *ctx;
    671 +    ngx_http_proxy_loc_conf_t  *plcf;
    672 +
    673 +    if (ngx_http_upstream_create(r) != NGX_OK) {
    674 +        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    675 +    }
    676 +
    677 +    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
    678 +    if (ctx == NULL) {
    679 +        return NGX_ERROR;
    680 +    }
    681 +
    682 +    ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
    683 +
    684 +    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
    685 +
    686 +    u = r->upstream;
    687 +
    688 +    if (plcf->proxy_lengths == NULL) {
    689 +        ctx->vars = plcf->vars;
    690 +        u->schema = plcf->vars.schema;
    691 +#if (NGX_HTTP_SSL)
    692 +        u->ssl = (plcf->upstream.ssl != NULL);
    693 +#endif
    694 +
    695 +    } else {
    696 +        if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
    697 +            return NGX_HTTP_INTERNAL_SERVER_ERROR;
    698 +        }
    699 +    }
    700 +
    701 +    u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
    702 +
    703 +    u->conf = &plcf->upstream;
    704 +
    705 +#if (NGX_HTTP_CACHE)
    706 +    u->create_key = ngx_http_proxy_create_key;
    707 +#endif
    708 +    u->create_request = ngx_http_proxy_create_request;
    709 +    u->reinit_request = ngx_http_proxy_reinit_request;
    710 +    u->process_header = ngx_http_proxy_process_status_line;
    711 +    u->abort_request = ngx_http_proxy_abort_request;
    712 +    u->finalize_request = ngx_http_proxy_finalize_request;
    713 +    r->state = 0;
    714 +
    715 +    if (plcf->redirects) {
    716 +        u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
    717 +    }
    718 +
    719 +    u->buffering = plcf->upstream.buffering;
    720 +
    721 +    u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
    722 +    if (u->pipe == NULL) {
    723 +        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    724 +    }
    725 +
    726 +    u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
    727 +
    728 +    u->accel = 1;
    729 +
    730 +    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
    731 +
    732 +    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
    733 +        return rc;
    734 +    }
    735 +
    736 +    return NGX_DONE;
    737 +}
    738 +
    739 +
    740 +static ngx_int_t
    741 +ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
    742 +    ngx_http_proxy_loc_conf_t *plcf)
    743 +{
    744 +    u_char               *p;
    745 +    size_t                add;
    746 +    u_short               port;
    747 +    ngx_str_t             proxy;
    748 +    ngx_url_t             url;
    749 +    ngx_http_upstream_t  *u;
    750 +
    751 +    if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
    752 +                            plcf->proxy_values->elts)
    753 +        == NULL)
    754 +    {
    755 +        return NGX_ERROR;
    756 +    }
    757 +
    758 +    if (ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0) {
    759 +
    760 +        add = 7;
    761 +        port = 80;
    762 +
    763 +#if (NGX_HTTP_SSL)
    764 +
    765 +    } else if (ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0) {
    766 +
    767 +        add = 8;
    768 +        port = 443;
    769 +        r->upstream->ssl = 1;
    770 +
    771 +#endif
    772 +
    773 +    } else {
    774 +        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    775 +                      "invalid URL prefix in \"%V\"", &proxy);
    776 +        return NGX_ERROR;
    777 +    }
    778 +
    779 +    u = r->upstream;
    780 +
    781 +    u->schema.len = add;
    782 +    u->schema.data = proxy.data;
    783 +
    784 +    ngx_memzero(&url, sizeof(ngx_url_t));
    785 +
    786 +    url.url.len = proxy.len - add;
    787 +    url.url.data = proxy.data + add;
    788 +    url.default_port = port;
    789 +    url.uri_part = 1;
    790 +    url.no_resolve = 1;
    791 +
    792 +    if (ngx_parse_url(r->pool, &url) != NGX_OK) {
    793 +        if (url.err) {
    794 +            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    795 +                          "%s in upstream \"%V\"", url.err, &url.url);
    796 +        }
    797 +
    798 +        return NGX_ERROR;
    799 +    }
    800 +
    801 +    if (url.uri.len) {
    802 +        if (url.uri.data[0] == '?') {
    803 +            p = ngx_pnalloc(r->pool, url.uri.len + 1);
    804 +            if (p == NULL) {
    805 +                return NGX_ERROR;
    806 +            }
    807 +
    808 +            *p++ = '/';
    809 +            ngx_memcpy(p, url.uri.data, url.uri.len);
    810 +
    811 +            url.uri.len++;
    812 +            url.uri.data = p - 1;
    813 +        }
    814 +
    815 +    } else {
    816 +        url.uri = r->unparsed_uri;
    817 +    }
    818 +
    819 +    ctx->vars.key_start = u->schema;
    820 +
    821 +    ngx_http_proxy_set_vars(&url, &ctx->vars);
    822 +
    823 +    u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
    824 +    if (u->resolved == NULL) {
    825 +        return NGX_ERROR;
    826 +    }
    827 +
    828 +    if (url.addrs && url.addrs[0].sockaddr) {
    829 +        u->resolved->sockaddr = url.addrs[0].sockaddr;
    830 +        u->resolved->socklen = url.addrs[0].socklen;
    831 +        u->resolved->naddrs = 1;
    832 +        u->resolved->host = url.addrs[0].name;
    833 +
    834 +    } else {
    835 +        u->resolved->host = url.host;
    836 +        u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
    837 +        u->resolved->no_port = url.no_port;
    838 +    }
    839 +
    840 +    return NGX_OK;
    841 +}
    842 +
    843 +
    844 +#if (NGX_HTTP_CACHE)
    845 +
    846 +static ngx_int_t
    847 +ngx_http_proxy_create_key(ngx_http_request_t *r)
    848 +{
    849 +    size_t                      len, loc_len;
    850 +    u_char                     *p;
    851 +    uintptr_t                   escape;
    852 +    ngx_str_t                  *key;
    853 +    ngx_http_upstream_t        *u;
    854 +    ngx_http_proxy_ctx_t       *ctx;
    855 +    ngx_http_proxy_loc_conf_t  *plcf;
    856 +
    857 +    u = r->upstream;
    858 +
    859 +    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
    860 +
    861 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    862 +
    863 +    key = ngx_array_push(&r->cache->keys);
    864 +    if (key == NULL) {
    865 +        return NGX_ERROR;
    866 +    }
    867 +
    868 +    if (plcf->cache_key.value.len) {
    869 +
    870 +        if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
    871 +            return NGX_ERROR;
    872 +        }
    873 +
    874 +        return NGX_OK;
    875 +    }
    876 +
    877 +    *key = ctx->vars.key_start;
    878 +
    879 +    key = ngx_array_push(&r->cache->keys);
    880 +    if (key == NULL) {
    881 +        return NGX_ERROR;
    882 +    }
    883 +
    884 +    if (plcf->proxy_lengths) {
    885 +
    886 +        *key = ctx->vars.uri;
    887 +        u->uri = ctx->vars.uri;
    888 +
    889 +        return NGX_OK;
    890 +
    891 +    } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
    892 +    {
    893 +        *key = r->unparsed_uri;
    894 +        u->uri = r->unparsed_uri;
    895 +
    896 +        return NGX_OK;
    897 +    }
    898 +
    899 +    loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
    900 +
    901 +    if (r->quoted_uri || r->internal) {
    902 +        escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
    903 +                                    r->uri.len - loc_len, NGX_ESCAPE_URI);
    904 +    } else {
    905 +        escape = 0;
    906 +    }
    907 +
    908 +    len = ctx->vars.uri.len + r->uri.len - loc_len + escape
    909 +          + sizeof("?") - 1 + r->args.len;
    910 +
    911 +    p = ngx_pnalloc(r->pool, len);
    912 +    if (p == NULL) {
    913 +        return NGX_ERROR;
    914 +    }
    915 +
    916 +    key->data = p;
    917 +
    918 +    if (r->valid_location) {
    919 +        p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
    920 +    }
    921 +
    922 +    if (escape) {
    923 +        ngx_escape_uri(p, r->uri.data + loc_len,
    924 +                       r->uri.len - loc_len, NGX_ESCAPE_URI);
    925 +        p += r->uri.len - loc_len + escape;
    926 +
    927 +    } else {
    928 +        p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
    929 +    }
    930 +
    931 +    if (r->args.len > 0) {
    932 +        *p++ = '?';
    933 +        p = ngx_copy(p, r->args.data, r->args.len);
    934 +    }
    935 +
    936 +    key->len = p - key->data;
    937 +    u->uri = *key;
    938 +
    939 +    return NGX_OK;
    940 +}
    941 +
    942 +#endif
    943 +
    944 +
    945 +static ngx_int_t
    946 +ngx_http_proxy_create_request(ngx_http_request_t *r)
    947 +{
    948 +    size_t                        len, uri_len, loc_len, body_len;
    949 +    uintptr_t                     escape;
    950 +    ngx_buf_t                    *b;
    951 +    ngx_str_t                     method;
    952 +    ngx_uint_t                    i, unparsed_uri;
    953 +    ngx_chain_t                  *cl, *body;
    954 +    ngx_list_part_t              *part;
    955 +    ngx_table_elt_t              *header;
    956 +    ngx_http_upstream_t          *u;
    957 +    ngx_http_proxy_ctx_t         *ctx;
    958 +    ngx_http_script_code_pt       code;
    959 +    ngx_http_script_engine_t      e, le;
    960 +    ngx_http_proxy_loc_conf_t    *plcf;
    961 +    ngx_http_script_len_code_pt   lcode;
    962 +
    963 +    u = r->upstream;
    964 +
    965 +    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
    966 +
    967 +    if (u->method.len) {
    968 +        /* HEAD was changed to GET to cache response */
    969 +        method = u->method;
    970 +        method.len++;
    971 +
    972 +    } else if (plcf->method.len) {
    973 +        method = plcf->method;
    974 +
    975 +    } else {
    976 +        method = r->method_name;
    977 +        method.len++;
    978 +    }
    979 +
    980 +    len = method.len + sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
    981 +
    982 +    escape = 0;
    983 +    loc_len = 0;
    984 +    unparsed_uri = 0;
    985 +
    986 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    987 +
    988 +    if (plcf->proxy_lengths) {
    989 +        uri_len = ctx->vars.uri.len;
    990 +
    991 +    } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
    992 +    {
    993 +        unparsed_uri = 1;
    994 +        uri_len = r->unparsed_uri.len;
    995 +
    996 +    } else {
    997 +        loc_len = (r->valid_location && ctx->vars.uri.len) ?
    998 +                      plcf->location.len : 0;
    999 +
    1000 +        if (r->quoted_uri || r->space_in_uri || r->internal) {
    1001 +            escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
    1002 +                                        r->uri.len - loc_len, NGX_ESCAPE_URI);
    1003 +        }
    1004 +
    1005 +        uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
    1006 +                  + sizeof("?") - 1 + r->args.len;
    1007 +    }
    1008 +
    1009 +    if (uri_len == 0) {
    1010 +        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1011 +                      "zero length URI to proxy");
    1012 +        return NGX_ERROR;
    1013 +    }
    1014 +
    1015 +    len += uri_len;
    1016 +
    1017 +    ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
    1018 +
    1019 +    if (plcf->body_set_len) {
    1020 +        le.ip = plcf->body_set_len->elts;
    1021 +        le.request = r;
    1022 +        le.flushed = 1;
    1023 +        body_len = 0;
    1024 +
    1025 +        while (*(uintptr_t *) le.ip) {
    1026 +            lcode = *(ngx_http_script_len_code_pt *) le.ip;
    1027 +            body_len += lcode(&le);
    1028 +        }
    1029 +
    1030 +        ctx->internal_body_length = body_len;
    1031 +        len += body_len;
    1032 +    }
    1033 +
    1034 +    le.ip = plcf->headers_set_len->elts;
    1035 +    le.request = r;
    1036 +    le.flushed = 1;
    1037 +
    1038 +    while (*(uintptr_t *) le.ip) {
    1039 +        while (*(uintptr_t *) le.ip) {
    1040 +            lcode = *(ngx_http_script_len_code_pt *) le.ip;
    1041 +            len += lcode(&le);
    1042 +        }
    1043 +        le.ip += sizeof(uintptr_t);
    1044 +    }
    1045 +
    1046 +
    1047 +    if (plcf->upstream.pass_request_headers) {
    1048 +        part = &r->headers_in.headers.part;
    1049 +        header = part->elts;
    1050 +
    1051 +        for (i = 0; /* void */; i++) {
    1052 +
    1053 +            if (i >= part->nelts) {
    1054 +                if (part->next == NULL) {
    1055 +                    break;
    1056 +                }
    1057 +
    1058 +                part = part->next;
    1059 +                header = part->elts;
    1060 +                i = 0;
    1061 +            }
    1062 +
    1063 +            if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
    1064 +                              header[i].lowcase_key, header[i].key.len))
    1065 +            {
    1066 +                continue;
    1067 +            }
    1068 +
    1069 +            len += header[i].key.len + sizeof(": ") - 1
    1070 +                + header[i].value.len + sizeof(CRLF) - 1;
    1071 +        }
    1072 +    }
    1073 +
    1074 +
    1075 +    b = ngx_create_temp_buf(r->pool, len);
    1076 +    if (b == NULL) {
    1077 +        return NGX_ERROR;
    1078 +    }
    1079 +
    1080 +    cl = ngx_alloc_chain_link(r->pool);
    1081 +    if (cl == NULL) {
    1082 +        return NGX_ERROR;
    1083 +    }
    1084 +
    1085 +    cl->buf = b;
    1086 +
    1087 +
    1088 +    /* the request line */
    1089 +
    1090 +    b->last = ngx_copy(b->last, method.data, method.len);
    1091 +
    1092 +    u->uri.data = b->last;
    1093 +
    1094 +    if (plcf->proxy_lengths) {
    1095 +        b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
    1096 +
    1097 +    } else if (unparsed_uri) {
    1098 +        b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
    1099 +
    1100 +    } else {
    1101 +        if (r->valid_location) {
    1102 +            b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
    1103 +        }
    1104 +
    1105 +        if (escape) {
    1106 +            ngx_escape_uri(b->last, r->uri.data + loc_len,
    1107 +                           r->uri.len - loc_len, NGX_ESCAPE_URI);
    1108 +            b->last += r->uri.len - loc_len + escape;
    1109 +
    1110 +        } else {
    1111 +            b->last = ngx_copy(b->last, r->uri.data + loc_len,
    1112 +                               r->uri.len - loc_len);
    1113 +        }
    1114 +
    1115 +        if (r->args.len > 0) {
    1116 +            *b->last++ = '?';
    1117 +            b->last = ngx_copy(b->last, r->args.data, r->args.len);
    1118 +        }
    1119 +    }
    1120 +
    1121 +    u->uri.len = b->last - u->uri.data;
    1122 +
    1123 +    b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
    1124 +                         sizeof(ngx_http_proxy_version) - 1);
    1125 +
    1126 +    ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
    1127 +
    1128 +    e.ip = plcf->headers_set->elts;
    1129 +    e.pos = b->last;
    1130 +    e.request = r;
    1131 +    e.flushed = 1;
    1132 +
    1133 +    le.ip = plcf->headers_set_len->elts;
    1134 +
    1135 +    while (*(uintptr_t *) le.ip) {
    1136 +        lcode = *(ngx_http_script_len_code_pt *) le.ip;
    1137 +
    1138 +        /* skip the header line name length */
    1139 +        (void) lcode(&le);
    1140 +
    1141 +        if (*(ngx_http_script_len_code_pt *) le.ip) {
    1142 +
    1143 +            for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
    1144 +                lcode = *(ngx_http_script_len_code_pt *) le.ip;
    1145 +            }
    1146 +
    1147 +            e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0;
    1148 +
    1149 +        } else {
    1150 +            e.skip = 0;
    1151 +        }
    1152 +
    1153 +        le.ip += sizeof(uintptr_t);
    1154 +
    1155 +        while (*(uintptr_t *) e.ip) {
    1156 +            code = *(ngx_http_script_code_pt *) e.ip;
    1157 +            code((ngx_http_script_engine_t *) &e);
    1158 +        }
    1159 +        e.ip += sizeof(uintptr_t);
    1160 +    }
    1161 +
    1162 +    b->last = e.pos;
    1163 +
    1164 +
    1165 +    if (plcf->upstream.pass_request_headers) {
    1166 +        part = &r->headers_in.headers.part;
    1167 +        header = part->elts;
    1168 +
    1169 +        for (i = 0; /* void */; i++) {
    1170 +
    1171 +            if (i >= part->nelts) {
    1172 +                if (part->next == NULL) {
    1173 +                    break;
    1174 +                }
    1175 +
    1176 +                part = part->next;
    1177 +                header = part->elts;
    1178 +                i = 0;
    1179 +            }
    1180 +
    1181 +            if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
    1182 +                              header[i].lowcase_key, header[i].key.len))
    1183 +            {
    1184 +                continue;
    1185 +            }
    1186 +
    1187 +            b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
    1188 +
    1189 +            *b->last++ = ':'; *b->last++ = ' ';
    1190 +
    1191 +            b->last = ngx_copy(b->last, header[i].value.data,
    1192 +                               header[i].value.len);
    1193 +
    1194 +            *b->last++ = CR; *b->last++ = LF;
    1195 +
    1196 +            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1197 +                           "http proxy header: \"%V: %V\"",
    1198 +                           &header[i].key, &header[i].value);
    1199 +        }
    1200 +    }
    1201 +
    1202 +
    1203 +    /* add "\r\n" at the header end */
    1204 +    *b->last++ = CR; *b->last++ = LF;
    1205 +
    1206 +    if (plcf->body_set) {
    1207 +        e.ip = plcf->body_set->elts;
    1208 +        e.pos = b->last;
    1209 +
    1210 +        while (*(uintptr_t *) e.ip) {
    1211 +            code = *(ngx_http_script_code_pt *) e.ip;
    1212 +            code((ngx_http_script_engine_t *) &e);
    1213 +        }
    1214 +
    1215 +        b->last = e.pos;
    1216 +    }
    1217 +
    1218 +    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1219 +                   "http proxy header:\n\"%*s\"",
    1220 +                   (size_t) (b->last - b->pos), b->pos);
    1221 +
    1222 +    if (plcf->body_set == NULL && plcf->upstream.pass_request_body) {
    1223 +
    1224 +        body = u->request_bufs;
    1225 +        u->request_bufs = cl;
    1226 +
    1227 +        while (body) {
    1228 +            b = ngx_alloc_buf(r->pool);
    1229 +            if (b == NULL) {
    1230 +                return NGX_ERROR;
    1231 +            }
    1232 +
    1233 +            ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
    1234 +
    1235 +            cl->next = ngx_alloc_chain_link(r->pool);
    1236 +            if (cl->next == NULL) {
    1237 +                return NGX_ERROR;
    1238 +            }
    1239 +
    1240 +            cl = cl->next;
    1241 +            cl->buf = b;
    1242 +
    1243 +            body = body->next;
    1244 +        }
    1245 +
    1246 +        b->flush = 1;
    1247 +
    1248 +    } else {
    1249 +        u->request_bufs = cl;
    1250 +    }
    1251 +
    1252 +    cl->next = NULL;
    1253 +
    1254 +    return NGX_OK;
    1255 +}
    1256 +
    1257 +
    1258 +static ngx_int_t
    1259 +ngx_http_proxy_reinit_request(ngx_http_request_t *r)
    1260 +{
    1261 +    ngx_http_proxy_ctx_t  *ctx;
    1262 +
    1263 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    1264 +
    1265 +    if (ctx == NULL) {
    1266 +        return NGX_OK;
    1267 +    }
    1268 +
    1269 +    ctx->status.code = 0;
    1270 +    ctx->status.count = 0;
    1271 +    ctx->status.start = NULL;
    1272 +    ctx->status.end = NULL;
    1273 +
    1274 +    r->upstream->process_header = ngx_http_proxy_process_status_line;
    1275 +    r->state = 0;
    1276 +
    1277 +    return NGX_OK;
    1278 +}
    1279 +
    1280 +
    1281 +static ngx_int_t
    1282 +ngx_http_proxy_process_status_line(ngx_http_request_t *r)
    1283 +{
    1284 +    size_t                 len;
    1285 +    ngx_int_t              rc;
    1286 +    ngx_http_upstream_t   *u;
    1287 +    ngx_http_proxy_ctx_t  *ctx;
    1288 +
    1289 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    1290 +
    1291 +    if (ctx == NULL) {
    1292 +        return NGX_ERROR;
    1293 +    }
    1294 +
    1295 +    u = r->upstream;
    1296 +
    1297 +    rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);
    1298 +
    1299 +    if (rc == NGX_AGAIN) {
    1300 +        return rc;
    1301 +    }
    1302 +
    1303 +    if (rc == NGX_ERROR) {
    1304 +
    1305 +#if (NGX_HTTP_CACHE)
    1306 +
    1307 +        if (r->cache) {
    1308 +            r->http_version = NGX_HTTP_VERSION_9;
    1309 +            return NGX_OK;
    1310 +        }
    1311 +
    1312 +#endif
    1313 +
    1314 +        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1315 +                      "upstream sent no valid HTTP/1.0 header");
    1316 +
    1317 +#if 0
    1318 +        if (u->accel) {
    1319 +            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
    1320 +        }
    1321 +#endif
    1322 +
    1323 +        r->http_version = NGX_HTTP_VERSION_9;
    1324 +        u->state->status = NGX_HTTP_OK;
    1325 +
    1326 +        return NGX_OK;
    1327 +    }
    1328 +
    1329 +    if (u->state) {
    1330 +        u->state->status = ctx->status.code;
    1331 +    }
    1332 +
    1333 +    u->headers_in.status_n = ctx->status.code;
    1334 +
    1335 +    len = ctx->status.end - ctx->status.start;
    1336 +    u->headers_in.status_line.len = len;
    1337 +
    1338 +    u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
    1339 +    if (u->headers_in.status_line.data == NULL) {
    1340 +        return NGX_ERROR;
    1341 +    }
    1342 +
    1343 +    ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);
    1344 +
    1345 +    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1346 +                   "http proxy status %ui \"%V\"",
    1347 +                   u->headers_in.status_n, &u->headers_in.status_line);
    1348 +
    1349 +    u->process_header = ngx_http_proxy_process_header;
    1350 +
    1351 +    return ngx_http_proxy_process_header(r);
    1352 +}
    1353 +
    1354 +
    1355 +static ngx_int_t
    1356 +ngx_http_proxy_process_header(ngx_http_request_t *r)
    1357 +{
    1358 +    ngx_int_t                       rc;
    1359 +    ngx_table_elt_t                *h;
    1360 +    ngx_http_upstream_header_t     *hh;
    1361 +    ngx_http_upstream_main_conf_t  *umcf;
    1362 +
    1363 +    umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
    1364 +
    1365 +    for ( ;; ) {
    1366 +
    1367 +        rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
    1368 +
    1369 +        if (rc == NGX_OK) {
    1370 +
    1371 +            /* a header line has been parsed successfully */
    1372 +
    1373 +            h = ngx_list_push(&r->upstream->headers_in.headers);
    1374 +            if (h == NULL) {
    1375 +                return NGX_ERROR;
    1376 +            }
    1377 +
    1378 +            h->hash = r->header_hash;
    1379 +
    1380 +            h->key.len = r->header_name_end - r->header_name_start;
    1381 +            h->value.len = r->header_end - r->header_start;
    1382 +
    1383 +            h->key.data = ngx_pnalloc(r->pool,
    1384 +                               h->key.len + 1 + h->value.len + 1 + h->key.len);
    1385 +            if (h->key.data == NULL) {
    1386 +                return NGX_ERROR;
    1387 +            }
    1388 +
    1389 +            h->value.data = h->key.data + h->key.len + 1;
    1390 +            h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
    1391 +
    1392 +            ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
    1393 +            ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
    1394 +
    1395 +            if (h->key.len == r->lowcase_index) {
    1396 +                ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
    1397 +
    1398 +            } else {
    1399 +                ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
    1400 +            }
    1401 +
    1402 +            hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
    1403 +                               h->lowcase_key, h->key.len);
    1404 +
    1405 +            if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
    1406 +                return NGX_ERROR;
    1407 +            }
    1408 +
    1409 +            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1410 +                           "http proxy header: \"%V: %V\"",
    1411 +                           &h->key, &h->value);
    1412 +
    1413 +            continue;
    1414 +        }
    1415 +
    1416 +        if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
    1417 +
    1418 +            /* a whole header has been parsed successfully */
    1419 +
    1420 +            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1421 +                           "http proxy header done");
    1422 +
    1423 +            /*
    1424 +             * if no "Server" and "Date" in header line,
    1425 +             * then add the special empty headers
    1426 +             */
    1427 +
    1428 +            if (r->upstream->headers_in.server == NULL) {
    1429 +                h = ngx_list_push(&r->upstream->headers_in.headers);
    1430 +                if (h == NULL) {
    1431 +                    return NGX_ERROR;
    1432 +                }
    1433 +
    1434 +                h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
    1435 +                                    ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
    1436 +
    1437 +                ngx_str_set(&h->key, "Server");
    1438 +                ngx_str_null(&h->value);
    1439 +                h->lowcase_key = (u_char *) "server";
    1440 +            }
    1441 +
    1442 +            if (r->upstream->headers_in.date == NULL) {
    1443 +                h = ngx_list_push(&r->upstream->headers_in.headers);
    1444 +                if (h == NULL) {
    1445 +                    return NGX_ERROR;
    1446 +                }
    1447 +
    1448 +                h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
    1449 +
    1450 +                ngx_str_set(&h->key, "Date");
    1451 +                ngx_str_null(&h->value);
    1452 +                h->lowcase_key = (u_char *) "date";
    1453 +            }
    1454 +
    1455 +            return NGX_OK;
    1456 +        }
    1457 +
    1458 +        if (rc == NGX_AGAIN) {
    1459 +            return NGX_AGAIN;
    1460 +        }
    1461 +
    1462 +        /* there was error while a header line parsing */
    1463 +
    1464 +        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
    1465 +                      "upstream sent invalid header");
    1466 +
    1467 +        return NGX_HTTP_UPSTREAM_INVALID_HEADER;
    1468 +    }
    1469 +}
    1470 +
    1471 +
    1472 +static void
    1473 +ngx_http_proxy_abort_request(ngx_http_request_t *r)
    1474 +{
    1475 +    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1476 +                   "abort http proxy request");
    1477 +
    1478 +    return;
    1479 +}
    1480 +
    1481 +
    1482 +static void
    1483 +ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
    1484 +{
    1485 +    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    1486 +                   "finalize http proxy request");
    1487 +
    1488 +    return;
    1489 +}
    1490 +
    1491 +
    1492 +static ngx_int_t
    1493 +ngx_http_proxy_host_variable(ngx_http_request_t *r,
    1494 +    ngx_http_variable_value_t *v, uintptr_t data)
    1495 +{
    1496 +    ngx_http_proxy_ctx_t  *ctx;
    1497 +
    1498 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    1499 +
    1500 +    if (ctx == NULL) {
    1501 +        v->not_found = 1;
    1502 +        return NGX_OK;
    1503 +    }
    1504 +
    1505 +    v->len = ctx->vars.host_header.len;
    1506 +    v->valid = 1;
    1507 +    v->no_cacheable = 0;
    1508 +    v->not_found = 0;
    1509 +    v->data = ctx->vars.host_header.data;
    1510 +
    1511 +    return NGX_OK;
    1512 +}
    1513 +
    1514 +
    1515 +static ngx_int_t
    1516 +ngx_http_proxy_port_variable(ngx_http_request_t *r,
    1517 +    ngx_http_variable_value_t *v, uintptr_t data)
    1518 +{
    1519 +    ngx_http_proxy_ctx_t  *ctx;
    1520 +
    1521 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    1522 +
    1523 +    if (ctx == NULL) {
    1524 +        v->not_found = 1;
    1525 +        return NGX_OK;
    1526 +    }
    1527 +
    1528 +    v->len = ctx->vars.port.len;
    1529 +    v->valid = 1;
    1530 +    v->no_cacheable = 0;
    1531 +    v->not_found = 0;
    1532 +    v->data = ctx->vars.port.data;
    1533 +
    1534 +    return NGX_OK;
    1535 +}
    1536 +
    1537 +
    1538 +static ngx_int_t
    1539 +ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
    1540 +    ngx_http_variable_value_t *v, uintptr_t data)
    1541 +{
    1542 +    u_char  *p;
    1543 +
    1544 +    v->valid = 1;
    1545 +    v->no_cacheable = 0;
    1546 +    v->not_found = 0;
    1547 +
    1548 +    if (r->headers_in.x_forwarded_for == NULL) {
    1549 +        v->len = r->connection->addr_text.len;
    1550 +        v->data = r->connection->addr_text.data;
    1551 +        return NGX_OK;
    1552 +    }
    1553 +
    1554 +    v->len = r->headers_in.x_forwarded_for->value.len
    1555 +             + sizeof(", ") - 1 + r->connection->addr_text.len;
    1556 +
    1557 +    p = ngx_pnalloc(r->pool, v->len);
    1558 +    if (p == NULL) {
    1559 +        return NGX_ERROR;
    1560 +    }
    1561 +
    1562 +    v->data = p;
    1563 +
    1564 +    p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
    1565 +                 r->headers_in.x_forwarded_for->value.len);
    1566 +
    1567 +    *p++ = ','; *p++ = ' ';
    1568 +
    1569 +    ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
    1570 +
    1571 +    return NGX_OK;
    1572 +}
    1573 +
    1574 +
    1575 +static ngx_int_t
    1576 +ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
    1577 +    ngx_http_variable_value_t *v, uintptr_t data)
    1578 +{
    1579 +    ngx_http_proxy_ctx_t  *ctx;
    1580 +
    1581 +    ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
    1582 +
    1583 +    if (ctx == NULL) {
    1584 +        v->not_found = 1;
    1585 +        return NGX_OK;
    1586 +    }
    1587 +
    1588 +    v->valid = 1;
    1589 +    v->no_cacheable = 0;
    1590 +    v->not_found = 0;
    1591 +
    1592 +    v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN);
    1593 +
    1594 +    if (v->data == NULL) {
    1595 +        return NGX_ERROR;
    1596 +    }
    1597 +
    1598 +    v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
    1599 +
    1600 +    return NGX_OK;
    1601 +}
    1602 +
    1603 +
    1604 +static ngx_int_t
    1605 +ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
    1606 +    size_t prefix)
    1607 +{
    1608 +    ngx_int_t                   rc;
    1609 +    ngx_uint_t                  i;
    1610 +    ngx_http_proxy_loc_conf_t  *plcf;
    1611 +    ngx_http_proxy_redirect_t  *pr;
    1612 +
    1613 +    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
    1614 +
    1615 +    pr = plcf->redirects->elts;
    1616 +
    1617 +    if (pr == NULL) {
    1618 +        return NGX_DECLINED;
    1619 +    }
    1620 +
    1621 +    for (i = 0; i < plcf->redirects->nelts; i++) {
    1622 +        rc = pr[i].handler(r, h, prefix, &pr[i]);
    1623 +
    1624 +        if (rc != NGX_DECLINED) {
    1625 +            return rc;
    1626 +        }
    1627 +    }
    1628 +
    1629 +    return NGX_DECLINED;
    1630 +}
    1631 +
    1632 +
    1633 +static ngx_int_t
    1634 +ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
    1635 +    size_t prefix, ngx_http_proxy_redirect_t *pr)
    1636 +{
    1637 +    size_t   len;
    1638 +    u_char  *data, *p;
    1639 +
    1640 +    if (pr->redirect.len > h->value.len - prefix
    1641 +        || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
    1642 +                        pr->redirect.len) != 0)
    1643 +    {
    1644 +        return NGX_DECLINED;
    1645 +    }
    1646 +
    1647 +    len = pr->replacement.text.len + h->value.len - pr->redirect.len;
    1648 +
    1649 +    data = ngx_pnalloc(r->pool, len);
    1650 +    if (data == NULL) {
    1651 +        return NGX_ERROR;
    1652 +    }
    1653 +
    1654 +    p = ngx_copy(data, h->value.data, prefix);
    1655 +
    1656 +    if (pr->replacement.text.len) {
    1657 +        p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
    1658 +    }
    1659 +
    1660 +    ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
    1661 +               h->value.len - pr->redirect.len - prefix);
    1662 +
    1663 +    h->value.len = len;
    1664 +    h->value.data = data;
    1665 +
    1666 +    return NGX_OK;
    1667 +}
    1668 +
    1669 +
    1670 +static ngx_int_t
    1671 +ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h,
    1672 +    size_t prefix, ngx_http_proxy_redirect_t *pr)
    1673 +{
    1674 +    size_t                        len;
    1675 +    u_char                       *data, *p;
    1676 +    ngx_http_script_code_pt       code;
    1677 +    ngx_http_script_engine_t      e;
    1678 +    ngx_http_script_len_code_pt   lcode;
    1679 +
    1680 +    if (pr->redirect.len > h->value.len - prefix
    1681 +        || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
    1682 +                        pr->redirect.len) != 0)
    1683 +    {
    1684 +        return NGX_DECLINED;
    1685 +    }
    1686 +
    1687 +    ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
    1688 +
    1689 +    e.ip = pr->replacement.vars.lengths;
    1690 +    e.request = r;
    1691 +
    1692 +    len = h->value.len - pr->redirect.len;
    1693 +
    1694 +    while (*(uintptr_t *) e.ip) {
    1695 +        lcode = *(ngx_http_script_len_code_pt *) e.ip;
    1696 +        len += lcode(&e);
    1697 +    }
    1698 +
    1699 +    data = ngx_pnalloc(r->pool, len);
    1700 +    if (data == NULL) {
    1701 +        return NGX_ERROR;
    1702 +    }
    1703 +
    1704 +    p = ngx_copy(data, h->value.data, prefix);
    1705 +
    1706 +    e.ip = pr->replacement.vars.values;
    1707 +    e.pos = p;
    1708 +
    1709 +    while (*(uintptr_t *) e.ip) {
    1710 +        code = *(ngx_http_script_code_pt *) e.ip;
    1711 +        code(&e);
    1712 +    }
    1713 +
    1714 +    ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
    1715 +               h->value.len - pr->redirect.len - prefix);
    1716 +
    1717 +    h->value.len = len;
    1718 +    h->value.data = data;
    1719 +
    1720 +    return NGX_OK;
    1721 +}
    1722 +
    1723 +
    1724 +static ngx_int_t
    1725 +ngx_http_proxy_add_variables(ngx_conf_t *cf)
    1726 +{
    1727 +    ngx_http_variable_t  *var, *v;
    1728 +
    1729 +    for (v = ngx_http_proxy_vars; v->name.len; v++) {
    1730 +        var = ngx_http_add_variable(cf, &v->name, v->flags);
    1731 +        if (var == NULL) {
    1732 +            return NGX_ERROR;
    1733 +        }
    1734 +
    1735 +        var->get_handler = v->get_handler;
    1736 +        var->data = v->data;
    1737 +    }
    1738 +
    1739 +    return NGX_OK;
    1740 +}
    1741 +
    1742 +
    1743 +static void *
    1744 +ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
    1745 +{
    1746 +    ngx_http_proxy_loc_conf_t  *conf;
    1747 +
    1748 +    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
    1749 +    if (conf == NULL) {
    1750 +        return NULL;
    1751 +    }
    1752 +
    1753 +    /*
    1754 +     * set by ngx_pcalloc():
    1755 +     *
    1756 +     *     conf->upstream.bufs.num = 0;
    1757 +     *     conf->upstream.ignore_headers = 0;
    1758 +     *     conf->upstream.next_upstream = 0;
    1759 +     *     conf->upstream.cache_use_stale = 0;
    1760 +     *     conf->upstream.cache_methods = 0;
    1761 +     *     conf->upstream.temp_path = NULL;
    1762 +     *     conf->upstream.hide_headers_hash = { NULL, 0 };
    1763 +     *     conf->upstream.uri = { 0, NULL };
    1764 +     *     conf->upstream.location = NULL;
    1765 +     *     conf->upstream.store_lengths = NULL;
    1766 +     *     conf->upstream.store_values = NULL;
    1767 +     *
    1768 +     *     conf->method = NULL;
    1769 +     *     conf->headers_source = NULL;
    1770 +     *     conf->headers_set_len = NULL;
    1771 +     *     conf->headers_set = NULL;
    1772 +     *     conf->headers_set_hash = NULL;
    1773 +     *     conf->body_set_len = NULL;
    1774 +     *     conf->body_set = NULL;
    1775 +     *     conf->body_source = { 0, NULL };
    1776 +     *     conf->redirects = NULL;
    1777 +     */
    1778 +
    1779 +    conf->upstream.store = NGX_CONF_UNSET;
    1780 +    conf->upstream.store_access = NGX_CONF_UNSET_UINT;
    1781 +    conf->upstream.buffering = NGX_CONF_UNSET;
    1782 +    conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
    1783 +
    1784 +    conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
    1785 +    conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
    1786 +    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
    1787 +
    1788 +    conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
    1789 +    conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
    1790 +
    1791 +    conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
    1792 +    conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
    1793 +    conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
    1794 +
    1795 +    conf->upstream.pass_request_headers = NGX_CONF_UNSET;
    1796 +    conf->upstream.pass_request_body = NGX_CONF_UNSET;
    1797 +
    1798 +#if (NGX_HTTP_CACHE)
    1799 +    conf->upstream.cache = NGX_CONF_UNSET_PTR;
    1800 +    conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
    1801 +    conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
    1802 +    conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
    1803 +    conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
    1804 +#endif
    1805 +
    1806 +    conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
    1807 +    conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
    1808 +
    1809 +    conf->upstream.intercept_errors = NGX_CONF_UNSET;
    1810 +#if (NGX_HTTP_SSL)
    1811 +    conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
    1812 +#endif
    1813 +
    1814 +    /* "proxy_cyclic_temp_file" is disabled */
    1815 +    conf->upstream.cyclic_temp_file = 0;
    1816 +
    1817 +    conf->redirect = NGX_CONF_UNSET;
    1818 +    conf->upstream.change_buffering = 1;
    1819 +
    1820 +    conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
    1821 +    conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
    1822 +
    1823 +    return conf;
    1824 +}
    1825 +
    1826 +
    1827 +static char *
    1828 +ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
    1829 +{
    1830 +    ngx_http_proxy_loc_conf_t *prev = parent;
    1831 +    ngx_http_proxy_loc_conf_t *conf = child;
    1832 +
    1833 +    size_t                      size;
    1834 +    ngx_keyval_t               *s;
    1835 +    ngx_hash_init_t             hash;
    1836 +    ngx_http_core_loc_conf_t   *clcf;
    1837 +    ngx_http_proxy_redirect_t  *pr;
    1838 +    ngx_http_script_compile_t   sc;
    1839 +
    1840 +    if (conf->upstream.store != 0) {
    1841 +        ngx_conf_merge_value(conf->upstream.store,
    1842 +                              prev->upstream.store, 0);
    1843 +
    1844 +        if (conf->upstream.store_lengths == NULL) {
    1845 +            conf->upstream.store_lengths = prev->upstream.store_lengths;
    1846 +            conf->upstream.store_values = prev->upstream.store_values;
    1847 +        }
    1848 +    }
    1849 +
    1850 +    ngx_conf_merge_uint_value(conf->upstream.store_access,
    1851 +                              prev->upstream.store_access, 0600);
    1852 +
    1853 +    ngx_conf_merge_value(conf->upstream.buffering,
    1854 +                              prev->upstream.buffering, 1);
    1855 +
    1856 +    ngx_conf_merge_value(conf->upstream.ignore_client_abort,
    1857 +                              prev->upstream.ignore_client_abort, 0);
    1858 +
    1859 +    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
    1860 +                              prev->upstream.connect_timeout, 60000);
    1861 +
    1862 +    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
    1863 +                              prev->upstream.send_timeout, 60000);
    1864 +
    1865 +    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
    1866 +                              prev->upstream.read_timeout, 60000);
    1867 +
    1868 +    ngx_conf_merge_size_value(conf->upstream.send_lowat,
    1869 +                              prev->upstream.send_lowat, 0);
    1870 +
    1871 +    ngx_conf_merge_size_value(conf->upstream.buffer_size,
    1872 +                              prev->upstream.buffer_size,
    1873 +                              (size_t) ngx_pagesize);
    1874 +
    1875 +    ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
    1876 +                              8, ngx_pagesize);
    1877 +
    1878 +    if (conf->upstream.bufs.num < 2) {
    1879 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    1880 +                           "there must be at least 2 \"proxy_buffers\"");
    1881 +        return NGX_CONF_ERROR;
    1882 +    }
    1883 +
    1884 +
    1885 +    size = conf->upstream.buffer_size;
    1886 +    if (size < conf->upstream.bufs.size) {
    1887 +        size = conf->upstream.bufs.size;
    1888 +    }
    1889 +
    1890 +
    1891 +    ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
    1892 +                              prev->upstream.busy_buffers_size_conf,
    1893 +                              NGX_CONF_UNSET_SIZE);
    1894 +
    1895 +    if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
    1896 +        conf->upstream.busy_buffers_size = 2 * size;
    1897 +    } else {
    1898 +        conf->upstream.busy_buffers_size =
    1899 +                                         conf->upstream.busy_buffers_size_conf;
    1900 +    }
    1901 +
    1902 +    if (conf->upstream.busy_buffers_size < size) {
    1903 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    1904 +             "\"proxy_busy_buffers_size\" must be equal or bigger than "
    1905 +             "maximum of the value of \"proxy_buffer_size\" and "
    1906 +             "one of the \"proxy_buffers\"");
    1907 +
    1908 +        return NGX_CONF_ERROR;
    1909 +    }
    1910 +
    1911 +    if (conf->upstream.busy_buffers_size
    1912 +        > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
    1913 +    {
    1914 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    1915 +             "\"proxy_busy_buffers_size\" must be less than "
    1916 +             "the size of all \"proxy_buffers\" minus one buffer");
    1917 +
    1918 +        return NGX_CONF_ERROR;
    1919 +    }
    1920 +
    1921 +
    1922 +    ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
    1923 +                              prev->upstream.temp_file_write_size_conf,
    1924 +                              NGX_CONF_UNSET_SIZE);
    1925 +
    1926 +    if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
    1927 +        conf->upstream.temp_file_write_size = 2 * size;
    1928 +    } else {
    1929 +        conf->upstream.temp_file_write_size =
    1930 +                                      conf->upstream.temp_file_write_size_conf;
    1931 +    }
    1932 +
    1933 +    if (conf->upstream.temp_file_write_size < size) {
    1934 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    1935 +             "\"proxy_temp_file_write_size\" must be equal or bigger than "
    1936 +             "maximum of the value of \"proxy_buffer_size\" and "
    1937 +             "one of the \"proxy_buffers\"");
    1938 +
    1939 +        return NGX_CONF_ERROR;
    1940 +    }
    1941 +
    1942 +    ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
    1943 +                              prev->upstream.max_temp_file_size_conf,
    1944 +                              NGX_CONF_UNSET_SIZE);
    1945 +
    1946 +    if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
    1947 +        conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
    1948 +    } else {
    1949 +        conf->upstream.max_temp_file_size =
    1950 +                                        conf->upstream.max_temp_file_size_conf;
    1951 +    }
    1952 +
    1953 +    if (conf->upstream.max_temp_file_size != 0
    1954 +        && conf->upstream.max_temp_file_size < size)
    1955 +    {
    1956 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    1957 +             "\"proxy_max_temp_file_size\" must be equal to zero to disable "
    1958 +             "the temporary files usage or must be equal or bigger than "
    1959 +             "maximum of the value of \"proxy_buffer_size\" and "
    1960 +             "one of the \"proxy_buffers\"");
    1961 +
    1962 +        return NGX_CONF_ERROR;
    1963 +    }
    1964 +
    1965 +
    1966 +    ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
    1967 +                              prev->upstream.ignore_headers,
    1968 +                              NGX_CONF_BITMASK_SET);
    1969 +
    1970 +
    1971 +    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
    1972 +                              prev->upstream.next_upstream,
    1973 +                              (NGX_CONF_BITMASK_SET
    1974 +                               |NGX_HTTP_UPSTREAM_FT_ERROR
    1975 +                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
    1976 +
    1977 +    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
    1978 +        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
    1979 +                                       |NGX_HTTP_UPSTREAM_FT_OFF;
    1980 +    }
    1981 +
    1982 +    if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
    1983 +                              prev->upstream.temp_path,
    1984 +                              &ngx_http_proxy_temp_path)
    1985 +        != NGX_OK)
    1986 +    {
    1987 +        return NGX_CONF_ERROR;
    1988 +    }
    1989 +
    1990 +
    1991 +#if (NGX_HTTP_CACHE)
    1992 +
    1993 +    ngx_conf_merge_ptr_value(conf->upstream.cache,
    1994 +                              prev->upstream.cache, NULL);
    1995 +
    1996 +    if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
    1997 +        ngx_shm_zone_t  *shm_zone;
    1998 +
    1999 +        shm_zone = conf->upstream.cache;
    2000 +
    2001 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2002 +                           "\"proxy_cache\" zone \"%V\" is unknown",
    2003 +                           &shm_zone->shm.name);
    2004 +
    2005 +        return NGX_CONF_ERROR;
    2006 +    }
    2007 +
    2008 +    ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
    2009 +                              prev->upstream.cache_min_uses, 1);
    2010 +
    2011 +    ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
    2012 +                              prev->upstream.cache_use_stale,
    2013 +                              (NGX_CONF_BITMASK_SET
    2014 +                               |NGX_HTTP_UPSTREAM_FT_OFF));
    2015 +
    2016 +    if (conf->upstream.cache_methods == 0) {
    2017 +        conf->upstream.cache_methods = prev->upstream.cache_methods;
    2018 +    }
    2019 +
    2020 +    conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
    2021 +
    2022 +    if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
    2023 +        conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
    2024 +                                         |NGX_HTTP_UPSTREAM_FT_OFF;
    2025 +    }
    2026 +
    2027 +    ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
    2028 +                             prev->upstream.cache_bypass, NULL);
    2029 +
    2030 +    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
    2031 +                             prev->upstream.no_cache, NULL);
    2032 +
    2033 +    if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
    2034 +        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
    2035 +             "\"proxy_no_cache\" functionality has been changed in 0.8.46, "
    2036 +             "now it should be used together with \"proxy_cache_bypass\"");
    2037 +    }
    2038 +
    2039 +    ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
    2040 +                             prev->upstream.cache_valid, NULL);
    2041 +
    2042 +    if (conf->cache_key.value.data == NULL) {
    2043 +        conf->cache_key = prev->cache_key;
    2044 +    }
    2045 +
    2046 +#endif
    2047 +
    2048 +    if (conf->method.len == 0) {
    2049 +        conf->method = prev->method;
    2050 +
    2051 +    } else {
    2052 +        conf->method.data[conf->method.len] = ' ';
    2053 +        conf->method.len++;
    2054 +    }
    2055 +
    2056 +    ngx_conf_merge_value(conf->upstream.pass_request_headers,
    2057 +                              prev->upstream.pass_request_headers, 1);
    2058 +    ngx_conf_merge_value(conf->upstream.pass_request_body,
    2059 +                              prev->upstream.pass_request_body, 1);
    2060 +
    2061 +    ngx_conf_merge_value(conf->upstream.intercept_errors,
    2062 +                              prev->upstream.intercept_errors, 0);
    2063 +
    2064 +#if (NGX_HTTP_SSL)
    2065 +    ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
    2066 +                              prev->upstream.ssl_session_reuse, 1);
    2067 +#endif
    2068 +
    2069 +    ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
    2070 +
    2071 +    if (conf->redirect) {
    2072 +
    2073 +        if (conf->redirects == NULL) {
    2074 +            conf->redirects = prev->redirects;
    2075 +        }
    2076 +
    2077 +        if (conf->redirects == NULL && conf->url.data) {
    2078 +
    2079 +            conf->redirects = ngx_array_create(cf->pool, 1,
    2080 +                                            sizeof(ngx_http_proxy_redirect_t));
    2081 +            if (conf->redirects == NULL) {
    2082 +                return NGX_CONF_ERROR;
    2083 +            }
    2084 +
    2085 +            pr = ngx_array_push(conf->redirects);
    2086 +            if (pr == NULL) {
    2087 +                return NGX_CONF_ERROR;
    2088 +            }
    2089 +
    2090 +            pr->handler = ngx_http_proxy_rewrite_redirect_text;
    2091 +            pr->redirect = conf->url;
    2092 +
    2093 +            if (conf->vars.uri.len) {
    2094 +                pr->replacement.text = conf->location;
    2095 +
    2096 +            } else {
    2097 +                ngx_str_null(&pr->replacement.text);
    2098 +            }
    2099 +        }
    2100 +    }
    2101 +
    2102 +#if (NGX_HTTP_SSL)
    2103 +    if (conf->upstream.ssl == NULL) {
    2104 +        conf->upstream.ssl = prev->upstream.ssl;
    2105 +    }
    2106 +#endif
    2107 +
    2108 +    ngx_conf_merge_uint_value(conf->headers_hash_max_size,
    2109 +                              prev->headers_hash_max_size, 512);
    2110 +
    2111 +    ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
    2112 +                              prev->headers_hash_bucket_size, 64);
    2113 +
    2114 +    conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
    2115 +                                               ngx_cacheline_size);
    2116 +
    2117 +    hash.max_size = conf->headers_hash_max_size;
    2118 +    hash.bucket_size = conf->headers_hash_bucket_size;
    2119 +    hash.name = "proxy_headers_hash";
    2120 +
    2121 +    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
    2122 +            &prev->upstream, ngx_http_proxy_hide_headers, &hash)
    2123 +        != NGX_OK)
    2124 +    {
    2125 +        return NGX_CONF_ERROR;
    2126 +    }
    2127 +
    2128 +    if (conf->upstream.upstream == NULL) {
    2129 +        conf->upstream.upstream = prev->upstream.upstream;
    2130 +        conf->vars = prev->vars;
    2131 +    }
    2132 +
    2133 +    if (conf->proxy_lengths == NULL) {
    2134 +        conf->proxy_lengths = prev->proxy_lengths;
    2135 +        conf->proxy_values = prev->proxy_values;
    2136 +    }
    2137 +
    2138 +    if (conf->upstream.upstream || conf->proxy_lengths) {
    2139 +        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    2140 +        if (clcf->handler == NULL && clcf->lmt_excpt) {
    2141 +            clcf->handler = ngx_http_proxy_handler;
    2142 +            conf->location = prev->location;
    2143 +        }
    2144 +    }
    2145 +
    2146 +    if (conf->body_source.data == NULL) {
    2147 +        conf->body_source = prev->body_source;
    2148 +        conf->body_set_len = prev->body_set_len;
    2149 +        conf->body_set = prev->body_set;
    2150 +    }
    2151 +
    2152 +    if (conf->body_source.data && conf->body_set_len == NULL) {
    2153 +
    2154 +        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
    2155 +
    2156 +        sc.cf = cf;
    2157 +        sc.source = &conf->body_source;
    2158 +        sc.flushes = &conf->flushes;
    2159 +        sc.lengths = &conf->body_set_len;
    2160 +        sc.values = &conf->body_set;
    2161 +        sc.complete_lengths = 1;
    2162 +        sc.complete_values = 1;
    2163 +
    2164 +        if (ngx_http_script_compile(&sc) != NGX_OK) {
    2165 +            return NGX_CONF_ERROR;
    2166 +        }
    2167 +
    2168 +        if (conf->headers_source == NULL) {
    2169 +            conf->headers_source = ngx_array_create(cf->pool, 4,
    2170 +                                                    sizeof(ngx_keyval_t));
    2171 +            if (conf->headers_source == NULL) {
    2172 +                return NGX_CONF_ERROR;
    2173 +            }
    2174 +        }
    2175 +
    2176 +        s = ngx_array_push(conf->headers_source);
    2177 +        if (s == NULL) {
    2178 +            return NGX_CONF_ERROR;
    2179 +        }
    2180 +
    2181 +        ngx_str_set(&s->key, "Content-Length");
    2182 +        ngx_str_set(&s->value, "$proxy_internal_body_length");
    2183 +    }
    2184 +
    2185 +    if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) {
    2186 +        return NGX_CONF_ERROR;
    2187 +    }
    2188 +
    2189 +    return NGX_CONF_OK;
    2190 +}
    2191 +
    2192 +
    2193 +static ngx_int_t
    2194 +ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
    2195 +    ngx_http_proxy_loc_conf_t *prev)
    2196 +{
    2197 +    u_char                       *p;
    2198 +    size_t                        size;
    2199 +    uintptr_t                    *code;
    2200 +    ngx_uint_t                    i;
    2201 +    ngx_array_t                   headers_names;
    2202 +    ngx_keyval_t                 *src, *s, *h;
    2203 +    ngx_hash_key_t               *hk;
    2204 +    ngx_hash_init_t               hash;
    2205 +    ngx_http_script_compile_t     sc;
    2206 +    ngx_http_script_copy_code_t  *copy;
    2207 +
    2208 +    if (conf->headers_source == NULL) {
    2209 +        conf->flushes = prev->flushes;
    2210 +        conf->headers_set_len = prev->headers_set_len;
    2211 +        conf->headers_set = prev->headers_set;
    2212 +        conf->headers_set_hash = prev->headers_set_hash;
    2213 +        conf->headers_source = prev->headers_source;
    2214 +    }
    2215 +
    2216 +    if (conf->headers_set_hash.buckets
    2217 +#if (NGX_HTTP_CACHE)
    2218 +        && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
    2219 +#endif
    2220 +       )
    2221 +    {
    2222 +        return NGX_OK;
    2223 +    }
    2224 +
    2225 +
    2226 +    if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
    2227 +        != NGX_OK)
    2228 +    {
    2229 +        return NGX_ERROR;
    2230 +    }
    2231 +
    2232 +    if (conf->headers_source == NULL) {
    2233 +        conf->headers_source = ngx_array_create(cf->pool, 4,
    2234 +                                                sizeof(ngx_keyval_t));
    2235 +        if (conf->headers_source == NULL) {
    2236 +            return NGX_ERROR;
    2237 +        }
    2238 +    }
    2239 +
    2240 +    conf->headers_set_len = ngx_array_create(cf->pool, 64, 1);
    2241 +    if (conf->headers_set_len == NULL) {
    2242 +        return NGX_ERROR;
    2243 +    }
    2244 +
    2245 +    conf->headers_set = ngx_array_create(cf->pool, 512, 1);
    2246 +    if (conf->headers_set == NULL) {
    2247 +        return NGX_ERROR;
    2248 +    }
    2249 +
    2250 +
    2251 +    src = conf->headers_source->elts;
    2252 +
    2253 +#if (NGX_HTTP_CACHE)
    2254 +
    2255 +    h = conf->upstream.cache ? ngx_http_proxy_cache_headers:
    2256 +                               ngx_http_proxy_headers;
    2257 +#else
    2258 +
    2259 +    h = ngx_http_proxy_headers;
    2260 +
    2261 +#endif
    2262 +
    2263 +    while (h->key.len) {
    2264 +
    2265 +        for (i = 0; i < conf->headers_source->nelts; i++) {
    2266 +            if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
    2267 +                goto next;
    2268 +            }
    2269 +        }
    2270 +
    2271 +        s = ngx_array_push(conf->headers_source);
    2272 +        if (s == NULL) {
    2273 +            return NGX_ERROR;
    2274 +        }
    2275 +
    2276 +        *s = *h;
    2277 +
    2278 +        src = conf->headers_source->elts;
    2279 +
    2280 +    next:
    2281 +
    2282 +        h++;
    2283 +    }
    2284 +
    2285 +
    2286 +    src = conf->headers_source->elts;
    2287 +    for (i = 0; i < conf->headers_source->nelts; i++) {
    2288 +
    2289 +        hk = ngx_array_push(&headers_names);
    2290 +        if (hk == NULL) {
    2291 +            return NGX_ERROR;
    2292 +        }
    2293 +
    2294 +        hk->key = src[i].key;
    2295 +        hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
    2296 +        hk->value = (void *) 1;
    2297 +
    2298 +        if (src[i].value.len == 0) {
    2299 +            continue;
    2300 +        }
    2301 +
    2302 +        if (ngx_http_script_variables_count(&src[i].value) == 0) {
    2303 +            copy = ngx_array_push_n(conf->headers_set_len,
    2304 +                                    sizeof(ngx_http_script_copy_code_t));
    2305 +            if (copy == NULL) {
    2306 +                return NGX_ERROR;
    2307 +            }
    2308 +
    2309 +            copy->code = (ngx_http_script_code_pt)
    2310 +                                                 ngx_http_script_copy_len_code;
    2311 +            copy->len = src[i].key.len + sizeof(": ") - 1
    2312 +                        + src[i].value.len + sizeof(CRLF) - 1;
    2313 +
    2314 +
    2315 +            size = (sizeof(ngx_http_script_copy_code_t)
    2316 +                       + src[i].key.len + sizeof(": ") - 1
    2317 +                       + src[i].value.len + sizeof(CRLF) - 1
    2318 +                       + sizeof(uintptr_t) - 1)
    2319 +                    & ~(sizeof(uintptr_t) - 1);
    2320 +
    2321 +            copy = ngx_array_push_n(conf->headers_set, size);
    2322 +            if (copy == NULL) {
    2323 +                return NGX_ERROR;
    2324 +            }
    2325 +
    2326 +            copy->code = ngx_http_script_copy_code;
    2327 +            copy->len = src[i].key.len + sizeof(": ") - 1
    2328 +                        + src[i].value.len + sizeof(CRLF) - 1;
    2329 +
    2330 +            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
    2331 +
    2332 +            p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
    2333 +            *p++ = ':'; *p++ = ' ';
    2334 +            p = ngx_cpymem(p, src[i].value.data, src[i].value.len);
    2335 +            *p++ = CR; *p = LF;
    2336 +
    2337 +        } else {
    2338 +            copy = ngx_array_push_n(conf->headers_set_len,
    2339 +                                    sizeof(ngx_http_script_copy_code_t));
    2340 +            if (copy == NULL) {
    2341 +                return NGX_ERROR;
    2342 +            }
    2343 +
    2344 +            copy->code = (ngx_http_script_code_pt)
    2345 +                                                 ngx_http_script_copy_len_code;
    2346 +            copy->len = src[i].key.len + sizeof(": ") - 1;
    2347 +
    2348 +
    2349 +            size = (sizeof(ngx_http_script_copy_code_t)
    2350 +                    + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
    2351 +                    & ~(sizeof(uintptr_t) - 1);
    2352 +
    2353 +            copy = ngx_array_push_n(conf->headers_set, size);
    2354 +            if (copy == NULL) {
    2355 +                return NGX_ERROR;
    2356 +            }
    2357 +
    2358 +            copy->code = ngx_http_script_copy_code;
    2359 +            copy->len = src[i].key.len + sizeof(": ") - 1;
    2360 +
    2361 +            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
    2362 +            p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
    2363 +            *p++ = ':'; *p = ' ';
    2364 +
    2365 +
    2366 +            ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
    2367 +
    2368 +            sc.cf = cf;
    2369 +            sc.source = &src[i].value;
    2370 +            sc.flushes = &conf->flushes;
    2371 +            sc.lengths = &conf->headers_set_len;
    2372 +            sc.values = &conf->headers_set;
    2373 +
    2374 +            if (ngx_http_script_compile(&sc) != NGX_OK) {
    2375 +                return NGX_ERROR;
    2376 +            }
    2377 +
    2378 +
    2379 +            copy = ngx_array_push_n(conf->headers_set_len,
    2380 +                                    sizeof(ngx_http_script_copy_code_t));
    2381 +            if (copy == NULL) {
    2382 +                return NGX_ERROR;
    2383 +            }
    2384 +
    2385 +            copy->code = (ngx_http_script_code_pt)
    2386 +                                                 ngx_http_script_copy_len_code;
    2387 +            copy->len = sizeof(CRLF) - 1;
    2388 +
    2389 +
    2390 +            size = (sizeof(ngx_http_script_copy_code_t)
    2391 +                    + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
    2392 +                    & ~(sizeof(uintptr_t) - 1);
    2393 +
    2394 +            copy = ngx_array_push_n(conf->headers_set, size);
    2395 +            if (copy == NULL) {
    2396 +                return NGX_ERROR;
    2397 +            }
    2398 +
    2399 +            copy->code = ngx_http_script_copy_code;
    2400 +            copy->len = sizeof(CRLF) - 1;
    2401 +
    2402 +            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
    2403 +            *p++ = CR; *p = LF;
    2404 +        }
    2405 +
    2406 +        code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
    2407 +        if (code == NULL) {
    2408 +            return NGX_ERROR;
    2409 +        }
    2410 +
    2411 +        *code = (uintptr_t) NULL;
    2412 +
    2413 +        code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t));
    2414 +        if (code == NULL) {
    2415 +            return NGX_ERROR;
    2416 +        }
    2417 +
    2418 +        *code = (uintptr_t) NULL;
    2419 +    }
    2420 +
    2421 +    code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
    2422 +    if (code == NULL) {
    2423 +        return NGX_ERROR;
    2424 +    }
    2425 +
    2426 +    *code = (uintptr_t) NULL;
    2427 +
    2428 +
    2429 +    hash.hash = &conf->headers_set_hash;
    2430 +    hash.key = ngx_hash_key_lc;
    2431 +    hash.max_size = conf->headers_hash_max_size;
    2432 +    hash.bucket_size = conf->headers_hash_bucket_size;
    2433 +    hash.name = "proxy_headers_hash";
    2434 +    hash.pool = cf->pool;
    2435 +    hash.temp_pool = NULL;
    2436 +
    2437 +    return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
    2438 +}
    2439 +
    2440 +
    2441 +static char *
    2442 +ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    2443 +{
    2444 +    ngx_http_proxy_loc_conf_t *plcf = conf;
    2445 +
    2446 +    size_t                      add;
    2447 +    u_short                     port;
    2448 +    ngx_str_t                  *value, *url;
    2449 +    ngx_url_t                   u;
    2450 +    ngx_uint_t                  n;
    2451 +    ngx_http_core_loc_conf_t   *clcf;
    2452 +    ngx_http_script_compile_t   sc;
    2453 +
    2454 +    if (plcf->upstream.upstream || plcf->proxy_lengths) {
    2455 +        return "is duplicate";
    2456 +    }
    2457 +
    2458 +    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    2459 +
    2460 +    clcf->handler = ngx_http_proxy_handler;
    2461 +
    2462 +    if (clcf->name.data[clcf->name.len - 1] == '/') {
    2463 +        clcf->auto_redirect = 1;
    2464 +    }
    2465 +
    2466 +    value = cf->args->elts;
    2467 +
    2468 +    url = &value[1];
    2469 +
    2470 +    n = ngx_http_script_variables_count(url);
    2471 +
    2472 +    if (n) {
    2473 +
    2474 +        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
    2475 +
    2476 +        sc.cf = cf;
    2477 +        sc.source = url;
    2478 +        sc.lengths = &plcf->proxy_lengths;
    2479 +        sc.values = &plcf->proxy_values;
    2480 +        sc.variables = n;
    2481 +        sc.complete_lengths = 1;
    2482 +        sc.complete_values = 1;
    2483 +
    2484 +        if (ngx_http_script_compile(&sc) != NGX_OK) {
    2485 +            return NGX_CONF_ERROR;
    2486 +        }
    2487 +
    2488 +#if (NGX_HTTP_SSL)
    2489 +        if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
    2490 +            return NGX_CONF_ERROR;
    2491 +        }
    2492 +#endif
    2493 +
    2494 +        return NGX_CONF_OK;
    2495 +    }
    2496 +
    2497 +    if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
    2498 +        add = 7;
    2499 +        port = 80;
    2500 +
    2501 +    } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
    2502 +
    2503 +#if (NGX_HTTP_SSL)
    2504 +        if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
    2505 +            return NGX_CONF_ERROR;
    2506 +        }
    2507 +
    2508 +        add = 8;
    2509 +        port = 443;
    2510 +#else
    2511 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2512 +                           "https protocol requires SSL support");
    2513 +        return NGX_CONF_ERROR;
    2514 +#endif
    2515 +
    2516 +    } else {
    2517 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
    2518 +        return NGX_CONF_ERROR;
    2519 +    }
    2520 +
    2521 +    ngx_memzero(&u, sizeof(ngx_url_t));
    2522 +
    2523 +    u.url.len = url->len - add;
    2524 +    u.url.data = url->data + add;
    2525 +    u.default_port = port;
    2526 +    u.uri_part = 1;
    2527 +    u.no_resolve = 1;
    2528 +
    2529 +    plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
    2530 +    if (plcf->upstream.upstream == NULL) {
    2531 +        return NGX_CONF_ERROR;
    2532 +    }
    2533 +
    2534 +    plcf->vars.schema.len = add;
    2535 +    plcf->vars.schema.data = url->data;
    2536 +    plcf->vars.key_start = plcf->vars.schema;
    2537 +
    2538 +    ngx_http_proxy_set_vars(&u, &plcf->vars);
    2539 +
    2540 +    plcf->location = clcf->name;
    2541 +
    2542 +    if (clcf->named
    2543 +#if (NGX_PCRE)
    2544 +        || clcf->regex
    2545 +#endif
    2546 +        || clcf->noname)
    2547 +    {
    2548 +        if (plcf->vars.uri.len) {
    2549 +            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2550 +                               "\"proxy_pass\" may not have URI part in "
    2551 +                               "location given by regular expression, "
    2552 +                               "or inside named location, "
    2553 +                               "or inside the \"if\" statement, "
    2554 +                               "or inside the \"limit_except\" block");
    2555 +            return NGX_CONF_ERROR;
    2556 +        }
    2557 +
    2558 +        plcf->location.len = 0;
    2559 +    }
    2560 +
    2561 +    plcf->url = *url;
    2562 +
    2563 +    return NGX_CONF_OK;
    2564 +}
    2565 +
    2566 +
    2567 +static char *
    2568 +ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    2569 +{
    2570 +    ngx_http_proxy_loc_conf_t *plcf = conf;
    2571 +
    2572 +    ngx_str_t                  *value;
    2573 +    ngx_array_t                *vars_lengths, *vars_values;
    2574 +    ngx_http_script_compile_t   sc;
    2575 +    ngx_http_proxy_redirect_t  *pr;
    2576 +
    2577 +    if (plcf->redirect == 0) {
    2578 +        return NGX_CONF_OK;
    2579 +    }
    2580 +
    2581 +    value = cf->args->elts;
    2582 +
    2583 +    if (cf->args->nelts == 2) {
    2584 +        if (ngx_strcmp(value[1].data, "off") == 0) {
    2585 +            plcf->redirect = 0;
    2586 +            plcf->redirects = NULL;
    2587 +            return NGX_CONF_OK;
    2588 +        }
    2589 +
    2590 +        if (ngx_strcmp(value[1].data, "false") == 0) {
    2591 +            ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
    2592 +                           "invalid parameter \"false\", use \"off\" instead");
    2593 +            plcf->redirect = 0;
    2594 +            plcf->redirects = NULL;
    2595 +            return NGX_CONF_OK;
    2596 +        }
    2597 +
    2598 +        if (ngx_strcmp(value[1].data, "default") != 0) {
    2599 +            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2600 +                               "invalid parameter \"%V\"", &value[1]);
    2601 +            return NGX_CONF_ERROR;
    2602 +        }
    2603 +    }
    2604 +
    2605 +    if (plcf->redirects == NULL) {
    2606 +        plcf->redirects = ngx_array_create(cf->pool, 1,
    2607 +                                           sizeof(ngx_http_proxy_redirect_t));
    2608 +        if (plcf->redirects == NULL) {
    2609 +            return NGX_CONF_ERROR;
    2610 +        }
    2611 +    }
    2612 +
    2613 +    pr = ngx_array_push(plcf->redirects);
    2614 +    if (pr == NULL) {
    2615 +        return NGX_CONF_ERROR;
    2616 +    }
    2617 +
    2618 +    if (ngx_strcmp(value[1].data, "default") == 0) {
    2619 +        if (plcf->proxy_lengths) {
    2620 +            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2621 +                               "\"proxy_redirect default\" may not be used "
    2622 +                               "with \"proxy_pass\" directive with variables");
    2623 +            return NGX_CONF_ERROR;
    2624 +        }
    2625 +
    2626 +        if (plcf->url.data == NULL) {
    2627 +            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2628 +                               "\"proxy_redirect default\" must go "
    2629 +                               "after the \"proxy_pass\" directive");
    2630 +            return NGX_CONF_ERROR;
    2631 +        }
    2632 +
    2633 +        pr->handler = ngx_http_proxy_rewrite_redirect_text;
    2634 +        pr->redirect = plcf->url;
    2635 +
    2636 +        if (plcf->vars.uri.len) {
    2637 +            pr->replacement.text = plcf->location;
    2638 +
    2639 +        } else {
    2640 +            ngx_str_null(&pr->replacement.text);
    2641 +        }
    2642 +
    2643 +        return NGX_CONF_OK;
    2644 +    }
    2645 +
    2646 +    if (ngx_http_script_variables_count(&value[2]) == 0) {
    2647 +        pr->handler = ngx_http_proxy_rewrite_redirect_text;
    2648 +        pr->redirect = value[1];
    2649 +        pr->replacement.text = value[2];
    2650 +
    2651 +        return NGX_CONF_OK;
    2652 +    }
    2653 +
    2654 +    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
    2655 +
    2656 +    vars_lengths = NULL;
    2657 +    vars_values = NULL;
    2658 +
    2659 +    sc.cf = cf;
    2660 +    sc.source = &value[2];
    2661 +    sc.lengths = &vars_lengths;
    2662 +    sc.values = &vars_values;
    2663 +    sc.complete_lengths = 1;
    2664 +    sc.complete_values = 1;
    2665 +
    2666 +    if (ngx_http_script_compile(&sc) != NGX_OK) {
    2667 +        return NGX_CONF_ERROR;
    2668 +    }
    2669 +
    2670 +    pr->handler = ngx_http_proxy_rewrite_redirect_vars;
    2671 +    pr->redirect = value[1];
    2672 +    pr->replacement.vars.lengths = vars_lengths->elts;
    2673 +    pr->replacement.vars.values = vars_values->elts;
    2674 +
    2675 +    return NGX_CONF_OK;
    2676 +}
    2677 +
    2678 +
    2679 +static char *
    2680 +ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    2681 +{
    2682 +    ngx_http_proxy_loc_conf_t *plcf = conf;
    2683 +
    2684 +    ngx_str_t                  *value;
    2685 +    ngx_http_script_compile_t   sc;
    2686 +
    2687 +    if (plcf->upstream.store != NGX_CONF_UNSET
    2688 +        || plcf->upstream.store_lengths)
    2689 +    {
    2690 +        return "is duplicate";
    2691 +    }
    2692 +
    2693 +    value = cf->args->elts;
    2694 +
    2695 +    if (ngx_strcmp(value[1].data, "off") == 0) {
    2696 +        plcf->upstream.store = 0;
    2697 +        return NGX_CONF_OK;
    2698 +    }
    2699 +
    2700 +#if (NGX_HTTP_CACHE)
    2701 +
    2702 +    if (plcf->upstream.cache != NGX_CONF_UNSET_PTR
    2703 +        && plcf->upstream.cache != NULL)
    2704 +    {
    2705 +        return "is incompatible with \"proxy_cache\"";
    2706 +    }
    2707 +
    2708 +#endif
    2709 +
    2710 +    if (ngx_strcmp(value[1].data, "on") == 0) {
    2711 +        plcf->upstream.store = 1;
    2712 +        return NGX_CONF_OK;
    2713 +    }
    2714 +
    2715 +    /* include the terminating '\0' into script */
    2716 +    value[1].len++;
    2717 +
    2718 +    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
    2719 +
    2720 +    sc.cf = cf;
    2721 +    sc.source = &value[1];
    2722 +    sc.lengths = &plcf->upstream.store_lengths;
    2723 +    sc.values = &plcf->upstream.store_values;
    2724 +    sc.variables = ngx_http_script_variables_count(&value[1]);
    2725 +    sc.complete_lengths = 1;
    2726 +    sc.complete_values = 1;
    2727 +
    2728 +    if (ngx_http_script_compile(&sc) != NGX_OK) {
    2729 +        return NGX_CONF_ERROR;
    2730 +    }
    2731 +
    2732 +    return NGX_CONF_OK;
    2733 +}
    2734 +
    2735 +
    2736 +#if (NGX_HTTP_CACHE)
    2737 +
    2738 +static char *
    2739 +ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    2740 +{
    2741 +    ngx_http_proxy_loc_conf_t *plcf = conf;
    2742 +
    2743 +    ngx_str_t  *value;
    2744 +
    2745 +    value = cf->args->elts;
    2746 +
    2747 +    if (plcf->upstream.cache != NGX_CONF_UNSET_PTR) {
    2748 +        return "is duplicate";
    2749 +    }
    2750 +
    2751 +    if (ngx_strcmp(value[1].data, "off") == 0) {
    2752 +        plcf->upstream.cache = NULL;
    2753 +        return NGX_CONF_OK;
    2754 +    }
    2755 +
    2756 +    if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) {
    2757 +        return "is incompatible with \"proxy_store\"";
    2758 +    }
    2759 +
    2760 +    plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
    2761 +                                                 &ngx_http_proxy_module);
    2762 +    if (plcf->upstream.cache == NULL) {
    2763 +        return NGX_CONF_ERROR;
    2764 +    }
    2765 +
    2766 +    return NGX_CONF_OK;
    2767 +}
    2768 +
    2769 +
    2770 +static char *
    2771 +ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    2772 +{
    2773 +    ngx_http_proxy_loc_conf_t *plcf = conf;
    2774 +
    2775 +    ngx_str_t                         *value;
    2776 +    ngx_http_compile_complex_value_t   ccv;
    2777 +
    2778 +    value = cf->args->elts;
    2779 +
    2780 +    if (plcf->cache_key.value.len) {
    2781 +        return "is duplicate";
    2782 +    }
    2783 +
    2784 +    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
    2785 +
    2786 +    ccv.cf = cf;
    2787 +    ccv.value = &value[1];
    2788 +    ccv.complex_value = &plcf->cache_key;
    2789 +
    2790 +    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
    2791 +        return NGX_CONF_ERROR;
    2792 +    }
    2793 +
    2794 +    return NGX_CONF_OK;
    2795 +}
    2796 +
    2797 +#endif
    2798 +
    2799 +
    2800 +static char *
    2801 +ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
    2802 +{
    2803 +#if (NGX_FREEBSD)
    2804 +    ssize_t *np = data;
    2805 +
    2806 +    if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
    2807 +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
    2808 +                           "\"proxy_send_lowat\" must be less than %d "
    2809 +                           "(sysctl net.inet.tcp.sendspace)",
    2810 +                           ngx_freebsd_net_inet_tcp_sendspace);
    2811 +
    2812 +        return NGX_CONF_ERROR;
    2813 +    }
    2814 +
    2815 +#elif !(NGX_HAVE_SO_SNDLOWAT)
    2816 +    ssize_t *np = data;
    2817 +
    2818 +    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
    2819 +                       "\"proxy_send_lowat\" is not supported, ignored");
    2820 +
    2821 +    *np = 0;
    2822 +
    2823 +#endif
    2824 +
    2825 +    return NGX_CONF_OK;
    2826 +}
    2827 +
    2828 +
    2829 +#if (NGX_HTTP_SSL)
    2830 +
    2831 +static ngx_int_t
    2832 +ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
    2833 +{
    2834 +    ngx_pool_cleanup_t  *cln;
    2835 +
    2836 +    plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
    2837 +    if (plcf->upstream.ssl == NULL) {
    2838 +        return NGX_ERROR;
    2839 +    }
    2840 +
    2841 +    plcf->upstream.ssl->log = cf->log;
    2842 +
    2843 +    if (ngx_ssl_create(plcf->upstream.ssl,
    2844 +                       NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
    2845 +        != NGX_OK)
    2846 +    {
    2847 +        return NGX_ERROR;
    2848 +    }
    2849 +
    2850 +    cln = ngx_pool_cleanup_add(cf->pool, 0);
    2851 +    if (cln == NULL) {
    2852 +        return NGX_ERROR;
    2853 +    }
    2854 +
    2855 +    cln->handler = ngx_ssl_cleanup_ctx;
    2856 +    cln->data = plcf->upstream.ssl;
    2857 +
    2858 +    return NGX_OK;
    2859 +}
    2860 +
    2861 +#endif
    2862 +
    2863 +
    2864 +static void
    2865 +ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
    2866 +{
    2867 +    if (u->family != AF_UNIX) {
    2868 +
    2869 +        if (u->no_port || u->port == u->default_port) {
    2870 +
    2871 +            v->host_header = u->host;
    2872 +
    2873 +            if (u->default_port == 80) {
    2874 +                ngx_str_set(&v->port, "80");
    2875 +
    2876 +            } else {
    2877 +                ngx_str_set(&v->port, "443");
    2878 +            }
    2879 +
    2880 +        } else {
    2881 +            v->host_header.len = u->host.len + 1 + u->port_text.len;
    2882 +            v->host_header.data = u->host.data;
    2883 +            v->port = u->port_text;
    2884 +        }
    2885 +
    2886 +        v->key_start.len += v->host_header.len;
    2887 +
    2888 +    } else {
    2889 +        ngx_str_set(&v->host_header, "localhost");
    2890 +        ngx_str_null(&v->port);
    2891 +        v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
    2892 +    }
    2893 +
    2894 +    v->uri = u->uri;
    2895 +}
    2896 diff -uNr ../nginx-0.8.55/src/http/ngx_http_upstream.h src/http/ngx_http_upstream.h
    2897 --- ../nginx-0.8.55/src/http/ngx_http_upstream.h        2010-07-19 02:36:04.000000000 -0700
    2898 +++ src/http/ngx_http_upstream.h        2011-09-13 15:27:08.000000000 -0700
    2899 @@ -177,6 +177,9 @@
    2900  #if (NGX_HTTP_SSL)
    2901      ngx_ssl_t                       *ssl;
    2902      ngx_flag_t                       ssl_session_reuse;
    2903 +    ngx_uint_t                       ssl_verify;
    2904 +    ngx_uint_t                       ssl_verify_depth;
    2905 +    ngx_str_t                        ssl_ca_certificate;
    2906  #endif
    2907  
    2908  } ngx_http_upstream_conf_t;
    2909 diff -uNr ../nginx-0.8.55/src/http/ngx_http_upstream.h.orig src/http/ngx_http_upstream.h.orig
    2910 --- ../nginx-0.8.55/src/http/ngx_http_upstream.h.orig   1969-12-31 16:00:00.000000000 -0800
    2911 +++ src/http/ngx_http_upstream.h.orig   2010-07-19 02:36:04.000000000 -0700
    2912 @@ -0,0 +1,345 @@
    2913 +
    2914 +/*
    2915 + * Copyright (C) Igor Sysoev
    2916 + */
    2917 +
    2918 +
    2919 +#ifndef _NGX_HTTP_UPSTREAM_H_INCLUDED_
    2920 +#define _NGX_HTTP_UPSTREAM_H_INCLUDED_
    2921 +
    2922 +
    2923 +#include <ngx_config.h>
    2924 +#include <ngx_core.h>
    2925 +#include <ngx_event.h>
    2926 +#include <ngx_event_connect.h>
    2927 +#include <ngx_event_pipe.h>
    2928 +#include <ngx_http.h>
    2929 +
    2930 +
    2931 +#define NGX_HTTP_UPSTREAM_FT_ERROR           0x00000002
    2932 +#define NGX_HTTP_UPSTREAM_FT_TIMEOUT         0x00000004
    2933 +#define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER  0x00000008
    2934 +#define NGX_HTTP_UPSTREAM_FT_HTTP_500        0x00000010
    2935 +#define NGX_HTTP_UPSTREAM_FT_HTTP_502        0x00000020
    2936 +#define NGX_HTTP_UPSTREAM_FT_HTTP_503        0x00000040
    2937 +#define NGX_HTTP_UPSTREAM_FT_HTTP_504        0x00000080
    2938 +#define NGX_HTTP_UPSTREAM_FT_HTTP_404        0x00000100
    2939 +#define NGX_HTTP_UPSTREAM_FT_UPDATING        0x00000200
    2940 +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK       0x00000400
    2941 +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING     0x00000800
    2942 +#define NGX_HTTP_UPSTREAM_FT_NOLIVE          0x40000000
    2943 +#define NGX_HTTP_UPSTREAM_FT_OFF             0x80000000
    2944 +
    2945 +#define NGX_HTTP_UPSTREAM_FT_STATUS          (NGX_HTTP_UPSTREAM_FT_HTTP_500  \
    2946 +                                             |NGX_HTTP_UPSTREAM_FT_HTTP_502  \
    2947 +                                             |NGX_HTTP_UPSTREAM_FT_HTTP_503  \
    2948 +                                             |NGX_HTTP_UPSTREAM_FT_HTTP_504  \
    2949 +                                             |NGX_HTTP_UPSTREAM_FT_HTTP_404)
    2950 +
    2951 +#define NGX_HTTP_UPSTREAM_INVALID_HEADER     40
    2952 +
    2953 +
    2954 +#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT    0x00000002
    2955 +#define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES     0x00000004
    2956 +#define NGX_HTTP_UPSTREAM_IGN_EXPIRES        0x00000008
    2957 +#define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL  0x00000010
    2958 +#define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE     0x00000020
    2959 +
    2960 +
    2961 +typedef struct {
    2962 +    ngx_msec_t                       bl_time;
    2963 +    ngx_uint_t                       bl_state;
    2964 +
    2965 +    ngx_uint_t                       status;
    2966 +    time_t                           response_sec;
    2967 +    ngx_uint_t                       response_msec;
    2968 +    off_t                           response_length;
    2969 +
    2970 +    ngx_str_t                       *peer;
    2971 +} ngx_http_upstream_state_t;
    2972 +
    2973 +
    2974 +typedef struct {
    2975 +    ngx_hash_t                       headers_in_hash;
    2976 +    ngx_array_t                      upstreams;
    2977 +                                             /* ngx_http_upstream_srv_conf_t */
    2978 +} ngx_http_upstream_main_conf_t;
    2979 +
    2980 +typedef struct ngx_http_upstream_srv_conf_s  ngx_http_upstream_srv_conf_t;
    2981 +
    2982 +typedef ngx_int_t (*ngx_http_upstream_init_pt)(ngx_conf_t *cf,
    2983 +    ngx_http_upstream_srv_conf_t *us);
    2984 +typedef ngx_int_t (*ngx_http_upstream_init_peer_pt)(ngx_http_request_t *r,
    2985 +    ngx_http_upstream_srv_conf_t *us);
    2986 +
    2987 +
    2988 +typedef struct {
    2989 +    ngx_http_upstream_init_pt        init_upstream;
    2990 +    ngx_http_upstream_init_peer_pt   init;
    2991 +    void                            *data;
    2992 +} ngx_http_upstream_peer_t;
    2993 +
    2994 +
    2995 +typedef struct {
    2996 +    ngx_addr_t                      *addrs;
    2997 +    ngx_uint_t                       naddrs;
    2998 +    ngx_uint_t                       weight;
    2999 +    ngx_uint_t                       max_fails;
    3000 +    time_t                           fail_timeout;
    3001 +
    3002 +    unsigned                         down:1;
    3003 +    unsigned                         backup:1;
    3004 +} ngx_http_upstream_server_t;
    3005 +
    3006 +
    3007 +#define NGX_HTTP_UPSTREAM_CREATE        0x0001
    3008 +#define NGX_HTTP_UPSTREAM_WEIGHT        0x0002
    3009 +#define NGX_HTTP_UPSTREAM_MAX_FAILS     0x0004
    3010 +#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT  0x0008
    3011 +#define NGX_HTTP_UPSTREAM_DOWN          0x0010
    3012 +#define NGX_HTTP_UPSTREAM_BACKUP        0x0020
    3013 +
    3014 +
    3015 +struct ngx_http_upstream_srv_conf_s {
    3016 +    ngx_http_upstream_peer_t         peer;
    3017 +    void                           **srv_conf;
    3018 +
    3019 +    ngx_array_t                     *servers;  /* ngx_http_upstream_server_t */
    3020 +
    3021 +    ngx_uint_t                       flags;
    3022 +    ngx_str_t                        host;
    3023 +    u_char                          *file_name;
    3024 +    ngx_uint_t                       line;
    3025 +    in_port_t                        port;
    3026 +    in_port_t                        default_port;
    3027 +};
    3028 +
    3029 +
    3030 +typedef struct {
    3031 +    ngx_http_upstream_srv_conf_t    *upstream;
    3032 +
    3033 +    ngx_msec_t                       connect_timeout;
    3034 +    ngx_msec_t                       send_timeout;
    3035 +    ngx_msec_t                       read_timeout;
    3036 +    ngx_msec_t                       timeout;
    3037 +
    3038 +    size_t                           send_lowat;
    3039 +    size_t                           buffer_size;
    3040 +
    3041 +    size_t                           busy_buffers_size;
    3042 +    size_t                           max_temp_file_size;
    3043 +    size_t                           temp_file_write_size;
    3044 +
    3045 +    size_t                           busy_buffers_size_conf;
    3046 +    size_t                           max_temp_file_size_conf;
    3047 +    size_t                           temp_file_write_size_conf;
    3048 +
    3049 +    ngx_bufs_t                       bufs;
    3050 +
    3051 +    ngx_uint_t                       ignore_headers;
    3052 +    ngx_uint_t                       next_upstream;
    3053 +    ngx_uint_t                       store_access;
    3054 +    ngx_flag_t                       buffering;
    3055 +    ngx_flag_t                       pass_request_headers;
    3056 +    ngx_flag_t                       pass_request_body;
    3057 +
    3058 +    ngx_flag_t                       ignore_client_abort;
    3059 +    ngx_flag_t                       intercept_errors;
    3060 +    ngx_flag_t                       cyclic_temp_file;
    3061 +
    3062 +    ngx_path_t                      *temp_path;
    3063 +
    3064 +    ngx_hash_t                       hide_headers_hash;
    3065 +    ngx_array_t                     *hide_headers;
    3066 +    ngx_array_t                     *pass_headers;
    3067 +
    3068 +    ngx_addr_t                      *local;
    3069 +
    3070 +#if (NGX_HTTP_CACHE)
    3071 +    ngx_shm_zone_t                  *cache;
    3072 +
    3073 +    ngx_uint_t                       cache_min_uses;
    3074 +    ngx_uint_t                       cache_use_stale;
    3075 +    ngx_uint_t                       cache_methods;
    3076 +
    3077 +    ngx_array_t                     *cache_valid;
    3078 +    ngx_array_t                     *cache_bypass;
    3079 +    ngx_array_t                     *no_cache;
    3080 +#endif
    3081 +
    3082 +    ngx_array_t                     *store_lengths;
    3083 +    ngx_array_t                     *store_values;
    3084 +
    3085 +    signed                           store:2;
    3086 +    unsigned                         intercept_404:1;
    3087 +    unsigned                         change_buffering:1;
    3088 +
    3089 +#if (NGX_HTTP_SSL)
    3090 +    ngx_ssl_t                       *ssl;
    3091 +    ngx_flag_t                       ssl_session_reuse;
    3092 +#endif
    3093 +
    3094 +} ngx_http_upstream_conf_t;
    3095 +
    3096 +
    3097 +typedef struct {
    3098 +    ngx_str_t                        name;
    3099 +    ngx_http_header_handler_pt       handler;
    3100 +    ngx_uint_t                       offset;
    3101 +    ngx_http_header_handler_pt       copy_handler;
    3102 +    ngx_uint_t                       conf;
    3103 +    ngx_uint_t                       redirect;  /* unsigned   redirect:1; */
    3104 +} ngx_http_upstream_header_t;
    3105 +
    3106 +
    3107 +typedef struct {
    3108 +    ngx_list_t                       headers;
    3109 +
    3110 +    ngx_uint_t                       status_n;
    3111 +    ngx_str_t                        status_line;
    3112 +
    3113 +    ngx_table_elt_t                 *status;
    3114 +    ngx_table_elt_t                 *date;
    3115 +    ngx_table_elt_t                 *server;
    3116 +    ngx_table_elt_t                 *connection;
    3117 +
    3118 +    ngx_table_elt_t                 *expires;
    3119 +    ngx_table_elt_t                 *etag;
    3120 +    ngx_table_elt_t                 *x_accel_expires;
    3121 +    ngx_table_elt_t                 *x_accel_redirect;
    3122 +    ngx_table_elt_t                 *x_accel_limit_rate;
    3123 +
    3124 +    ngx_table_elt_t                 *content_type;
    3125 +    ngx_table_elt_t                 *content_length;
    3126 +
    3127 +    ngx_table_elt_t                 *last_modified;
    3128 +    ngx_table_elt_t                 *location;
    3129 +    ngx_table_elt_t                 *accept_ranges;
    3130 +    ngx_table_elt_t                 *www_authenticate;
    3131 +
    3132 +#if (NGX_HTTP_GZIP)
    3133 +    ngx_table_elt_t                 *content_encoding;
    3134 +#endif
    3135 +
    3136 +    off_t                            content_length_n;
    3137 +
    3138 +    ngx_array_t                      cache_control;
    3139 +} ngx_http_upstream_headers_in_t;
    3140 +
    3141 +
    3142 +typedef struct {
    3143 +    ngx_str_t                        host;
    3144 +    in_port_t                        port;
    3145 +    ngx_uint_t                       no_port; /* unsigned no_port:1 */
    3146 +
    3147 +    ngx_uint_t                       naddrs;
    3148 +    in_addr_t                       *addrs;
    3149 +
    3150 +    struct sockaddr                 *sockaddr;
    3151 +    socklen_t                        socklen;
    3152 +
    3153 +    ngx_resolver_ctx_t              *ctx;
    3154 +} ngx_http_upstream_resolved_t;
    3155 +
    3156 +
    3157 +typedef void (*ngx_http_upstream_handler_pt)(ngx_http_request_t *r,
    3158 +    ngx_http_upstream_t *u);
    3159 +
    3160 +
    3161 +struct ngx_http_upstream_s {
    3162 +    ngx_http_upstream_handler_pt     read_event_handler;
    3163 +    ngx_http_upstream_handler_pt     write_event_handler;
    3164 +
    3165 +    ngx_peer_connection_t            peer;
    3166 +
    3167 +    ngx_event_pipe_t                *pipe;
    3168 +
    3169 +    ngx_chain_t                     *request_bufs;
    3170 +
    3171 +    ngx_output_chain_ctx_t           output;
    3172 +    ngx_chain_writer_ctx_t           writer;
    3173 +
    3174 +    ngx_http_upstream_conf_t        *conf;
    3175 +
    3176 +    ngx_http_upstream_headers_in_t   headers_in;
    3177 +
    3178 +    ngx_http_upstream_resolved_t    *resolved;
    3179 +
    3180 +    ngx_buf_t                        buffer;
    3181 +    size_t                           length;
    3182 +
    3183 +    ngx_chain_t                     *out_bufs;
    3184 +    ngx_chain_t                     *busy_bufs;
    3185 +    ngx_chain_t                     *free_bufs;
    3186 +
    3187 +    ngx_int_t                      (*input_filter_init)(void *data);
    3188 +    ngx_int_t                      (*input_filter)(void *data, ssize_t bytes);
    3189 +    void                            *input_filter_ctx;
    3190 +
    3191 +#if (NGX_HTTP_CACHE)
    3192 +    ngx_int_t                      (*create_key)(ngx_http_request_t *r);
    3193 +#endif
    3194 +    ngx_int_t                      (*create_request)(ngx_http_request_t *r);
    3195 +    ngx_int_t                      (*reinit_request)(ngx_http_request_t *r);
    3196 +    ngx_int_t                      (*process_header)(ngx_http_request_t *r);
    3197 +    void                           (*abort_request)(ngx_http_request_t *r);
    3198 +    void                           (*finalize_request)(ngx_http_request_t *r,
    3199 +                                         ngx_int_t rc);
    3200 +    ngx_int_t                      (*rewrite_redirect)(ngx_http_request_t *r,
    3201 +                                         ngx_table_elt_t *h, size_t prefix);
    3202 +
    3203 +    ngx_msec_t                       timeout;
    3204 +
    3205 +    ngx_http_upstream_state_t       *state;
    3206 +
    3207 +    ngx_str_t                        method;
    3208 +    ngx_str_t                        schema;
    3209 +    ngx_str_t                        uri;
    3210 +
    3211 +    ngx_http_cleanup_pt             *cleanup;
    3212 +
    3213 +    unsigned                         store:1;
    3214 +    unsigned                         cacheable:1;
    3215 +    unsigned                         accel:1;
    3216 +    unsigned                         ssl:1;
    3217 +#if (NGX_HTTP_CACHE)
    3218 +    unsigned                         cache_status:3;
    3219 +#endif
    3220 +
    3221 +    unsigned                         buffering:1;
    3222 +
    3223 +    unsigned                         request_sent:1;
    3224 +    unsigned                         header_sent:1;
    3225 +};
    3226 +
    3227 +
    3228 +typedef struct {
    3229 +    ngx_uint_t                      status;
    3230 +    ngx_uint_t                      mask;
    3231 +} ngx_http_upstream_next_t;
    3232 +
    3233 +
    3234 +ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r,
    3235 +    ngx_http_variable_value_t *v, uintptr_t data);
    3236 +
    3237 +ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
    3238 +void ngx_http_upstream_init(ngx_http_request_t *r);
    3239 +ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
    3240 +    ngx_url_t *u, ngx_uint_t flags);
    3241 +char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
    3242 +    void *conf);
    3243 +ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
    3244 +    ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
    3245 +    ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
    3246 +
    3247 +
    3248 +#define ngx_http_conf_upstream_srv_conf(uscf, module)                         \
    3249 +    uscf->srv_conf[module.ctx_index]
    3250 +
    3251 +
    3252 +extern ngx_module_t        ngx_http_upstream_module;
    3253 +extern ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[];
    3254 +extern ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[];
    3255 +
    3256 +
    3257 +#endif /* _NGX_HTTP_UPSTREAM_H_INCLUDED_ */
    3258 
    3259 }}}
     1Proxy should be able to verify peer's SSL certificate.