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

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Unbit S.a.s. 2009-2010
        !             4:  * Copyright (C) 2008 Manlio Perillo (manlio.perillo@gmail.com)
        !             5:  * Copyright (C) Igor Sysoev
        !             6:  * Copyright (C) Nginx, Inc.
        !             7:  */
        !             8: 
        !             9: 
        !            10: #include <ngx_config.h>
        !            11: #include <ngx_core.h>
        !            12: #include <ngx_http.h>
        !            13: 
        !            14: 
        !            15: typedef struct {
        !            16:     ngx_http_upstream_conf_t   upstream;
        !            17: 
        !            18:     ngx_array_t               *flushes;
        !            19:     ngx_array_t               *params_len;
        !            20:     ngx_array_t               *params;
        !            21:     ngx_array_t               *params_source;
        !            22: 
        !            23:     ngx_hash_t                 headers_hash;
        !            24:     ngx_uint_t                 header_params;
        !            25: 
        !            26:     ngx_array_t               *uwsgi_lengths;
        !            27:     ngx_array_t               *uwsgi_values;
        !            28: 
        !            29: #if (NGX_HTTP_CACHE)
        !            30:     ngx_http_complex_value_t   cache_key;
        !            31: #endif
        !            32: 
        !            33:     ngx_str_t                  uwsgi_string;
        !            34: 
        !            35:     ngx_uint_t                 modifier1;
        !            36:     ngx_uint_t                 modifier2;
        !            37: } ngx_http_uwsgi_loc_conf_t;
        !            38: 
        !            39: 
        !            40: static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r,
        !            41:     ngx_http_uwsgi_loc_conf_t *uwcf);
        !            42: static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
        !            43: static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
        !            44: static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
        !            45: static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
        !            46: static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
        !            47: static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
        !            48:     ngx_int_t rc);
        !            49: 
        !            50: static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
        !            51: static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
        !            52:     void *child);
        !            53: static ngx_int_t ngx_http_uwsgi_merge_params(ngx_conf_t *cf,
        !            54:     ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev);
        !            55: 
        !            56: static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
        !            57:     void *conf);
        !            58: static char *ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
        !            59:     void *conf);
        !            60: 
        !            61: #if (NGX_HTTP_CACHE)
        !            62: static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r);
        !            63: static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
        !            64:     void *conf);
        !            65: static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
        !            66:     void *conf);
        !            67: #endif
        !            68: 
        !            69: 
        !            70: static ngx_conf_num_bounds_t  ngx_http_uwsgi_modifier_bounds = {
        !            71:     ngx_conf_check_num_bounds, 0, 255
        !            72: };
        !            73: 
        !            74: 
        !            75: static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
        !            76:     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
        !            77:     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
        !            78:     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
        !            79:     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
        !            80:     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
        !            81:     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
        !            82:     { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
        !            83:     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
        !            84:     { ngx_null_string, 0 }
        !            85: };
        !            86: 
        !            87: 
        !            88: ngx_module_t  ngx_http_uwsgi_module;
        !            89: 
        !            90: 
        !            91: static ngx_command_t ngx_http_uwsgi_commands[] = {
        !            92: 
        !            93:     { ngx_string("uwsgi_pass"),
        !            94:       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
        !            95:       ngx_http_uwsgi_pass,
        !            96:       NGX_HTTP_LOC_CONF_OFFSET,
        !            97:       0,
        !            98:       NULL },
        !            99: 
        !           100:     { ngx_string("uwsgi_modifier1"),
        !           101:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           102:       ngx_conf_set_num_slot,
        !           103:       NGX_HTTP_LOC_CONF_OFFSET,
        !           104:       offsetof(ngx_http_uwsgi_loc_conf_t, modifier1),
        !           105:       &ngx_http_uwsgi_modifier_bounds },
        !           106: 
        !           107:     { ngx_string("uwsgi_modifier2"),
        !           108:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           109:       ngx_conf_set_num_slot,
        !           110:       NGX_HTTP_LOC_CONF_OFFSET,
        !           111:       offsetof(ngx_http_uwsgi_loc_conf_t, modifier2),
        !           112:       &ngx_http_uwsgi_modifier_bounds },
        !           113: 
        !           114:     { ngx_string("uwsgi_store"),
        !           115:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           116:       ngx_http_uwsgi_store,
        !           117:       NGX_HTTP_LOC_CONF_OFFSET,
        !           118:       0,
        !           119:       NULL },
        !           120: 
        !           121:     { ngx_string("uwsgi_store_access"),
        !           122:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
        !           123:       ngx_conf_set_access_slot,
        !           124:       NGX_HTTP_LOC_CONF_OFFSET,
        !           125:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.store_access),
        !           126:       NULL },
        !           127: 
        !           128:     { ngx_string("uwsgi_buffering"),
        !           129:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           130:       ngx_conf_set_flag_slot,
        !           131:       NGX_HTTP_LOC_CONF_OFFSET,
        !           132:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffering),
        !           133:       NULL },
        !           134: 
        !           135:     { ngx_string("uwsgi_ignore_client_abort"),
        !           136:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           137:       ngx_conf_set_flag_slot,
        !           138:       NGX_HTTP_LOC_CONF_OFFSET,
        !           139:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort),
        !           140:       NULL },
        !           141: 
        !           142:     { ngx_string("uwsgi_bind"),
        !           143:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           144:       ngx_http_upstream_bind_set_slot,
        !           145:       NGX_HTTP_LOC_CONF_OFFSET,
        !           146:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.local),
        !           147:       NULL },
        !           148: 
        !           149:     { ngx_string("uwsgi_connect_timeout"),
        !           150:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           151:       ngx_conf_set_msec_slot,
        !           152:       NGX_HTTP_LOC_CONF_OFFSET,
        !           153:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout),
        !           154:       NULL },
        !           155: 
        !           156:     { ngx_string("uwsgi_send_timeout"),
        !           157:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           158:       ngx_conf_set_msec_slot,
        !           159:       NGX_HTTP_LOC_CONF_OFFSET,
        !           160:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.send_timeout),
        !           161:       NULL },
        !           162: 
        !           163:     { ngx_string("uwsgi_buffer_size"),
        !           164:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           165:       ngx_conf_set_size_slot,
        !           166:       NGX_HTTP_LOC_CONF_OFFSET,
        !           167:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffer_size),
        !           168:       NULL },
        !           169: 
        !           170:     { ngx_string("uwsgi_pass_request_headers"),
        !           171:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           172:       ngx_conf_set_flag_slot,
        !           173:       NGX_HTTP_LOC_CONF_OFFSET,
        !           174:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers),
        !           175:       NULL },
        !           176: 
        !           177:     { ngx_string("uwsgi_pass_request_body"),
        !           178:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           179:       ngx_conf_set_flag_slot,
        !           180:       NGX_HTTP_LOC_CONF_OFFSET,
        !           181:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body),
        !           182:       NULL },
        !           183: 
        !           184:     { ngx_string("uwsgi_intercept_errors"),
        !           185:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           186:       ngx_conf_set_flag_slot,
        !           187:       NGX_HTTP_LOC_CONF_OFFSET,
        !           188:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors),
        !           189:       NULL },
        !           190: 
        !           191:     { ngx_string("uwsgi_read_timeout"),
        !           192:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           193:       ngx_conf_set_msec_slot,
        !           194:       NGX_HTTP_LOC_CONF_OFFSET,
        !           195:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.read_timeout),
        !           196:       NULL },
        !           197: 
        !           198:     { ngx_string("uwsgi_buffers"),
        !           199:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
        !           200:       ngx_conf_set_bufs_slot,
        !           201:       NGX_HTTP_LOC_CONF_OFFSET,
        !           202:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.bufs),
        !           203:       NULL },
        !           204: 
        !           205:     { ngx_string("uwsgi_busy_buffers_size"),
        !           206:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           207:       ngx_conf_set_size_slot,
        !           208:       NGX_HTTP_LOC_CONF_OFFSET,
        !           209:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf),
        !           210:       NULL },
        !           211: 
        !           212: #if (NGX_HTTP_CACHE)
        !           213: 
        !           214:     { ngx_string("uwsgi_cache"),
        !           215:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           216:       ngx_http_uwsgi_cache,
        !           217:       NGX_HTTP_LOC_CONF_OFFSET,
        !           218:       0,
        !           219:       NULL },
        !           220: 
        !           221:     { ngx_string("uwsgi_cache_key"),
        !           222:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           223:       ngx_http_uwsgi_cache_key,
        !           224:       NGX_HTTP_LOC_CONF_OFFSET,
        !           225:       0,
        !           226:       NULL },
        !           227: 
        !           228:     { ngx_string("uwsgi_cache_path"),
        !           229:       NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
        !           230:       ngx_http_file_cache_set_slot,
        !           231:       0,
        !           232:       0,
        !           233:       &ngx_http_uwsgi_module },
        !           234: 
        !           235:     { ngx_string("uwsgi_cache_bypass"),
        !           236:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           237:       ngx_http_set_predicate_slot,
        !           238:       NGX_HTTP_LOC_CONF_OFFSET,
        !           239:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
        !           240:       NULL },
        !           241: 
        !           242:     { ngx_string("uwsgi_no_cache"),
        !           243:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           244:       ngx_http_set_predicate_slot,
        !           245:       NGX_HTTP_LOC_CONF_OFFSET,
        !           246:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
        !           247:       NULL },
        !           248: 
        !           249:     { ngx_string("uwsgi_cache_valid"),
        !           250:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           251:       ngx_http_file_cache_valid_set_slot,
        !           252:       NGX_HTTP_LOC_CONF_OFFSET,
        !           253:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_valid),
        !           254:       NULL },
        !           255: 
        !           256:     { ngx_string("uwsgi_cache_min_uses"),
        !           257:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           258:       ngx_conf_set_num_slot,
        !           259:       NGX_HTTP_LOC_CONF_OFFSET,
        !           260:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses),
        !           261:       NULL },
        !           262: 
        !           263:     { ngx_string("uwsgi_cache_use_stale"),
        !           264:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           265:       ngx_conf_set_bitmask_slot,
        !           266:       NGX_HTTP_LOC_CONF_OFFSET,
        !           267:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_use_stale),
        !           268:       &ngx_http_uwsgi_next_upstream_masks },
        !           269: 
        !           270:     { ngx_string("uwsgi_cache_methods"),
        !           271:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           272:       ngx_conf_set_bitmask_slot,
        !           273:       NGX_HTTP_LOC_CONF_OFFSET,
        !           274:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
        !           275:       &ngx_http_upstream_cache_method_mask },
        !           276: 
        !           277:     { ngx_string("uwsgi_cache_lock"),
        !           278:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !           279:       ngx_conf_set_flag_slot,
        !           280:       NGX_HTTP_LOC_CONF_OFFSET,
        !           281:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
        !           282:       NULL },
        !           283: 
        !           284:     { ngx_string("uwsgi_cache_lock_timeout"),
        !           285:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           286:       ngx_conf_set_msec_slot,
        !           287:       NGX_HTTP_LOC_CONF_OFFSET,
        !           288:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
        !           289:       NULL },
        !           290: 
        !           291: #endif
        !           292: 
        !           293:     { ngx_string("uwsgi_temp_path"),
        !           294:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
        !           295:       ngx_conf_set_path_slot,
        !           296:       NGX_HTTP_LOC_CONF_OFFSET,
        !           297:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_path),
        !           298:       NULL },
        !           299: 
        !           300:     { ngx_string("uwsgi_max_temp_file_size"),
        !           301:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           302:       ngx_conf_set_size_slot,
        !           303:       NGX_HTTP_LOC_CONF_OFFSET,
        !           304:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf),
        !           305:       NULL },
        !           306: 
        !           307:     { ngx_string("uwsgi_temp_file_write_size"),
        !           308:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           309:       ngx_conf_set_size_slot,
        !           310:       NGX_HTTP_LOC_CONF_OFFSET,
        !           311:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf),
        !           312:       NULL },
        !           313: 
        !           314:     { ngx_string("uwsgi_next_upstream"),
        !           315:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           316:       ngx_conf_set_bitmask_slot,
        !           317:       NGX_HTTP_LOC_CONF_OFFSET,
        !           318:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream),
        !           319:       &ngx_http_uwsgi_next_upstream_masks },
        !           320: 
        !           321:     { ngx_string("uwsgi_param"),
        !           322:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
        !           323:       ngx_http_upstream_param_set_slot,
        !           324:       NGX_HTTP_LOC_CONF_OFFSET,
        !           325:       offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
        !           326:       NULL },
        !           327: 
        !           328:     { ngx_string("uwsgi_string"),
        !           329:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           330:       ngx_conf_set_str_slot,
        !           331:       NGX_HTTP_LOC_CONF_OFFSET,
        !           332:       offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
        !           333:       NULL },
        !           334: 
        !           335:     { ngx_string("uwsgi_pass_header"),
        !           336:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           337:       ngx_conf_set_str_array_slot,
        !           338:       NGX_HTTP_LOC_CONF_OFFSET,
        !           339:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
        !           340:       NULL },
        !           341: 
        !           342:     { ngx_string("uwsgi_hide_header"),
        !           343:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           344:       ngx_conf_set_str_array_slot,
        !           345:       NGX_HTTP_LOC_CONF_OFFSET,
        !           346:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
        !           347:       NULL },
        !           348: 
        !           349:     { ngx_string("uwsgi_ignore_headers"),
        !           350:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           351:       ngx_conf_set_bitmask_slot,
        !           352:       NGX_HTTP_LOC_CONF_OFFSET,
        !           353:       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
        !           354:       &ngx_http_upstream_ignore_headers_masks },
        !           355: 
        !           356:       ngx_null_command
        !           357: };
        !           358: 
        !           359: 
        !           360: static ngx_http_module_t ngx_http_uwsgi_module_ctx = {
        !           361:     NULL,                                  /* preconfiguration */
        !           362:     NULL,                                  /* postconfiguration */
        !           363: 
        !           364:     NULL,                                  /* create main configuration */
        !           365:     NULL,                                  /* init main configuration */
        !           366: 
        !           367:     NULL,                                  /* create server configuration */
        !           368:     NULL,                                  /* merge server configuration */
        !           369: 
        !           370:     ngx_http_uwsgi_create_loc_conf,        /* create location configuration */
        !           371:     ngx_http_uwsgi_merge_loc_conf          /* merge location configuration */
        !           372: };
        !           373: 
        !           374: 
        !           375: ngx_module_t ngx_http_uwsgi_module = {
        !           376:     NGX_MODULE_V1,
        !           377:     &ngx_http_uwsgi_module_ctx,            /* module context */
        !           378:     ngx_http_uwsgi_commands,               /* module directives */
        !           379:     NGX_HTTP_MODULE,                       /* module type */
        !           380:     NULL,                                  /* init master */
        !           381:     NULL,                                  /* init module */
        !           382:     NULL,                                  /* init process */
        !           383:     NULL,                                  /* init thread */
        !           384:     NULL,                                  /* exit thread */
        !           385:     NULL,                                  /* exit process */
        !           386:     NULL,                                  /* exit master */
        !           387:     NGX_MODULE_V1_PADDING
        !           388: };
        !           389: 
        !           390: 
        !           391: static ngx_str_t ngx_http_uwsgi_hide_headers[] = {
        !           392:     ngx_string("X-Accel-Expires"),
        !           393:     ngx_string("X-Accel-Redirect"),
        !           394:     ngx_string("X-Accel-Limit-Rate"),
        !           395:     ngx_string("X-Accel-Buffering"),
        !           396:     ngx_string("X-Accel-Charset"),
        !           397:     ngx_null_string
        !           398: };
        !           399: 
        !           400: 
        !           401: #if (NGX_HTTP_CACHE)
        !           402: 
        !           403: static ngx_keyval_t  ngx_http_uwsgi_cache_headers[] = {
        !           404:     { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
        !           405:     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
        !           406:     { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
        !           407:     { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
        !           408:     { ngx_string("HTTP_RANGE"), ngx_string("") },
        !           409:     { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
        !           410:     { ngx_null_string, ngx_null_string }
        !           411: };
        !           412: 
        !           413: #endif
        !           414: 
        !           415: 
        !           416: static ngx_path_init_t ngx_http_uwsgi_temp_path = {
        !           417:     ngx_string(NGX_HTTP_UWSGI_TEMP_PATH), { 1, 2, 0 }
        !           418: };
        !           419: 
        !           420: 
        !           421: static ngx_int_t
        !           422: ngx_http_uwsgi_handler(ngx_http_request_t *r)
        !           423: {
        !           424:     ngx_int_t                   rc;
        !           425:     ngx_http_status_t          *status;
        !           426:     ngx_http_upstream_t        *u;
        !           427:     ngx_http_uwsgi_loc_conf_t  *uwcf;
        !           428: 
        !           429:     if (r->subrequest_in_memory) {
        !           430:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
        !           431:                       "ngx_http_uwsgi_module does not support "
        !           432:                       "subrequests in memory");
        !           433:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           434:     }
        !           435: 
        !           436:     if (ngx_http_upstream_create(r) != NGX_OK) {
        !           437:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           438:     }
        !           439: 
        !           440:     status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
        !           441:     if (status == NULL) {
        !           442:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           443:     }
        !           444: 
        !           445:     ngx_http_set_ctx(r, status, ngx_http_uwsgi_module);
        !           446: 
        !           447:     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
        !           448: 
        !           449:     if (uwcf->uwsgi_lengths) {
        !           450:         if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
        !           451:             return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           452:         }
        !           453:     }
        !           454: 
        !           455:     u = r->upstream;
        !           456: 
        !           457:     ngx_str_set(&u->schema, "uwsgi://");
        !           458:     u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
        !           459: 
        !           460:     u->conf = &uwcf->upstream;
        !           461: 
        !           462: #if (NGX_HTTP_CACHE)
        !           463:     u->create_key = ngx_http_uwsgi_create_key;
        !           464: #endif
        !           465:     u->create_request = ngx_http_uwsgi_create_request;
        !           466:     u->reinit_request = ngx_http_uwsgi_reinit_request;
        !           467:     u->process_header = ngx_http_uwsgi_process_status_line;
        !           468:     u->abort_request = ngx_http_uwsgi_abort_request;
        !           469:     u->finalize_request = ngx_http_uwsgi_finalize_request;
        !           470:     r->state = 0;
        !           471: 
        !           472:     u->buffering = uwcf->upstream.buffering;
        !           473: 
        !           474:     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
        !           475:     if (u->pipe == NULL) {
        !           476:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           477:     }
        !           478: 
        !           479:     u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
        !           480:     u->pipe->input_ctx = r;
        !           481: 
        !           482:     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
        !           483: 
        !           484:     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        !           485:         return rc;
        !           486:     }
        !           487: 
        !           488:     return NGX_DONE;
        !           489: }
        !           490: 
        !           491: 
        !           492: static ngx_int_t
        !           493: ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
        !           494: {
        !           495:     ngx_url_t             url;
        !           496:     ngx_http_upstream_t  *u;
        !           497: 
        !           498:     ngx_memzero(&url, sizeof(ngx_url_t));
        !           499: 
        !           500:     if (ngx_http_script_run(r, &url.url, uwcf->uwsgi_lengths->elts, 0,
        !           501:                             uwcf->uwsgi_values->elts)
        !           502:         == NULL)
        !           503:     {
        !           504:         return NGX_ERROR;
        !           505:     }
        !           506: 
        !           507:     url.no_resolve = 1;
        !           508: 
        !           509:     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
        !           510:         if (url.err) {
        !           511:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           512:                           "%s in upstream \"%V\"", url.err, &url.url);
        !           513:         }
        !           514: 
        !           515:         return NGX_ERROR;
        !           516:     }
        !           517: 
        !           518:     u = r->upstream;
        !           519: 
        !           520:     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
        !           521:     if (u->resolved == NULL) {
        !           522:         return NGX_ERROR;
        !           523:     }
        !           524: 
        !           525:     if (url.addrs && url.addrs[0].sockaddr) {
        !           526:         u->resolved->sockaddr = url.addrs[0].sockaddr;
        !           527:         u->resolved->socklen = url.addrs[0].socklen;
        !           528:         u->resolved->naddrs = 1;
        !           529:         u->resolved->host = url.addrs[0].name;
        !           530: 
        !           531:     } else {
        !           532:         u->resolved->host = url.host;
        !           533:         u->resolved->port = url.port;
        !           534:         u->resolved->no_port = url.no_port;
        !           535:     }
        !           536: 
        !           537:     return NGX_OK;
        !           538: }
        !           539: 
        !           540: 
        !           541: #if (NGX_HTTP_CACHE)
        !           542: 
        !           543: static ngx_int_t
        !           544: ngx_http_uwsgi_create_key(ngx_http_request_t *r)
        !           545: {
        !           546:     ngx_str_t                  *key;
        !           547:     ngx_http_uwsgi_loc_conf_t  *uwcf;
        !           548: 
        !           549:     key = ngx_array_push(&r->cache->keys);
        !           550:     if (key == NULL) {
        !           551:         return NGX_ERROR;
        !           552:     }
        !           553: 
        !           554:     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
        !           555: 
        !           556:     if (ngx_http_complex_value(r, &uwcf->cache_key, key) != NGX_OK) {
        !           557:         return NGX_ERROR;
        !           558:     }
        !           559: 
        !           560:     return NGX_OK;
        !           561: }
        !           562: 
        !           563: #endif
        !           564: 
        !           565: 
        !           566: static ngx_int_t
        !           567: ngx_http_uwsgi_create_request(ngx_http_request_t *r)
        !           568: {
        !           569:     u_char                        ch, *lowcase_key;
        !           570:     size_t                        key_len, val_len, len, allocated;
        !           571:     ngx_uint_t                    i, n, hash, skip_empty, header_params;
        !           572:     ngx_buf_t                    *b;
        !           573:     ngx_chain_t                  *cl, *body;
        !           574:     ngx_list_part_t              *part;
        !           575:     ngx_table_elt_t              *header, **ignored;
        !           576:     ngx_http_script_code_pt       code;
        !           577:     ngx_http_script_engine_t      e, le;
        !           578:     ngx_http_uwsgi_loc_conf_t    *uwcf;
        !           579:     ngx_http_script_len_code_pt   lcode;
        !           580: 
        !           581:     len = 0;
        !           582:     header_params = 0;
        !           583:     ignored = NULL;
        !           584: 
        !           585:     uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
        !           586: 
        !           587:     if (uwcf->params_len) {
        !           588:         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
        !           589: 
        !           590:         ngx_http_script_flush_no_cacheable_variables(r, uwcf->flushes);
        !           591:         le.flushed = 1;
        !           592: 
        !           593:         le.ip = uwcf->params_len->elts;
        !           594:         le.request = r;
        !           595: 
        !           596:         while (*(uintptr_t *) le.ip) {
        !           597: 
        !           598:             lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           599:             key_len = lcode(&le);
        !           600: 
        !           601:             lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           602:             skip_empty = lcode(&le);
        !           603: 
        !           604:             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) {
        !           605:                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           606:             }
        !           607:             le.ip += sizeof(uintptr_t);
        !           608: 
        !           609:             if (skip_empty && val_len == 0) {
        !           610:                 continue;
        !           611:             }
        !           612: 
        !           613:             len += 2 + key_len + 2 + val_len;
        !           614:         }
        !           615:     }
        !           616: 
        !           617:     if (uwcf->upstream.pass_request_headers) {
        !           618: 
        !           619:         allocated = 0;
        !           620:         lowcase_key = NULL;
        !           621: 
        !           622:         if (uwcf->header_params) {
        !           623:             n = 0;
        !           624:             part = &r->headers_in.headers.part;
        !           625: 
        !           626:             while (part) {
        !           627:                 n += part->nelts;
        !           628:                 part = part->next;
        !           629:             }
        !           630: 
        !           631:             ignored = ngx_palloc(r->pool, n * sizeof(void *));
        !           632:             if (ignored == NULL) {
        !           633:                 return NGX_ERROR;
        !           634:             }
        !           635:         }
        !           636: 
        !           637:         part = &r->headers_in.headers.part;
        !           638:         header = part->elts;
        !           639: 
        !           640:         for (i = 0; /* void */ ; i++) {
        !           641: 
        !           642:             if (i >= part->nelts) {
        !           643:                 if (part->next == NULL) {
        !           644:                     break;
        !           645:                 }
        !           646: 
        !           647:                 part = part->next;
        !           648:                 header = part->elts;
        !           649:                 i = 0;
        !           650:             }
        !           651: 
        !           652:             if (uwcf->header_params) {
        !           653:                 if (allocated < header[i].key.len) {
        !           654:                     allocated = header[i].key.len + 16;
        !           655:                     lowcase_key = ngx_pnalloc(r->pool, allocated);
        !           656:                     if (lowcase_key == NULL) {
        !           657:                         return NGX_ERROR;
        !           658:                     }
        !           659:                 }
        !           660: 
        !           661:                 hash = 0;
        !           662: 
        !           663:                 for (n = 0; n < header[i].key.len; n++) {
        !           664:                     ch = header[i].key.data[n];
        !           665: 
        !           666:                     if (ch >= 'A' && ch <= 'Z') {
        !           667:                         ch |= 0x20;
        !           668: 
        !           669:                     } else if (ch == '-') {
        !           670:                         ch = '_';
        !           671:                     }
        !           672: 
        !           673:                     hash = ngx_hash(hash, ch);
        !           674:                     lowcase_key[n] = ch;
        !           675:                 }
        !           676: 
        !           677:                 if (ngx_hash_find(&uwcf->headers_hash, hash, lowcase_key, n)) {
        !           678:                     ignored[header_params++] = &header[i];
        !           679:                     continue;
        !           680:                 }
        !           681:             }
        !           682: 
        !           683:             len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
        !           684:                  + 2 + header[i].value.len;
        !           685:         }
        !           686:     }
        !           687: 
        !           688:     len += uwcf->uwsgi_string.len;
        !           689: 
        !           690: #if 0
        !           691:     /* allow custom uwsgi packet */
        !           692:     if (len > 0 && len < 2) {
        !           693:         ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0,
        !           694:                        "uwsgi request is too little: %uz", len);
        !           695:         return NGX_ERROR;
        !           696:     }
        !           697: #endif
        !           698: 
        !           699:     b = ngx_create_temp_buf(r->pool, len + 4);
        !           700:     if (b == NULL) {
        !           701:         return NGX_ERROR;
        !           702:     }
        !           703: 
        !           704:     cl = ngx_alloc_chain_link(r->pool);
        !           705:     if (cl == NULL) {
        !           706:         return NGX_ERROR;
        !           707:     }
        !           708: 
        !           709:     cl->buf = b;
        !           710: 
        !           711:     *b->last++ = (u_char) uwcf->modifier1;
        !           712:     *b->last++ = (u_char) (len & 0xff);
        !           713:     *b->last++ = (u_char) ((len >> 8) & 0xff);
        !           714:     *b->last++ = (u_char) uwcf->modifier2;
        !           715: 
        !           716:     if (uwcf->params_len) {
        !           717:         ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
        !           718: 
        !           719:         e.ip = uwcf->params->elts;
        !           720:         e.pos = b->last;
        !           721:         e.request = r;
        !           722:         e.flushed = 1;
        !           723: 
        !           724:         le.ip = uwcf->params_len->elts;
        !           725: 
        !           726:         while (*(uintptr_t *) le.ip) {
        !           727: 
        !           728:             lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           729:             key_len = (u_char) lcode (&le);
        !           730: 
        !           731:             lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           732:             skip_empty = lcode(&le);
        !           733: 
        !           734:             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
        !           735:                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
        !           736:             }
        !           737:             le.ip += sizeof(uintptr_t);
        !           738: 
        !           739:             if (skip_empty && val_len == 0) {
        !           740:                 e.skip = 1;
        !           741: 
        !           742:                 while (*(uintptr_t *) e.ip) {
        !           743:                     code = *(ngx_http_script_code_pt *) e.ip;
        !           744:                     code((ngx_http_script_engine_t *) &e);
        !           745:                 }
        !           746:                 e.ip += sizeof(uintptr_t);
        !           747: 
        !           748:                 e.skip = 0;
        !           749: 
        !           750:                 continue;
        !           751:             }
        !           752: 
        !           753:             *e.pos++ = (u_char) (key_len & 0xff);
        !           754:             *e.pos++ = (u_char) ((key_len >> 8) & 0xff);
        !           755: 
        !           756:             code = *(ngx_http_script_code_pt *) e.ip;
        !           757:             code((ngx_http_script_engine_t *) & e);
        !           758: 
        !           759:             *e.pos++ = (u_char) (val_len & 0xff);
        !           760:             *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
        !           761: 
        !           762:             while (*(uintptr_t *) e.ip) {
        !           763:                 code = *(ngx_http_script_code_pt *) e.ip;
        !           764:                 code((ngx_http_script_engine_t *) & e);
        !           765:             }
        !           766: 
        !           767:             e.ip += sizeof(uintptr_t);
        !           768: 
        !           769:             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           770:                            "uwsgi param: \"%*s: %*s\"",
        !           771:                            key_len, e.pos - (key_len + 2 + val_len),
        !           772:                            val_len, e.pos - val_len);
        !           773:         }
        !           774: 
        !           775:         b->last = e.pos;
        !           776:     }
        !           777: 
        !           778:     if (uwcf->upstream.pass_request_headers) {
        !           779: 
        !           780:         part = &r->headers_in.headers.part;
        !           781:         header = part->elts;
        !           782: 
        !           783:         for (i = 0; /* void */ ; i++) {
        !           784: 
        !           785:             if (i >= part->nelts) {
        !           786:                 if (part->next == NULL) {
        !           787:                     break;
        !           788:                 }
        !           789: 
        !           790:                 part = part->next;
        !           791:                 header = part->elts;
        !           792:                 i = 0;
        !           793:             }
        !           794: 
        !           795:             for (n = 0; n < header_params; n++) {
        !           796:                 if (&header[i] == ignored[n]) {
        !           797:                     goto next;
        !           798:                 }
        !           799:             }
        !           800: 
        !           801:             key_len = sizeof("HTTP_") - 1 + header[i].key.len;
        !           802:             *b->last++ = (u_char) (key_len & 0xff);
        !           803:             *b->last++ = (u_char) ((key_len >> 8) & 0xff);
        !           804: 
        !           805:             b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
        !           806:             for (n = 0; n < header[i].key.len; n++) {
        !           807:                 ch = header[i].key.data[n];
        !           808: 
        !           809:                 if (ch >= 'a' && ch <= 'z') {
        !           810:                     ch &= ~0x20;
        !           811: 
        !           812:                 } else if (ch == '-') {
        !           813:                     ch = '_';
        !           814:                 }
        !           815: 
        !           816:                 *b->last++ = ch;
        !           817:             }
        !           818: 
        !           819:             val_len = header[i].value.len;
        !           820:             *b->last++ = (u_char) (val_len & 0xff);
        !           821:             *b->last++ = (u_char) ((val_len >> 8) & 0xff);
        !           822:             b->last = ngx_copy(b->last, header[i].value.data, val_len);
        !           823: 
        !           824:             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           825:                            "uwsgi param: \"%*s: %*s\"",
        !           826:                            key_len, b->last - (key_len + 2 + val_len),
        !           827:                            val_len, b->last - val_len);
        !           828:         next:
        !           829: 
        !           830:             continue;
        !           831:         }
        !           832:     }
        !           833: 
        !           834:     b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
        !           835:                        uwcf->uwsgi_string.len);
        !           836: 
        !           837:     if (uwcf->upstream.pass_request_body) {
        !           838:         body = r->upstream->request_bufs;
        !           839:         r->upstream->request_bufs = cl;
        !           840: 
        !           841:         while (body) {
        !           842:             b = ngx_alloc_buf(r->pool);
        !           843:             if (b == NULL) {
        !           844:                 return NGX_ERROR;
        !           845:             }
        !           846: 
        !           847:             ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
        !           848: 
        !           849:             cl->next = ngx_alloc_chain_link(r->pool);
        !           850:             if (cl->next == NULL) {
        !           851:                 return NGX_ERROR;
        !           852:             }
        !           853: 
        !           854:             cl = cl->next;
        !           855:             cl->buf = b;
        !           856: 
        !           857:             body = body->next;
        !           858:         }
        !           859: 
        !           860:     } else {
        !           861:         r->upstream->request_bufs = cl;
        !           862:     }
        !           863: 
        !           864:     cl->next = NULL;
        !           865: 
        !           866:     return NGX_OK;
        !           867: }
        !           868: 
        !           869: 
        !           870: static ngx_int_t
        !           871: ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
        !           872: {
        !           873:     ngx_http_status_t  *status;
        !           874: 
        !           875:     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
        !           876: 
        !           877:     if (status == NULL) {
        !           878:         return NGX_OK;
        !           879:     }
        !           880: 
        !           881:     status->code = 0;
        !           882:     status->count = 0;
        !           883:     status->start = NULL;
        !           884:     status->end = NULL;
        !           885: 
        !           886:     r->upstream->process_header = ngx_http_uwsgi_process_status_line;
        !           887:     r->state = 0;
        !           888: 
        !           889:     return NGX_OK;
        !           890: }
        !           891: 
        !           892: 
        !           893: static ngx_int_t
        !           894: ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
        !           895: {
        !           896:     size_t                 len;
        !           897:     ngx_int_t              rc;
        !           898:     ngx_http_status_t     *status;
        !           899:     ngx_http_upstream_t   *u;
        !           900: 
        !           901:     status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
        !           902: 
        !           903:     if (status == NULL) {
        !           904:         return NGX_ERROR;
        !           905:     }
        !           906: 
        !           907:     u = r->upstream;
        !           908: 
        !           909:     rc = ngx_http_parse_status_line(r, &u->buffer, status);
        !           910: 
        !           911:     if (rc == NGX_AGAIN) {
        !           912:         return rc;
        !           913:     }
        !           914: 
        !           915:     if (rc == NGX_ERROR) {
        !           916:         u->process_header = ngx_http_uwsgi_process_header;
        !           917:         return ngx_http_uwsgi_process_header(r);
        !           918:     }
        !           919: 
        !           920:     if (u->state) {
        !           921:         u->state->status = status->code;
        !           922:     }
        !           923: 
        !           924:     u->headers_in.status_n = status->code;
        !           925: 
        !           926:     len = status->end - status->start;
        !           927:     u->headers_in.status_line.len = len;
        !           928: 
        !           929:     u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
        !           930:     if (u->headers_in.status_line.data == NULL) {
        !           931:         return NGX_ERROR;
        !           932:     }
        !           933: 
        !           934:     ngx_memcpy(u->headers_in.status_line.data, status->start, len);
        !           935: 
        !           936:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           937:                    "http uwsgi status %ui \"%V\"",
        !           938:                    u->headers_in.status_n, &u->headers_in.status_line);
        !           939: 
        !           940:     u->process_header = ngx_http_uwsgi_process_header;
        !           941: 
        !           942:     return ngx_http_uwsgi_process_header(r);
        !           943: }
        !           944: 
        !           945: 
        !           946: static ngx_int_t
        !           947: ngx_http_uwsgi_process_header(ngx_http_request_t *r)
        !           948: {
        !           949:     ngx_str_t                      *status_line;
        !           950:     ngx_int_t                       rc, status;
        !           951:     ngx_table_elt_t                *h;
        !           952:     ngx_http_upstream_t            *u;
        !           953:     ngx_http_upstream_header_t     *hh;
        !           954:     ngx_http_upstream_main_conf_t  *umcf;
        !           955: 
        !           956:     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
        !           957: 
        !           958:     for ( ;; ) {
        !           959: 
        !           960:         rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
        !           961: 
        !           962:         if (rc == NGX_OK) {
        !           963: 
        !           964:             /* a header line has been parsed successfully */
        !           965: 
        !           966:             h = ngx_list_push(&r->upstream->headers_in.headers);
        !           967:             if (h == NULL) {
        !           968:                 return NGX_ERROR;
        !           969:             }
        !           970: 
        !           971:             h->hash = r->header_hash;
        !           972: 
        !           973:             h->key.len = r->header_name_end - r->header_name_start;
        !           974:             h->value.len = r->header_end - r->header_start;
        !           975: 
        !           976:             h->key.data = ngx_pnalloc(r->pool,
        !           977:                                       h->key.len + 1 + h->value.len + 1
        !           978:                                       + h->key.len);
        !           979:             if (h->key.data == NULL) {
        !           980:                 return NGX_ERROR;
        !           981:             }
        !           982: 
        !           983:             h->value.data = h->key.data + h->key.len + 1;
        !           984:             h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
        !           985: 
        !           986:             ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
        !           987:             h->key.data[h->key.len] = '\0';
        !           988:             ngx_memcpy(h->value.data, r->header_start, h->value.len);
        !           989:             h->value.data[h->value.len] = '\0';
        !           990: 
        !           991:             if (h->key.len == r->lowcase_index) {
        !           992:                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
        !           993: 
        !           994:             } else {
        !           995:                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
        !           996:             }
        !           997: 
        !           998:             hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
        !           999:                                h->lowcase_key, h->key.len);
        !          1000: 
        !          1001:             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
        !          1002:                 return NGX_ERROR;
        !          1003:             }
        !          1004: 
        !          1005:             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1006:                            "http uwsgi header: \"%V: %V\"", &h->key, &h->value);
        !          1007: 
        !          1008:             continue;
        !          1009:         }
        !          1010: 
        !          1011:         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
        !          1012: 
        !          1013:             /* a whole header has been parsed successfully */
        !          1014: 
        !          1015:             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1016:                            "http uwsgi header done");
        !          1017: 
        !          1018:             u = r->upstream;
        !          1019: 
        !          1020:             if (u->headers_in.status_n) {
        !          1021:                 goto done;
        !          1022:             }
        !          1023: 
        !          1024:             if (u->headers_in.status) {
        !          1025:                 status_line = &u->headers_in.status->value;
        !          1026: 
        !          1027:                 status = ngx_atoi(status_line->data, 3);
        !          1028:                 if (status == NGX_ERROR) {
        !          1029:                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !          1030:                                   "upstream sent invalid status \"%V\"",
        !          1031:                                   status_line);
        !          1032:                     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
        !          1033:                 }
        !          1034: 
        !          1035:                 u->headers_in.status_n = status;
        !          1036:                 u->headers_in.status_line = *status_line;
        !          1037: 
        !          1038:             } else if (u->headers_in.location) {
        !          1039:                 u->headers_in.status_n = 302;
        !          1040:                 ngx_str_set(&u->headers_in.status_line,
        !          1041:                             "302 Moved Temporarily");
        !          1042: 
        !          1043:             } else {
        !          1044:                 u->headers_in.status_n = 200;
        !          1045:                 ngx_str_set(&u->headers_in.status_line, "200 OK");
        !          1046:             }
        !          1047: 
        !          1048:             if (u->state) {
        !          1049:                 u->state->status = u->headers_in.status_n;
        !          1050:             }
        !          1051: 
        !          1052:         done:
        !          1053: 
        !          1054:             if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
        !          1055:                 && r->headers_in.upgrade)
        !          1056:             {
        !          1057:                 u->upgrade = 1;
        !          1058:             }
        !          1059: 
        !          1060:             return NGX_OK;
        !          1061:         }
        !          1062: 
        !          1063:         if (rc == NGX_AGAIN) {
        !          1064:             return NGX_AGAIN;
        !          1065:         }
        !          1066: 
        !          1067:         /* there was error while a header line parsing */
        !          1068: 
        !          1069:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !          1070:                       "upstream sent invalid header");
        !          1071: 
        !          1072:         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
        !          1073:     }
        !          1074: }
        !          1075: 
        !          1076: 
        !          1077: static void
        !          1078: ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
        !          1079: {
        !          1080:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1081:                    "abort http uwsgi request");
        !          1082: 
        !          1083:     return;
        !          1084: }
        !          1085: 
        !          1086: 
        !          1087: static void
        !          1088: ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
        !          1089: {
        !          1090:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !          1091:                    "finalize http uwsgi request");
        !          1092: 
        !          1093:     return;
        !          1094: }
        !          1095: 
        !          1096: 
        !          1097: static void *
        !          1098: ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
        !          1099: {
        !          1100:     ngx_http_uwsgi_loc_conf_t  *conf;
        !          1101: 
        !          1102:     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_loc_conf_t));
        !          1103:     if (conf == NULL) {
        !          1104:         return NULL;
        !          1105:     }
        !          1106: 
        !          1107:     conf->modifier1 = NGX_CONF_UNSET_UINT;
        !          1108:     conf->modifier2 = NGX_CONF_UNSET_UINT;
        !          1109: 
        !          1110:     conf->upstream.store = NGX_CONF_UNSET;
        !          1111:     conf->upstream.store_access = NGX_CONF_UNSET_UINT;
        !          1112:     conf->upstream.buffering = NGX_CONF_UNSET;
        !          1113:     conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
        !          1114: 
        !          1115:     conf->upstream.local = NGX_CONF_UNSET_PTR;
        !          1116: 
        !          1117:     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
        !          1118:     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
        !          1119:     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
        !          1120: 
        !          1121:     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
        !          1122:     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
        !          1123: 
        !          1124:     conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
        !          1125:     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
        !          1126:     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
        !          1127: 
        !          1128:     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
        !          1129:     conf->upstream.pass_request_body = NGX_CONF_UNSET;
        !          1130: 
        !          1131: #if (NGX_HTTP_CACHE)
        !          1132:     conf->upstream.cache = NGX_CONF_UNSET_PTR;
        !          1133:     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
        !          1134:     conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
        !          1135:     conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
        !          1136:     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
        !          1137:     conf->upstream.cache_lock = NGX_CONF_UNSET;
        !          1138:     conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
        !          1139: #endif
        !          1140: 
        !          1141:     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
        !          1142:     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
        !          1143: 
        !          1144:     conf->upstream.intercept_errors = NGX_CONF_UNSET;
        !          1145: 
        !          1146:     /* "uwsgi_cyclic_temp_file" is disabled */
        !          1147:     conf->upstream.cyclic_temp_file = 0;
        !          1148: 
        !          1149:     conf->upstream.change_buffering = 1;
        !          1150: 
        !          1151:     ngx_str_set(&conf->upstream.module, "uwsgi");
        !          1152: 
        !          1153:     return conf;
        !          1154: }
        !          1155: 
        !          1156: 
        !          1157: static char *
        !          1158: ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
        !          1159: {
        !          1160:     ngx_http_uwsgi_loc_conf_t *prev = parent;
        !          1161:     ngx_http_uwsgi_loc_conf_t *conf = child;
        !          1162: 
        !          1163:     size_t                        size;
        !          1164:     ngx_hash_init_t               hash;
        !          1165:     ngx_http_core_loc_conf_t     *clcf;
        !          1166: 
        !          1167:     if (conf->upstream.store != 0) {
        !          1168:         ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);
        !          1169: 
        !          1170:         if (conf->upstream.store_lengths == NULL) {
        !          1171:             conf->upstream.store_lengths = prev->upstream.store_lengths;
        !          1172:             conf->upstream.store_values = prev->upstream.store_values;
        !          1173:         }
        !          1174:     }
        !          1175: 
        !          1176:     ngx_conf_merge_uint_value(conf->upstream.store_access,
        !          1177:                               prev->upstream.store_access, 0600);
        !          1178: 
        !          1179:     ngx_conf_merge_value(conf->upstream.buffering,
        !          1180:                               prev->upstream.buffering, 1);
        !          1181: 
        !          1182:     ngx_conf_merge_value(conf->upstream.ignore_client_abort,
        !          1183:                               prev->upstream.ignore_client_abort, 0);
        !          1184: 
        !          1185:     ngx_conf_merge_ptr_value(conf->upstream.local,
        !          1186:                               prev->upstream.local, NULL);
        !          1187: 
        !          1188:     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
        !          1189:                               prev->upstream.connect_timeout, 60000);
        !          1190: 
        !          1191:     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
        !          1192:                               prev->upstream.send_timeout, 60000);
        !          1193: 
        !          1194:     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
        !          1195:                               prev->upstream.read_timeout, 60000);
        !          1196: 
        !          1197:     ngx_conf_merge_size_value(conf->upstream.send_lowat,
        !          1198:                               prev->upstream.send_lowat, 0);
        !          1199: 
        !          1200:     ngx_conf_merge_size_value(conf->upstream.buffer_size,
        !          1201:                               prev->upstream.buffer_size,
        !          1202:                               (size_t) ngx_pagesize);
        !          1203: 
        !          1204: 
        !          1205:     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
        !          1206:                               8, ngx_pagesize);
        !          1207: 
        !          1208:     if (conf->upstream.bufs.num < 2) {
        !          1209:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1210:                            "there must be at least 2 \"uwsgi_buffers\"");
        !          1211:         return NGX_CONF_ERROR;
        !          1212:     }
        !          1213: 
        !          1214: 
        !          1215:     size = conf->upstream.buffer_size;
        !          1216:     if (size < conf->upstream.bufs.size) {
        !          1217:         size = conf->upstream.bufs.size;
        !          1218:     }
        !          1219: 
        !          1220: 
        !          1221:     ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
        !          1222:                               prev->upstream.busy_buffers_size_conf,
        !          1223:                               NGX_CONF_UNSET_SIZE);
        !          1224: 
        !          1225:     if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
        !          1226:         conf->upstream.busy_buffers_size = 2 * size;
        !          1227:     } else {
        !          1228:         conf->upstream.busy_buffers_size =
        !          1229:             conf->upstream.busy_buffers_size_conf;
        !          1230:     }
        !          1231: 
        !          1232:     if (conf->upstream.busy_buffers_size < size) {
        !          1233:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1234:             "\"uwsgi_busy_buffers_size\" must be equal to or greater "
        !          1235:             "than the maximum of the value of \"uwsgi_buffer_size\" and "
        !          1236:             "one of the \"uwsgi_buffers\"");
        !          1237: 
        !          1238:         return NGX_CONF_ERROR;
        !          1239:     }
        !          1240: 
        !          1241:     if (conf->upstream.busy_buffers_size
        !          1242:         > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
        !          1243:     {
        !          1244:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1245:             "\"uwsgi_busy_buffers_size\" must be less than "
        !          1246:             "the size of all \"uwsgi_buffers\" minus one buffer");
        !          1247: 
        !          1248:         return NGX_CONF_ERROR;
        !          1249:     }
        !          1250: 
        !          1251: 
        !          1252:     ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
        !          1253:                               prev->upstream.temp_file_write_size_conf,
        !          1254:                               NGX_CONF_UNSET_SIZE);
        !          1255: 
        !          1256:     if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
        !          1257:         conf->upstream.temp_file_write_size = 2 * size;
        !          1258:     } else {
        !          1259:         conf->upstream.temp_file_write_size =
        !          1260:             conf->upstream.temp_file_write_size_conf;
        !          1261:     }
        !          1262: 
        !          1263:     if (conf->upstream.temp_file_write_size < size) {
        !          1264:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1265:             "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
        !          1266:             "the maximum of the value of \"uwsgi_buffer_size\" and "
        !          1267:             "one of the \"uwsgi_buffers\"");
        !          1268: 
        !          1269:         return NGX_CONF_ERROR;
        !          1270:     }
        !          1271: 
        !          1272: 
        !          1273:     ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
        !          1274:                               prev->upstream.max_temp_file_size_conf,
        !          1275:                               NGX_CONF_UNSET_SIZE);
        !          1276: 
        !          1277:     if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
        !          1278:         conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
        !          1279:     } else {
        !          1280:         conf->upstream.max_temp_file_size =
        !          1281:             conf->upstream.max_temp_file_size_conf;
        !          1282:     }
        !          1283: 
        !          1284:     if (conf->upstream.max_temp_file_size != 0
        !          1285:         && conf->upstream.max_temp_file_size < size) {
        !          1286:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1287:             "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
        !          1288:             "temporary files usage or must be equal to or greater than "
        !          1289:             "the maximum of the value of \"uwsgi_buffer_size\" and "
        !          1290:             "one of the \"uwsgi_buffers\"");
        !          1291: 
        !          1292:         return NGX_CONF_ERROR;
        !          1293:     }
        !          1294: 
        !          1295: 
        !          1296:     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
        !          1297:                                  prev->upstream.ignore_headers,
        !          1298:                                  NGX_CONF_BITMASK_SET);
        !          1299: 
        !          1300: 
        !          1301:     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
        !          1302:                                  prev->upstream.next_upstream,
        !          1303:                                  (NGX_CONF_BITMASK_SET
        !          1304:                                   |NGX_HTTP_UPSTREAM_FT_ERROR
        !          1305:                                   |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
        !          1306: 
        !          1307:     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        !          1308:         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
        !          1309:                                        |NGX_HTTP_UPSTREAM_FT_OFF;
        !          1310:     }
        !          1311: 
        !          1312:     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
        !          1313:                                   prev->upstream.temp_path,
        !          1314:                                   &ngx_http_uwsgi_temp_path)
        !          1315:         != NGX_OK)
        !          1316:     {
        !          1317:         return NGX_CONF_ERROR;
        !          1318:     }
        !          1319: 
        !          1320: #if (NGX_HTTP_CACHE)
        !          1321: 
        !          1322:     ngx_conf_merge_ptr_value(conf->upstream.cache,
        !          1323:                               prev->upstream.cache, NULL);
        !          1324: 
        !          1325:     if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
        !          1326:         ngx_shm_zone_t  *shm_zone;
        !          1327: 
        !          1328:         shm_zone = conf->upstream.cache;
        !          1329: 
        !          1330:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1331:                            "\"uwsgi_cache\" zone \"%V\" is unknown",
        !          1332:                            &shm_zone->shm.name);
        !          1333: 
        !          1334:         return NGX_CONF_ERROR;
        !          1335:     }
        !          1336: 
        !          1337:     ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
        !          1338:                               prev->upstream.cache_min_uses, 1);
        !          1339: 
        !          1340:     ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
        !          1341:                               prev->upstream.cache_use_stale,
        !          1342:                               (NGX_CONF_BITMASK_SET
        !          1343:                                |NGX_HTTP_UPSTREAM_FT_OFF));
        !          1344: 
        !          1345:     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
        !          1346:         conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
        !          1347:                                          |NGX_HTTP_UPSTREAM_FT_OFF;
        !          1348:     }
        !          1349: 
        !          1350:     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
        !          1351:         conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
        !          1352:     }
        !          1353: 
        !          1354:     if (conf->upstream.cache_methods == 0) {
        !          1355:         conf->upstream.cache_methods = prev->upstream.cache_methods;
        !          1356:     }
        !          1357: 
        !          1358:     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
        !          1359: 
        !          1360:     ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
        !          1361:                              prev->upstream.cache_bypass, NULL);
        !          1362: 
        !          1363:     ngx_conf_merge_ptr_value(conf->upstream.no_cache,
        !          1364:                              prev->upstream.no_cache, NULL);
        !          1365: 
        !          1366:     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
        !          1367:                              prev->upstream.cache_valid, NULL);
        !          1368: 
        !          1369:     if (conf->cache_key.value.data == NULL) {
        !          1370:         conf->cache_key = prev->cache_key;
        !          1371:     }
        !          1372: 
        !          1373:     ngx_conf_merge_value(conf->upstream.cache_lock,
        !          1374:                               prev->upstream.cache_lock, 0);
        !          1375: 
        !          1376:     ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
        !          1377:                               prev->upstream.cache_lock_timeout, 5000);
        !          1378: 
        !          1379: #endif
        !          1380: 
        !          1381:     ngx_conf_merge_value(conf->upstream.pass_request_headers,
        !          1382:                          prev->upstream.pass_request_headers, 1);
        !          1383:     ngx_conf_merge_value(conf->upstream.pass_request_body,
        !          1384:                          prev->upstream.pass_request_body, 1);
        !          1385: 
        !          1386:     ngx_conf_merge_value(conf->upstream.intercept_errors,
        !          1387:                          prev->upstream.intercept_errors, 0);
        !          1388: 
        !          1389:     ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
        !          1390: 
        !          1391:     hash.max_size = 512;
        !          1392:     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
        !          1393:     hash.name = "uwsgi_hide_headers_hash";
        !          1394: 
        !          1395:     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
        !          1396:             &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
        !          1397:         != NGX_OK)
        !          1398:     {
        !          1399:         return NGX_CONF_ERROR;
        !          1400:     }
        !          1401: 
        !          1402:     if (conf->upstream.upstream == NULL) {
        !          1403:         conf->upstream.upstream = prev->upstream.upstream;
        !          1404:     }
        !          1405: 
        !          1406:     if (conf->uwsgi_lengths == NULL) {
        !          1407:         conf->uwsgi_lengths = prev->uwsgi_lengths;
        !          1408:         conf->uwsgi_values = prev->uwsgi_values;
        !          1409:     }
        !          1410: 
        !          1411:     if (conf->upstream.upstream || conf->uwsgi_lengths) {
        !          1412:         clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
        !          1413:         if (clcf->handler == NULL && clcf->lmt_excpt) {
        !          1414:             clcf->handler = ngx_http_uwsgi_handler;
        !          1415:         }
        !          1416:     }
        !          1417: 
        !          1418:     ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
        !          1419:     ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);
        !          1420: 
        !          1421:     if (ngx_http_uwsgi_merge_params(cf, conf, prev) != NGX_OK) {
        !          1422:         return NGX_CONF_ERROR;
        !          1423:     }
        !          1424: 
        !          1425:     return NGX_CONF_OK;
        !          1426: }
        !          1427: 
        !          1428: 
        !          1429: static ngx_int_t
        !          1430: ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
        !          1431:     ngx_http_uwsgi_loc_conf_t *prev)
        !          1432: {
        !          1433:     u_char                       *p;
        !          1434:     size_t                        size;
        !          1435:     uintptr_t                    *code;
        !          1436:     ngx_uint_t                    i, nsrc;
        !          1437:     ngx_array_t                   headers_names;
        !          1438: #if (NGX_HTTP_CACHE)
        !          1439:     ngx_array_t                   params_merged;
        !          1440: #endif
        !          1441:     ngx_hash_key_t               *hk;
        !          1442:     ngx_hash_init_t               hash;
        !          1443:     ngx_http_upstream_param_t    *src;
        !          1444:     ngx_http_script_compile_t     sc;
        !          1445:     ngx_http_script_copy_code_t  *copy;
        !          1446: 
        !          1447:     if (conf->params_source == NULL) {
        !          1448:         conf->params_source = prev->params_source;
        !          1449: 
        !          1450:         if (prev->headers_hash.buckets
        !          1451: #if (NGX_HTTP_CACHE)
        !          1452:             && ((conf->upstream.cache == NULL)
        !          1453:                 == (prev->upstream.cache == NULL))
        !          1454: #endif
        !          1455:            )
        !          1456:         {
        !          1457:             conf->flushes = prev->flushes;
        !          1458:             conf->params_len = prev->params_len;
        !          1459:             conf->params = prev->params;
        !          1460:             conf->headers_hash = prev->headers_hash;
        !          1461:             conf->header_params = prev->header_params;
        !          1462: 
        !          1463:             return NGX_OK;
        !          1464:         }
        !          1465:     }
        !          1466: 
        !          1467:     if (conf->params_source == NULL
        !          1468: #if (NGX_HTTP_CACHE)
        !          1469:         && (conf->upstream.cache == NULL)
        !          1470: #endif
        !          1471:        )
        !          1472:     {
        !          1473:         conf->headers_hash.buckets = (void *) 1;
        !          1474:         return NGX_OK;
        !          1475:     }
        !          1476: 
        !          1477:     conf->params_len = ngx_array_create(cf->pool, 64, 1);
        !          1478:     if (conf->params_len == NULL) {
        !          1479:         return NGX_ERROR;
        !          1480:     }
        !          1481: 
        !          1482:     conf->params = ngx_array_create(cf->pool, 512, 1);
        !          1483:     if (conf->params == NULL) {
        !          1484:         return NGX_ERROR;
        !          1485:     }
        !          1486: 
        !          1487:     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
        !          1488:         != NGX_OK)
        !          1489:     {
        !          1490:         return NGX_ERROR;
        !          1491:     }
        !          1492: 
        !          1493:     if (conf->params_source) {
        !          1494:         src = conf->params_source->elts;
        !          1495:         nsrc = conf->params_source->nelts;
        !          1496: 
        !          1497:     } else {
        !          1498:         src = NULL;
        !          1499:         nsrc = 0;
        !          1500:     }
        !          1501: 
        !          1502: #if (NGX_HTTP_CACHE)
        !          1503: 
        !          1504:     if (conf->upstream.cache) {
        !          1505:         ngx_keyval_t               *h;
        !          1506:         ngx_http_upstream_param_t  *s;
        !          1507: 
        !          1508:         if (ngx_array_init(&params_merged, cf->temp_pool, 4,
        !          1509:                            sizeof(ngx_http_upstream_param_t))
        !          1510:             != NGX_OK)
        !          1511:         {
        !          1512:             return NGX_ERROR;
        !          1513:         }
        !          1514: 
        !          1515:         for (i = 0; i < nsrc; i++) {
        !          1516: 
        !          1517:             s = ngx_array_push(&params_merged);
        !          1518:             if (s == NULL) {
        !          1519:                 return NGX_ERROR;
        !          1520:             }
        !          1521: 
        !          1522:             *s = src[i];
        !          1523:         }
        !          1524: 
        !          1525:         h = ngx_http_uwsgi_cache_headers;
        !          1526: 
        !          1527:         while (h->key.len) {
        !          1528: 
        !          1529:             src = params_merged.elts;
        !          1530:             nsrc = params_merged.nelts;
        !          1531: 
        !          1532:             for (i = 0; i < nsrc; i++) {
        !          1533:                 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
        !          1534:                     goto next;
        !          1535:                 }
        !          1536:             }
        !          1537: 
        !          1538:             s = ngx_array_push(&params_merged);
        !          1539:             if (s == NULL) {
        !          1540:                 return NGX_ERROR;
        !          1541:             }
        !          1542: 
        !          1543:             s->key = h->key;
        !          1544:             s->value = h->value;
        !          1545:             s->skip_empty = 0;
        !          1546: 
        !          1547:         next:
        !          1548: 
        !          1549:             h++;
        !          1550:         }
        !          1551: 
        !          1552:         src = params_merged.elts;
        !          1553:         nsrc = params_merged.nelts;
        !          1554:     }
        !          1555: 
        !          1556: #endif
        !          1557: 
        !          1558:     for (i = 0; i < nsrc; i++) {
        !          1559: 
        !          1560:         if (src[i].key.len > sizeof("HTTP_") - 1
        !          1561:             && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
        !          1562:         {
        !          1563:             hk = ngx_array_push(&headers_names);
        !          1564:             if (hk == NULL) {
        !          1565:                 return NGX_ERROR;
        !          1566:             }
        !          1567: 
        !          1568:             hk->key.len = src[i].key.len - 5;
        !          1569:             hk->key.data = src[i].key.data + 5;
        !          1570:             hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
        !          1571:             hk->value = (void *) 1;
        !          1572: 
        !          1573:             if (src[i].value.len == 0) {
        !          1574:                 continue;
        !          1575:             }
        !          1576:         }
        !          1577: 
        !          1578:         copy = ngx_array_push_n(conf->params_len,
        !          1579:                                 sizeof(ngx_http_script_copy_code_t));
        !          1580:         if (copy == NULL) {
        !          1581:             return NGX_ERROR;
        !          1582:         }
        !          1583: 
        !          1584:         copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
        !          1585:         copy->len = src[i].key.len;
        !          1586: 
        !          1587:         copy = ngx_array_push_n(conf->params_len,
        !          1588:                                 sizeof(ngx_http_script_copy_code_t));
        !          1589:         if (copy == NULL) {
        !          1590:             return NGX_ERROR;
        !          1591:         }
        !          1592: 
        !          1593:         copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
        !          1594:         copy->len = src[i].skip_empty;
        !          1595: 
        !          1596: 
        !          1597:         size = (sizeof(ngx_http_script_copy_code_t)
        !          1598:                 + src[i].key.len + sizeof(uintptr_t) - 1)
        !          1599:                & ~(sizeof(uintptr_t) - 1);
        !          1600: 
        !          1601:         copy = ngx_array_push_n(conf->params, size);
        !          1602:         if (copy == NULL) {
        !          1603:             return NGX_ERROR;
        !          1604:         }
        !          1605: 
        !          1606:         copy->code = ngx_http_script_copy_code;
        !          1607:         copy->len = src[i].key.len;
        !          1608: 
        !          1609:         p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
        !          1610:         ngx_memcpy(p, src[i].key.data, src[i].key.len);
        !          1611: 
        !          1612: 
        !          1613:         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
        !          1614: 
        !          1615:         sc.cf = cf;
        !          1616:         sc.source = &src[i].value;
        !          1617:         sc.flushes = &conf->flushes;
        !          1618:         sc.lengths = &conf->params_len;
        !          1619:         sc.values = &conf->params;
        !          1620: 
        !          1621:         if (ngx_http_script_compile(&sc) != NGX_OK) {
        !          1622:             return NGX_ERROR;
        !          1623:         }
        !          1624: 
        !          1625:         code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
        !          1626:         if (code == NULL) {
        !          1627:             return NGX_ERROR;
        !          1628:         }
        !          1629: 
        !          1630:         *code = (uintptr_t) NULL;
        !          1631: 
        !          1632: 
        !          1633:         code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
        !          1634:         if (code == NULL) {
        !          1635:             return NGX_ERROR;
        !          1636:         }
        !          1637: 
        !          1638:         *code = (uintptr_t) NULL;
        !          1639:     }
        !          1640: 
        !          1641:     code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
        !          1642:     if (code == NULL) {
        !          1643:         return NGX_ERROR;
        !          1644:     }
        !          1645: 
        !          1646:     *code = (uintptr_t) NULL;
        !          1647: 
        !          1648:     conf->header_params = headers_names.nelts;
        !          1649: 
        !          1650:     hash.hash = &conf->headers_hash;
        !          1651:     hash.key = ngx_hash_key_lc;
        !          1652:     hash.max_size = 512;
        !          1653:     hash.bucket_size = 64;
        !          1654:     hash.name = "uwsgi_params_hash";
        !          1655:     hash.pool = cf->pool;
        !          1656:     hash.temp_pool = NULL;
        !          1657: 
        !          1658:     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
        !          1659: }
        !          1660: 
        !          1661: 
        !          1662: static char *
        !          1663: ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          1664: {
        !          1665:     ngx_http_uwsgi_loc_conf_t *uwcf = conf;
        !          1666: 
        !          1667:     ngx_url_t                   u;
        !          1668:     ngx_str_t                  *value, *url;
        !          1669:     ngx_uint_t                  n;
        !          1670:     ngx_http_core_loc_conf_t   *clcf;
        !          1671:     ngx_http_script_compile_t   sc;
        !          1672: 
        !          1673:     if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) {
        !          1674:         return "is duplicate";
        !          1675:     }
        !          1676: 
        !          1677:     clcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module);
        !          1678:     clcf->handler = ngx_http_uwsgi_handler;
        !          1679: 
        !          1680:     value = cf->args->elts;
        !          1681: 
        !          1682:     url = &value[1];
        !          1683: 
        !          1684:     n = ngx_http_script_variables_count(url);
        !          1685: 
        !          1686:     if (n) {
        !          1687: 
        !          1688:         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
        !          1689: 
        !          1690:         sc.cf = cf;
        !          1691:         sc.source = url;
        !          1692:         sc.lengths = &uwcf->uwsgi_lengths;
        !          1693:         sc.values = &uwcf->uwsgi_values;
        !          1694:         sc.variables = n;
        !          1695:         sc.complete_lengths = 1;
        !          1696:         sc.complete_values = 1;
        !          1697: 
        !          1698:         if (ngx_http_script_compile(&sc) != NGX_OK) {
        !          1699:             return NGX_CONF_ERROR;
        !          1700:         }
        !          1701: 
        !          1702:         return NGX_CONF_OK;
        !          1703:     }
        !          1704: 
        !          1705:     ngx_memzero(&u, sizeof(ngx_url_t));
        !          1706: 
        !          1707:     u.url = value[1];
        !          1708:     u.no_resolve = 1;
        !          1709: 
        !          1710:     uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
        !          1711:     if (uwcf->upstream.upstream == NULL) {
        !          1712:         return NGX_CONF_ERROR;
        !          1713:     }
        !          1714: 
        !          1715:     if (clcf->name.data[clcf->name.len - 1] == '/') {
        !          1716:         clcf->auto_redirect = 1;
        !          1717:     }
        !          1718: 
        !          1719:     return NGX_CONF_OK;
        !          1720: }
        !          1721: 
        !          1722: 
        !          1723: static char *
        !          1724: ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          1725: {
        !          1726:     ngx_http_uwsgi_loc_conf_t *uwcf = conf;
        !          1727: 
        !          1728:     ngx_str_t                  *value;
        !          1729:     ngx_http_script_compile_t   sc;
        !          1730: 
        !          1731:     if (uwcf->upstream.store != NGX_CONF_UNSET || uwcf->upstream.store_lengths)
        !          1732:     {
        !          1733:         return "is duplicate";
        !          1734:     }
        !          1735: 
        !          1736:     value = cf->args->elts;
        !          1737: 
        !          1738:     if (ngx_strcmp(value[1].data, "off") == 0) {
        !          1739:         uwcf->upstream.store = 0;
        !          1740:         return NGX_CONF_OK;
        !          1741:     }
        !          1742: 
        !          1743: #if (NGX_HTTP_CACHE)
        !          1744: 
        !          1745:     if (uwcf->upstream.cache != NGX_CONF_UNSET_PTR
        !          1746:         && uwcf->upstream.cache != NULL)
        !          1747:     {
        !          1748:         return "is incompatible with \"uwsgi_cache\"";
        !          1749:     }
        !          1750: 
        !          1751: #endif
        !          1752: 
        !          1753:     if (ngx_strcmp(value[1].data, "on") == 0) {
        !          1754:         uwcf->upstream.store = 1;
        !          1755:         return NGX_CONF_OK;
        !          1756:     }
        !          1757: 
        !          1758:     /* include the terminating '\0' into script */
        !          1759:     value[1].len++;
        !          1760: 
        !          1761:     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
        !          1762: 
        !          1763:     sc.cf = cf;
        !          1764:     sc.source = &value[1];
        !          1765:     sc.lengths = &uwcf->upstream.store_lengths;
        !          1766:     sc.values = &uwcf->upstream.store_values;
        !          1767:     sc.variables = ngx_http_script_variables_count(&value[1]);;
        !          1768:     sc.complete_lengths = 1;
        !          1769:     sc.complete_values = 1;
        !          1770: 
        !          1771:     if (ngx_http_script_compile(&sc) != NGX_OK) {
        !          1772:         return NGX_CONF_ERROR;
        !          1773:     }
        !          1774: 
        !          1775:     return NGX_CONF_OK;
        !          1776: }
        !          1777: 
        !          1778: 
        !          1779: #if (NGX_HTTP_CACHE)
        !          1780: 
        !          1781: static char *
        !          1782: ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          1783: {
        !          1784:     ngx_http_uwsgi_loc_conf_t *uwcf = conf;
        !          1785: 
        !          1786:     ngx_str_t  *value;
        !          1787: 
        !          1788:     value = cf->args->elts;
        !          1789: 
        !          1790:     if (uwcf->upstream.cache != NGX_CONF_UNSET_PTR) {
        !          1791:         return "is duplicate";
        !          1792:     }
        !          1793: 
        !          1794:     if (ngx_strcmp(value[1].data, "off") == 0) {
        !          1795:         uwcf->upstream.cache = NULL;
        !          1796:         return NGX_CONF_OK;
        !          1797:     }
        !          1798: 
        !          1799:     if (uwcf->upstream.store > 0 || uwcf->upstream.store_lengths) {
        !          1800:         return "is incompatible with \"uwsgi_store\"";
        !          1801:     }
        !          1802: 
        !          1803:     uwcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
        !          1804:                                                  &ngx_http_uwsgi_module);
        !          1805:     if (uwcf->upstream.cache == NULL) {
        !          1806:         return NGX_CONF_ERROR;
        !          1807:     }
        !          1808: 
        !          1809:     return NGX_CONF_OK;
        !          1810: }
        !          1811: 
        !          1812: 
        !          1813: static char *
        !          1814: ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          1815: {
        !          1816:     ngx_http_uwsgi_loc_conf_t *uwcf = conf;
        !          1817: 
        !          1818:     ngx_str_t                         *value;
        !          1819:     ngx_http_compile_complex_value_t   ccv;
        !          1820: 
        !          1821:     value = cf->args->elts;
        !          1822: 
        !          1823:     if (uwcf->cache_key.value.data) {
        !          1824:         return "is duplicate";
        !          1825:     }
        !          1826: 
        !          1827:     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
        !          1828: 
        !          1829:     ccv.cf = cf;
        !          1830:     ccv.value = &value[1];
        !          1831:     ccv.complex_value = &uwcf->cache_key;
        !          1832: 
        !          1833:     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
        !          1834:         return NGX_CONF_ERROR;
        !          1835:     }
        !          1836: 
        !          1837:     return NGX_CONF_OK;
        !          1838: }
        !          1839: 
        !          1840: #endif

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