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