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(¶ms_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(¶ms_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(¶ms_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>