Annotation of embedaddon/nginx/src/http/modules/ngx_http_proxy_module.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>