Annotation of embedaddon/nginx/src/http/modules/ngx_http_uwsgi_module.c, revision 1.1.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>