Mercurial > hg > nginx
comparison src/http/modules/ngx_http_uwsgi_module.c @ 3541:21452748d165
import original ngx_http_uwsgi_module version
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 01 Jun 2010 15:53:11 +0000 |
parents | |
children | 9bf51b3fc1c1 |
comparison
equal
deleted
inserted
replaced
3540:2bf7f72f26b7 | 3541:21452748d165 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Unbit S.a.s. 2009-2010 | |
4 * | |
5 * | |
6 * Redistribution and use in source and binary forms, with or without | |
7 * modification, are permitted provided that the following conditions | |
8 * are met: | |
9 * 1. Redistributions of source code must retain the above copyright | |
10 * notice, this list of conditions and the following disclaimer. | |
11 * 2. Redistributions in binary form must reproduce the above copyright | |
12 * notice, this list of conditions and the following disclaimer in the | |
13 * documentation and/or other materials provided with the distribution. | |
14 * | |
15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
25 * SUCH DAMAGE. | |
26 | |
27 | |
28 | |
29 * heavily based on Manlio's mod_scgi, mod_fastcgi and mod_proxy of nginx 0.7.x | |
30 | |
31 */ | |
32 | |
33 | |
34 #include <ngx_config.h> | |
35 #include <ngx_core.h> | |
36 #include <ngx_http.h> | |
37 | |
38 #define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp" | |
39 | |
40 typedef struct { | |
41 ngx_http_upstream_conf_t upstream; | |
42 | |
43 ngx_array_t *flushes; | |
44 ngx_array_t *params_len; | |
45 ngx_array_t *params; | |
46 ngx_array_t *params_source; | |
47 | |
48 ngx_array_t *uwsgi_lengths; | |
49 ngx_array_t *uwsgi_values; | |
50 | |
51 ngx_str_t uwsgi_string ; | |
52 | |
53 u_char modifier1; | |
54 u_char modifier2; | |
55 | |
56 } ngx_http_uwsgi_loc_conf_t; | |
57 | |
58 typedef struct { | |
59 ngx_uint_t status; | |
60 ngx_uint_t status_count; | |
61 u_char *status_start; | |
62 u_char *status_end; | |
63 } ngx_http_uwsgi_ctx_t; | |
64 | |
65 #define NGX_HTTP_XCGI_PARSE_NO_HEADER 20 | |
66 | |
67 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
68 static uint16_t | |
69 uwsgi_swap16 (uint16_t x) | |
70 { | |
71 return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); | |
72 } | |
73 #endif | |
74 | |
75 | |
76 | |
77 static ngx_int_t ngx_http_uwsgi_eval (ngx_http_request_t * r, | |
78 ngx_http_uwsgi_loc_conf_t * uwcf); | |
79 static ngx_int_t ngx_http_uwsgi_create_request (ngx_http_request_t * r); | |
80 static ngx_int_t ngx_http_uwsgi_reinit_request (ngx_http_request_t * r); | |
81 static ngx_int_t ngx_http_uwsgi_process_status_line (ngx_http_request_t * r); | |
82 static ngx_int_t ngx_http_uwsgi_parse_status_line (ngx_http_request_t * r, | |
83 ngx_http_uwsgi_ctx_t * | |
84 ctx); | |
85 static ngx_int_t ngx_http_uwsgi_process_header (ngx_http_request_t * r); | |
86 static ngx_int_t ngx_http_uwsgi_process_header (ngx_http_request_t * r); | |
87 static void ngx_http_uwsgi_abort_request (ngx_http_request_t * r); | |
88 static void ngx_http_uwsgi_finalize_request (ngx_http_request_t * r, | |
89 ngx_int_t rc); | |
90 | |
91 static char *ngx_http_uwsgi_modifier1 (ngx_conf_t * cf, ngx_command_t * cmd, | |
92 void *conf); | |
93 | |
94 static char *ngx_http_uwsgi_modifier2 (ngx_conf_t * cf, ngx_command_t * cmd, | |
95 void *conf); | |
96 | |
97 static ngx_int_t ngx_http_uwsgi_add_variables (ngx_conf_t * cf); | |
98 static void *ngx_http_uwsgi_create_loc_conf (ngx_conf_t * cf); | |
99 static char *ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, | |
100 void *parent, void *child); | |
101 | |
102 static char *ngx_http_uwsgi_pass (ngx_conf_t * cf, ngx_command_t * cmd, | |
103 void *conf); | |
104 | |
105 | |
106 static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = { | |
107 {ngx_string ("error"), NGX_HTTP_UPSTREAM_FT_ERROR}, | |
108 {ngx_string ("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT}, | |
109 {ngx_string ("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER}, | |
110 {ngx_string ("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500}, | |
111 {ngx_string ("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503}, | |
112 {ngx_string ("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404}, | |
113 {ngx_string ("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING}, | |
114 {ngx_string ("off"), NGX_HTTP_UPSTREAM_FT_OFF}, | |
115 {ngx_null_string, 0} | |
116 }; | |
117 | |
118 | |
119 static ngx_conf_bitmask_t ngx_http_uwsgi_ignore_headers_masks[] = { | |
120 {ngx_string ("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT}, | |
121 {ngx_string ("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES}, | |
122 {ngx_string ("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES}, | |
123 {ngx_string ("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL}, | |
124 {ngx_null_string, 0} | |
125 }; | |
126 | |
127 | |
128 ngx_module_t ngx_http_uwsgi_module; | |
129 | |
130 | |
131 static ngx_command_t ngx_http_uwsgi_commands[] = { | |
132 | |
133 {ngx_string ("uwsgi_pass"), | |
134 NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1, | |
135 ngx_http_uwsgi_pass, | |
136 NGX_HTTP_LOC_CONF_OFFSET, | |
137 0, | |
138 NULL}, | |
139 | |
140 {ngx_string ("uwsgi_modifier1"), | |
141 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
142 NGX_CONF_TAKE1, | |
143 ngx_http_uwsgi_modifier1, | |
144 NGX_HTTP_LOC_CONF_OFFSET, | |
145 0, | |
146 NULL}, | |
147 | |
148 {ngx_string ("uwsgi_modifier2"), | |
149 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
150 NGX_CONF_TAKE1, | |
151 ngx_http_uwsgi_modifier2, | |
152 NGX_HTTP_LOC_CONF_OFFSET, | |
153 0, | |
154 NULL}, | |
155 | |
156 {ngx_string ("uwsgi_ignore_client_abort"), | |
157 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
158 NGX_CONF_FLAG, | |
159 ngx_conf_set_flag_slot, | |
160 NGX_HTTP_LOC_CONF_OFFSET, | |
161 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort), | |
162 NULL}, | |
163 | |
164 {ngx_string ("uwsgi_connect_timeout"), | |
165 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
166 NGX_CONF_TAKE1, | |
167 ngx_conf_set_msec_slot, | |
168 NGX_HTTP_LOC_CONF_OFFSET, | |
169 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout), | |
170 NULL}, | |
171 | |
172 {ngx_string ("uwsgi_send_timeout"), | |
173 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
174 NGX_CONF_TAKE1, | |
175 ngx_conf_set_msec_slot, | |
176 NGX_HTTP_LOC_CONF_OFFSET, | |
177 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.send_timeout), | |
178 NULL}, | |
179 | |
180 {ngx_string ("uwsgi_buffer_size"), | |
181 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
182 NGX_CONF_TAKE1, | |
183 ngx_conf_set_size_slot, | |
184 NGX_HTTP_LOC_CONF_OFFSET, | |
185 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.buffer_size), | |
186 NULL}, | |
187 | |
188 {ngx_string ("uwsgi_pass_request_headers"), | |
189 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
190 NGX_CONF_FLAG, | |
191 ngx_conf_set_flag_slot, | |
192 NGX_HTTP_LOC_CONF_OFFSET, | |
193 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers), | |
194 NULL}, | |
195 | |
196 {ngx_string ("uwsgi_pass_request_body"), | |
197 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
198 NGX_CONF_FLAG, | |
199 ngx_conf_set_flag_slot, | |
200 NGX_HTTP_LOC_CONF_OFFSET, | |
201 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body), | |
202 NULL}, | |
203 | |
204 {ngx_string ("uwsgi_intercept_errors"), | |
205 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
206 NGX_CONF_FLAG, | |
207 ngx_conf_set_flag_slot, | |
208 NGX_HTTP_LOC_CONF_OFFSET, | |
209 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors), | |
210 NULL}, | |
211 | |
212 {ngx_string ("uwsgi_read_timeout"), | |
213 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
214 NGX_CONF_TAKE1, | |
215 ngx_conf_set_msec_slot, | |
216 NGX_HTTP_LOC_CONF_OFFSET, | |
217 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.read_timeout), | |
218 NULL}, | |
219 | |
220 {ngx_string ("uwsgi_buffers"), | |
221 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
222 NGX_CONF_TAKE2, | |
223 ngx_conf_set_bufs_slot, | |
224 NGX_HTTP_LOC_CONF_OFFSET, | |
225 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.bufs), | |
226 NULL}, | |
227 | |
228 {ngx_string ("uwsgi_busy_buffers_size"), | |
229 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
230 NGX_CONF_TAKE1, | |
231 ngx_conf_set_size_slot, | |
232 NGX_HTTP_LOC_CONF_OFFSET, | |
233 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf), | |
234 NULL}, | |
235 | |
236 {ngx_string ("uwsgi_temp_path"), | |
237 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
238 NGX_CONF_TAKE1234, | |
239 ngx_conf_set_path_slot, | |
240 NGX_HTTP_LOC_CONF_OFFSET, | |
241 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.temp_path), | |
242 NULL}, | |
243 | |
244 {ngx_string ("uwsgi_max_temp_file_size"), | |
245 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
246 NGX_CONF_TAKE1, | |
247 ngx_conf_set_size_slot, | |
248 NGX_HTTP_LOC_CONF_OFFSET, | |
249 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf), | |
250 NULL}, | |
251 | |
252 {ngx_string ("uwsgi_temp_file_write_size"), | |
253 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
254 NGX_CONF_TAKE1, | |
255 ngx_conf_set_size_slot, | |
256 NGX_HTTP_LOC_CONF_OFFSET, | |
257 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf), | |
258 NULL}, | |
259 | |
260 {ngx_string ("uwsgi_next_upstream"), | |
261 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
262 NGX_CONF_1MORE, | |
263 ngx_conf_set_bitmask_slot, | |
264 NGX_HTTP_LOC_CONF_OFFSET, | |
265 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.next_upstream), | |
266 &ngx_http_uwsgi_next_upstream_masks}, | |
267 | |
268 {ngx_string ("uwsgi_param"), | |
269 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
270 NGX_CONF_TAKE2, | |
271 ngx_conf_set_keyval_slot, | |
272 NGX_HTTP_LOC_CONF_OFFSET, | |
273 offsetof (ngx_http_uwsgi_loc_conf_t, params_source), | |
274 NULL}, | |
275 | |
276 { ngx_string("uwsgi_string"), | |
277 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
278 NGX_CONF_TAKE1, | |
279 ngx_conf_set_str_slot, | |
280 NGX_HTTP_LOC_CONF_OFFSET, | |
281 offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string), | |
282 NULL }, | |
283 | |
284 {ngx_string ("uwsgi_pass_header"), | |
285 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
286 NGX_CONF_FLAG, | |
287 ngx_conf_set_str_array_slot, | |
288 NGX_HTTP_LOC_CONF_OFFSET, | |
289 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_headers), | |
290 NULL}, | |
291 | |
292 {ngx_string ("uwsgi_hide_header"), | |
293 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
294 NGX_CONF_FLAG, | |
295 ngx_conf_set_str_array_slot, | |
296 NGX_HTTP_LOC_CONF_OFFSET, | |
297 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.hide_headers), | |
298 NULL}, | |
299 | |
300 {ngx_string ("uwsgi_ignore_headers"), | |
301 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | | |
302 NGX_CONF_1MORE, | |
303 ngx_conf_set_bitmask_slot, | |
304 NGX_HTTP_LOC_CONF_OFFSET, | |
305 offsetof (ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers), | |
306 &ngx_http_uwsgi_ignore_headers_masks}, | |
307 | |
308 ngx_null_command | |
309 }; | |
310 | |
311 | |
312 static ngx_http_module_t ngx_http_uwsgi_module_ctx = { | |
313 ngx_http_uwsgi_add_variables, /* preconfiguration */ | |
314 NULL, /* postconfiguration */ | |
315 | |
316 NULL, /* create main configuration */ | |
317 NULL, /* init main configuration */ | |
318 | |
319 NULL, /* create server configuration */ | |
320 NULL, /* merge server configuration */ | |
321 | |
322 ngx_http_uwsgi_create_loc_conf, /* create location configuration */ | |
323 ngx_http_uwsgi_merge_loc_conf /* merge location configuration */ | |
324 }; | |
325 | |
326 | |
327 ngx_module_t ngx_http_uwsgi_module = { | |
328 NGX_MODULE_V1, | |
329 &ngx_http_uwsgi_module_ctx, /* module context */ | |
330 ngx_http_uwsgi_commands, /* module directives */ | |
331 NGX_HTTP_MODULE, /* module type */ | |
332 NULL, /* init master */ | |
333 NULL, /* init module */ | |
334 NULL, /* init process */ | |
335 NULL, /* init thread */ | |
336 NULL, /* exit thread */ | |
337 NULL, /* exit process */ | |
338 NULL, /* exit master */ | |
339 NGX_MODULE_V1_PADDING | |
340 }; | |
341 | |
342 | |
343 static ngx_http_variable_t ngx_http_uwsgi_vars[] = { | |
344 | |
345 {ngx_null_string, NULL, NULL, 0, 0, 0} | |
346 }; | |
347 | |
348 | |
349 static ngx_str_t ngx_http_uwsgi_hide_headers[] = { | |
350 ngx_string ("Status"), | |
351 ngx_string ("X-Accel-Expires"), | |
352 ngx_string ("X-Accel-Redirect"), | |
353 ngx_string ("X-Accel-Limit-Rate"), | |
354 ngx_string ("X-Accel-Buffering"), | |
355 ngx_string ("X-Accel-Charset"), | |
356 ngx_null_string | |
357 }; | |
358 | |
359 | |
360 static ngx_path_init_t ngx_http_uwsgi_temp_path = { | |
361 ngx_string (NGX_HTTP_UWSGI_TEMP_PATH), {1, 2, 0} | |
362 }; | |
363 | |
364 | |
365 static ngx_int_t | |
366 ngx_http_uwsgi_handler (ngx_http_request_t * r) | |
367 { | |
368 ngx_int_t rc; | |
369 ngx_http_upstream_t *u; | |
370 ngx_http_uwsgi_ctx_t *f; | |
371 ngx_http_uwsgi_loc_conf_t *uwcf; | |
372 | |
373 if (r->subrequest_in_memory) { | |
374 ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0, | |
375 "ngx_http_uwsgi_module does not support " | |
376 "subrequest in memory"); | |
377 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
378 } | |
379 | |
380 if (ngx_http_upstream_create (r) != NGX_OK) { | |
381 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
382 } | |
383 | |
384 f = ngx_pcalloc (r->pool, sizeof (ngx_http_uwsgi_ctx_t)); | |
385 if (f == NULL) { | |
386 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
387 } | |
388 | |
389 ngx_http_set_ctx (r, f, ngx_http_uwsgi_module); | |
390 | |
391 uwcf = ngx_http_get_module_loc_conf (r, ngx_http_uwsgi_module); | |
392 | |
393 if (uwcf->uwsgi_lengths) { | |
394 if (ngx_http_uwsgi_eval (r, uwcf) != NGX_OK) { | |
395 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
396 } | |
397 } | |
398 | |
399 u = r->upstream; | |
400 | |
401 u->schema.len = sizeof ("uwsgi://") - 1; | |
402 u->schema.data = (u_char *) "uwsgi://"; | |
403 | |
404 u->output.tag = (ngx_buf_tag_t) & ngx_http_uwsgi_module; | |
405 | |
406 u->conf = &uwcf->upstream; | |
407 | |
408 u->create_request = ngx_http_uwsgi_create_request; | |
409 u->reinit_request = ngx_http_uwsgi_reinit_request; | |
410 u->process_header = ngx_http_uwsgi_process_status_line; | |
411 u->abort_request = ngx_http_uwsgi_abort_request; | |
412 u->finalize_request = ngx_http_uwsgi_finalize_request; | |
413 | |
414 u->buffering = 1; | |
415 | |
416 u->pipe = ngx_pcalloc (r->pool, sizeof (ngx_event_pipe_t)); | |
417 if (u->pipe == NULL) { | |
418 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
419 } | |
420 | |
421 u->pipe->input_filter = ngx_event_pipe_copy_input_filter; | |
422 u->pipe->input_ctx = r; | |
423 | |
424 rc = ngx_http_read_client_request_body (r, ngx_http_upstream_init); | |
425 | |
426 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
427 return rc; | |
428 } | |
429 | |
430 return NGX_DONE; | |
431 } | |
432 | |
433 | |
434 static ngx_int_t | |
435 ngx_http_uwsgi_eval (ngx_http_request_t * r, ngx_http_uwsgi_loc_conf_t * uwcf) | |
436 { | |
437 ngx_url_t u; | |
438 | |
439 ngx_memzero (&u, sizeof (ngx_url_t)); | |
440 | |
441 if (ngx_http_script_run (r, &u.url, uwcf->uwsgi_lengths->elts, 0, | |
442 uwcf->uwsgi_values->elts) == NULL) { | |
443 return NGX_ERROR; | |
444 } | |
445 | |
446 u.no_resolve = 1; | |
447 | |
448 if (ngx_parse_url (r->pool, &u) != NGX_OK) { | |
449 if (u.err) { | |
450 ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, | |
451 "%s in upstream \"%V\"", u.err, &u.url); | |
452 } | |
453 | |
454 return NGX_ERROR; | |
455 } | |
456 | |
457 if (u.no_port) { | |
458 ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, | |
459 "no port in upstream \"%V\"", &u.url); | |
460 return NGX_ERROR; | |
461 } | |
462 | |
463 r->upstream->resolved = ngx_pcalloc (r->pool, | |
464 sizeof | |
465 (ngx_http_upstream_resolved_t)); | |
466 if (r->upstream->resolved == NULL) { | |
467 return NGX_ERROR; | |
468 } | |
469 | |
470 if (u.addrs && u.addrs[0].sockaddr) { | |
471 r->upstream->resolved->sockaddr = u.addrs[0].sockaddr; | |
472 r->upstream->resolved->socklen = u.addrs[0].socklen; | |
473 r->upstream->resolved->naddrs = 1; | |
474 r->upstream->resolved->host = u.addrs[0].name; | |
475 | |
476 } | |
477 else { | |
478 r->upstream->resolved->host = u.host; | |
479 r->upstream->resolved->port = u.port; | |
480 } | |
481 | |
482 return NGX_OK; | |
483 } | |
484 | |
485 | |
486 static ngx_int_t | |
487 ngx_http_uwsgi_create_request (ngx_http_request_t * r) | |
488 { | |
489 u_char ch, *pos, tmp[2]; | |
490 size_t key_len, val_len; | |
491 uint16_t uwsgi_pkt_size, uwsgi_strlen; | |
492 ngx_uint_t i, n; | |
493 ngx_buf_t *b; | |
494 ngx_chain_t *cl, *body; | |
495 ngx_list_part_t *part; | |
496 ngx_table_elt_t *header; | |
497 ngx_http_script_code_pt code; | |
498 ngx_http_script_engine_t e, le; | |
499 ngx_http_uwsgi_loc_conf_t *uwcf; | |
500 ngx_http_script_len_code_pt lcode; | |
501 | |
502 uwsgi_pkt_size = 0; | |
503 | |
504 uwcf = ngx_http_get_module_loc_conf (r, ngx_http_uwsgi_module); | |
505 | |
506 if (uwcf->params_len) { | |
507 ngx_memzero (&le, sizeof (ngx_http_script_engine_t)); | |
508 | |
509 ngx_http_script_flush_no_cacheable_variables (r, uwcf->flushes); | |
510 le.flushed = 1; | |
511 | |
512 le.ip = uwcf->params_len->elts; | |
513 le.request = r; | |
514 | |
515 while (*(uintptr_t *) le.ip) { | |
516 | |
517 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
518 key_len = lcode (&le); | |
519 | |
520 for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { | |
521 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
522 } | |
523 le.ip += sizeof (uintptr_t); | |
524 | |
525 uwsgi_pkt_size += 2 + key_len + 2 + val_len; | |
526 } | |
527 } | |
528 | |
529 if (uwcf->upstream.pass_request_headers) { | |
530 | |
531 part = &r->headers_in.headers.part; | |
532 header = part->elts; | |
533 | |
534 for (i = 0; /* void */ ; i++) { | |
535 | |
536 if (i >= part->nelts) { | |
537 if (part->next == NULL) { | |
538 break; | |
539 } | |
540 | |
541 part = part->next; | |
542 header = part->elts; | |
543 i = 0; | |
544 } | |
545 | |
546 uwsgi_pkt_size += | |
547 2 + 5 + header[i].key.len + 2 + header[i].value.len; | |
548 } | |
549 } | |
550 | |
551 if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) { | |
552 uwsgi_pkt_size += uwcf->uwsgi_string.len ; | |
553 } | |
554 | |
555 | |
556 /* allow custom uwsgi packet | |
557 if (uwsgi_pkt_size > 0 && uwsgi_pkt_size < 2) { | |
558 ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0, | |
559 "uwsgi request is too little: %uz", uwsgi_pkt_size); | |
560 return NGX_ERROR; | |
561 } | |
562 */ | |
563 | |
564 b = ngx_create_temp_buf (r->pool, uwsgi_pkt_size + 4); | |
565 if (b == NULL) { | |
566 return NGX_ERROR; | |
567 } | |
568 | |
569 cl = ngx_alloc_chain_link (r->pool); | |
570 if (cl == NULL) { | |
571 return NGX_ERROR; | |
572 } | |
573 | |
574 cl->buf = b; | |
575 | |
576 *b->pos = uwcf->modifier1; | |
577 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
578 uwsgi_pkt_size = uwsgi_swap16 (uwsgi_pkt_size); | |
579 #endif | |
580 b->last = ngx_cpymem (b->pos + 1, &uwsgi_pkt_size, 2); | |
581 *(b->pos + 3) = uwcf->modifier2; | |
582 b->last++; | |
583 | |
584 if (uwcf->params_len) { | |
585 ngx_memzero (&e, sizeof (ngx_http_script_engine_t)); | |
586 | |
587 e.ip = uwcf->params->elts; | |
588 e.pos = b->last; | |
589 e.request = r; | |
590 e.flushed = 1; | |
591 | |
592 le.ip = uwcf->params_len->elts; | |
593 | |
594 while (*(uintptr_t *) le.ip) { | |
595 | |
596 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
597 key_len = (u_char) lcode (&le); | |
598 | |
599 for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { | |
600 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
601 } | |
602 le.ip += sizeof (uintptr_t); | |
603 | |
604 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
605 uwsgi_strlen = uwsgi_swap16 (key_len); | |
606 #else | |
607 uwsgi_strlen = key_len; | |
608 #endif | |
609 e.pos = ngx_cpymem (e.pos, &uwsgi_strlen, 2); | |
610 | |
611 while (*(uintptr_t *) e.ip) { | |
612 code = *(ngx_http_script_code_pt *) e.ip; | |
613 code ((ngx_http_script_engine_t *) & e); | |
614 } | |
615 | |
616 pos = e.pos - val_len; | |
617 /* move memory */ | |
618 for (i = 0; i < val_len; i += 2) { | |
619 e.pos = ngx_cpymem (tmp, pos + (i) + 2, 2); | |
620 e.pos = ngx_cpymem (pos + (i) + 2, pos, 2); | |
621 e.pos = ngx_cpymem (pos, tmp, 2); | |
622 } | |
623 | |
624 e.pos = pos; | |
625 | |
626 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
627 uwsgi_strlen = uwsgi_swap16 (val_len); | |
628 #else | |
629 uwsgi_strlen = val_len; | |
630 #endif | |
631 e.pos = ngx_cpymem (e.pos, &uwsgi_strlen, 2); | |
632 e.pos += val_len; | |
633 | |
634 e.ip += sizeof (uintptr_t); | |
635 | |
636 | |
637 } | |
638 | |
639 b->last = e.pos; | |
640 } | |
641 | |
642 | |
643 if (uwcf->upstream.pass_request_headers) { | |
644 | |
645 part = &r->headers_in.headers.part; | |
646 header = part->elts; | |
647 | |
648 for (i = 0; /* void */ ; i++) { | |
649 | |
650 if (i >= part->nelts) { | |
651 if (part->next == NULL) { | |
652 break; | |
653 } | |
654 | |
655 part = part->next; | |
656 header = part->elts; | |
657 i = 0; | |
658 } | |
659 | |
660 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
661 uwsgi_strlen = uwsgi_swap16 (5 + header[i].key.len); | |
662 #else | |
663 uwsgi_strlen = 5 + header[i].key.len; | |
664 #endif | |
665 b->last = ngx_cpymem (b->last, &uwsgi_strlen, 2); | |
666 b->last = ngx_cpymem (b->last, "HTTP_", 5); | |
667 for (n = 0; n < header[i].key.len; n++) { | |
668 ch = header[i].key.data[n]; | |
669 | |
670 if (ch >= 'a' && ch <= 'z') { | |
671 ch &= ~0x20; | |
672 | |
673 } | |
674 else if (ch == '-') { | |
675 ch = '_'; | |
676 } | |
677 | |
678 *b->last++ = ch; | |
679 } | |
680 #ifndef NGX_HAVE_LITTLE_ENDIAN | |
681 uwsgi_strlen = uwsgi_swap16 (header[i].value.len); | |
682 #else | |
683 uwsgi_strlen = header[i].value.len; | |
684 #endif | |
685 b->last = ngx_cpymem (b->last, &uwsgi_strlen, 2); | |
686 b->last = | |
687 ngx_copy (b->last, header[i].value.data, header[i].value.len); | |
688 | |
689 | |
690 } | |
691 } | |
692 | |
693 | |
694 | |
695 if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) { | |
696 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, uwcf->uwsgi_string.len); | |
697 } | |
698 | |
699 if (uwcf->upstream.pass_request_body) { | |
700 body = r->upstream->request_bufs; | |
701 r->upstream->request_bufs = cl; | |
702 | |
703 while (body) { | |
704 b = ngx_alloc_buf (r->pool); | |
705 if (b == NULL) { | |
706 return NGX_ERROR; | |
707 } | |
708 | |
709 ngx_memcpy (b, body->buf, sizeof (ngx_buf_t)); | |
710 | |
711 cl->next = ngx_alloc_chain_link (r->pool); | |
712 if (cl->next == NULL) { | |
713 return NGX_ERROR; | |
714 } | |
715 | |
716 cl = cl->next; | |
717 cl->buf = b; | |
718 | |
719 body = body->next; | |
720 } | |
721 | |
722 b->flush = 1; | |
723 | |
724 } | |
725 else { | |
726 r->upstream->request_bufs = cl; | |
727 } | |
728 | |
729 cl->next = NULL; | |
730 | |
731 return NGX_OK; | |
732 } | |
733 | |
734 | |
735 static ngx_int_t | |
736 ngx_http_uwsgi_reinit_request (ngx_http_request_t * r) | |
737 { | |
738 | |
739 ngx_http_uwsgi_ctx_t *s; | |
740 | |
741 s = ngx_http_get_module_ctx (r, ngx_http_uwsgi_module); | |
742 | |
743 if (s == NULL) { | |
744 return NGX_OK; | |
745 } | |
746 | |
747 s->status = 0; | |
748 s->status_count = 0; | |
749 s->status_start = NULL; | |
750 s->status_end = NULL; | |
751 | |
752 r->upstream->process_header = ngx_http_uwsgi_process_status_line; | |
753 | |
754 return NGX_OK; | |
755 } | |
756 | |
757 static ngx_int_t | |
758 ngx_http_uwsgi_parse_status_line (ngx_http_request_t * r, | |
759 ngx_http_uwsgi_ctx_t * ctx) | |
760 { | |
761 u_char ch; | |
762 u_char *p; | |
763 ngx_http_upstream_t *u; | |
764 enum { | |
765 sw_start = 0, | |
766 sw_H, | |
767 sw_HT, | |
768 sw_HTT, | |
769 sw_HTTP, | |
770 sw_first_major_digit, | |
771 sw_major_digit, | |
772 sw_first_minor_digit, | |
773 sw_minor_digit, | |
774 sw_status, | |
775 sw_space_after_status, | |
776 sw_status_text, | |
777 sw_almost_done | |
778 } state; | |
779 | |
780 u = r->upstream; | |
781 | |
782 state = r->state; | |
783 | |
784 for (p = u->buffer.pos; p < u->buffer.last; p++) { | |
785 ch = *p; | |
786 | |
787 switch (state) { | |
788 | |
789 /* "HTTP/" */ | |
790 case sw_start: | |
791 switch (ch) { | |
792 case 'H': | |
793 state = sw_H; | |
794 break; | |
795 default: | |
796 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
797 } | |
798 break; | |
799 | |
800 case sw_H: | |
801 switch (ch) { | |
802 case 'T': | |
803 state = sw_HT; | |
804 break; | |
805 default: | |
806 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
807 } | |
808 break; | |
809 | |
810 case sw_HT: | |
811 switch (ch) { | |
812 case 'T': | |
813 state = sw_HTT; | |
814 break; | |
815 default: | |
816 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
817 } | |
818 break; | |
819 | |
820 case sw_HTT: | |
821 switch (ch) { | |
822 case 'P': | |
823 state = sw_HTTP; | |
824 break; | |
825 default: | |
826 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
827 } | |
828 break; | |
829 | |
830 case sw_HTTP: | |
831 switch (ch) { | |
832 case '/': | |
833 state = sw_first_major_digit; | |
834 break; | |
835 default: | |
836 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
837 } | |
838 break; | |
839 | |
840 /* the first digit of major HTTP version */ | |
841 case sw_first_major_digit: | |
842 if (ch < '1' || ch > '9') { | |
843 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
844 } | |
845 | |
846 state = sw_major_digit; | |
847 break; | |
848 | |
849 /* the major HTTP version or dot */ | |
850 case sw_major_digit: | |
851 if (ch == '.') { | |
852 state = sw_first_minor_digit; | |
853 break; | |
854 } | |
855 | |
856 if (ch < '0' || ch > '9') { | |
857 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
858 } | |
859 | |
860 break; | |
861 | |
862 /* the first digit of minor HTTP version */ | |
863 case sw_first_minor_digit: | |
864 if (ch < '0' || ch > '9') { | |
865 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
866 } | |
867 | |
868 state = sw_minor_digit; | |
869 break; | |
870 | |
871 /* the minor HTTP version or the end of the request line */ | |
872 case sw_minor_digit: | |
873 if (ch == ' ') { | |
874 state = sw_status; | |
875 break; | |
876 } | |
877 | |
878 if (ch < '0' || ch > '9') { | |
879 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
880 } | |
881 | |
882 break; | |
883 | |
884 /* HTTP status code */ | |
885 case sw_status: | |
886 if (ch == ' ') { | |
887 break; | |
888 } | |
889 | |
890 if (ch < '0' || ch > '9') { | |
891 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
892 } | |
893 | |
894 ctx->status = ctx->status * 10 + ch - '0'; | |
895 | |
896 if (++ctx->status_count == 3) { | |
897 state = sw_space_after_status; | |
898 ctx->status_start = p - 2; | |
899 } | |
900 | |
901 break; | |
902 | |
903 /* space or end of line */ | |
904 case sw_space_after_status: | |
905 switch (ch) { | |
906 case ' ': | |
907 state = sw_status_text; | |
908 break; | |
909 case '.': /* IIS may send 403.1, 403.2, etc */ | |
910 state = sw_status_text; | |
911 break; | |
912 case CR: | |
913 state = sw_almost_done; | |
914 break; | |
915 case LF: | |
916 goto done; | |
917 default: | |
918 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
919 } | |
920 break; | |
921 | |
922 /* any text until end of line */ | |
923 case sw_status_text: | |
924 switch (ch) { | |
925 case CR: | |
926 state = sw_almost_done; | |
927 | |
928 break; | |
929 case LF: | |
930 goto done; | |
931 } | |
932 break; | |
933 | |
934 /* end of status line */ | |
935 case sw_almost_done: | |
936 ctx->status_end = p - 1; | |
937 switch (ch) { | |
938 case LF: | |
939 goto done; | |
940 default: | |
941 return NGX_HTTP_XCGI_PARSE_NO_HEADER; | |
942 } | |
943 } | |
944 } | |
945 | |
946 u->buffer.pos = p; | |
947 r->state = state; | |
948 | |
949 return NGX_AGAIN; | |
950 | |
951 done: | |
952 | |
953 u->buffer.pos = p + 1; | |
954 | |
955 if (ctx->status_end == NULL) { | |
956 ctx->status_end = p; | |
957 } | |
958 | |
959 r->state = sw_start; | |
960 | |
961 return NGX_OK; | |
962 } | |
963 | |
964 | |
965 static ngx_int_t | |
966 ngx_http_uwsgi_process_status_line (ngx_http_request_t * r) | |
967 { | |
968 ngx_int_t rc; | |
969 ngx_http_upstream_t *u; | |
970 ngx_http_uwsgi_ctx_t *ctx; | |
971 | |
972 ctx = ngx_http_get_module_ctx (r, ngx_http_uwsgi_module); | |
973 | |
974 if (ctx == NULL) { | |
975 return NGX_ERROR; | |
976 } | |
977 | |
978 rc = ngx_http_uwsgi_parse_status_line (r, ctx); | |
979 | |
980 if (rc == NGX_AGAIN) { | |
981 return rc; | |
982 } | |
983 | |
984 u = r->upstream; | |
985 | |
986 if (rc == NGX_HTTP_XCGI_PARSE_NO_HEADER) { | |
987 | |
988 ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, | |
989 "upstream sent no valid HTTP/1.0 header"); | |
990 | |
991 r->http_version = NGX_HTTP_VERSION_9; | |
992 u->headers_in.status_n = NGX_HTTP_OK; | |
993 u->state->status = NGX_HTTP_OK; | |
994 | |
995 return NGX_OK; | |
996 } | |
997 | |
998 if (u->state) { | |
999 u->state->status = ctx->status; | |
1000 } | |
1001 | |
1002 u->headers_in.status_n = ctx->status; | |
1003 | |
1004 u->headers_in.status_line.len = ctx->status_end - ctx->status_start; | |
1005 u->headers_in.status_line.data = ngx_pnalloc (r->pool, | |
1006 u->headers_in. | |
1007 status_line.len); | |
1008 if (u->headers_in.status_line.data == NULL) { | |
1009 return NGX_ERROR; | |
1010 } | |
1011 | |
1012 ngx_memcpy (u->headers_in.status_line.data, ctx->status_start, | |
1013 u->headers_in.status_line.len); | |
1014 | |
1015 ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1016 "http uwsgi status %ui \"%V\"", | |
1017 u->headers_in.status_n, &u->headers_in.status_line); | |
1018 | |
1019 u->process_header = ngx_http_uwsgi_process_header; | |
1020 | |
1021 return ngx_http_uwsgi_process_header (r); | |
1022 } | |
1023 | |
1024 | |
1025 static ngx_int_t | |
1026 ngx_http_uwsgi_process_header (ngx_http_request_t * r) | |
1027 { | |
1028 ngx_int_t rc; | |
1029 ngx_table_elt_t *h; | |
1030 ngx_http_upstream_header_t *hh; | |
1031 ngx_http_upstream_main_conf_t *umcf; | |
1032 | |
1033 umcf = ngx_http_get_module_main_conf (r, ngx_http_upstream_module); | |
1034 | |
1035 for (;;) { | |
1036 | |
1037 rc = ngx_http_parse_header_line (r, &r->upstream->buffer, 1); | |
1038 | |
1039 if (rc == NGX_OK) { | |
1040 | |
1041 /* a header line has been parsed successfully */ | |
1042 | |
1043 h = ngx_list_push (&r->upstream->headers_in.headers); | |
1044 if (h == NULL) { | |
1045 return NGX_ERROR; | |
1046 } | |
1047 | |
1048 h->hash = r->header_hash; | |
1049 | |
1050 h->key.len = r->header_name_end - r->header_name_start; | |
1051 h->value.len = r->header_end - r->header_start; | |
1052 | |
1053 h->key.data = ngx_pnalloc (r->pool, | |
1054 h->key.len + 1 + h->value.len + 1 + | |
1055 h->key.len); | |
1056 if (h->key.data == NULL) { | |
1057 return NGX_ERROR; | |
1058 } | |
1059 | |
1060 h->value.data = h->key.data + h->key.len + 1; | |
1061 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; | |
1062 | |
1063 ngx_cpystrn (h->key.data, r->header_name_start, h->key.len + 1); | |
1064 ngx_cpystrn (h->value.data, r->header_start, h->value.len + 1); | |
1065 | |
1066 if (h->key.len == r->lowcase_index) { | |
1067 ngx_memcpy (h->lowcase_key, r->lowcase_header, h->key.len); | |
1068 | |
1069 } | |
1070 else { | |
1071 ngx_strlow (h->lowcase_key, h->key.data, h->key.len); | |
1072 } | |
1073 | |
1074 hh = ngx_hash_find (&umcf->headers_in_hash, h->hash, | |
1075 h->lowcase_key, h->key.len); | |
1076 | |
1077 if (hh && hh->handler (r, h, hh->offset) != NGX_OK) { | |
1078 return NGX_ERROR; | |
1079 } | |
1080 | |
1081 ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1082 "http uwsgi header: \"%V: %V\"", | |
1083 &h->key, &h->value); | |
1084 | |
1085 continue; | |
1086 } | |
1087 | |
1088 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
1089 | |
1090 /* a whole header has been parsed successfully */ | |
1091 | |
1092 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1093 "http uwsgi header done"); | |
1094 | |
1095 /* | |
1096 * if no "Server" and "Date" in header line, | |
1097 * then add the special empty headers | |
1098 */ | |
1099 | |
1100 if (r->upstream->headers_in.server == NULL) { | |
1101 h = ngx_list_push (&r->upstream->headers_in.headers); | |
1102 if (h == NULL) { | |
1103 return NGX_ERROR; | |
1104 } | |
1105 | |
1106 h->hash = | |
1107 ngx_hash (ngx_hash | |
1108 (ngx_hash | |
1109 (ngx_hash (ngx_hash ('s', 'e'), 'r'), | |
1110 'v'), 'e'), 'r'); | |
1111 | |
1112 h->key.len = sizeof ("Server") - 1; | |
1113 h->key.data = (u_char *) "Server"; | |
1114 h->value.len = 0; | |
1115 h->value.data = NULL; | |
1116 h->lowcase_key = (u_char *) "server"; | |
1117 } | |
1118 | |
1119 if (r->upstream->headers_in.date == NULL) { | |
1120 h = ngx_list_push (&r->upstream->headers_in.headers); | |
1121 if (h == NULL) { | |
1122 return NGX_ERROR; | |
1123 } | |
1124 | |
1125 h->hash = ngx_hash (ngx_hash (ngx_hash ('d', 'a'), 't'), 'e'); | |
1126 | |
1127 h->key.len = sizeof ("Date") - 1; | |
1128 h->key.data = (u_char *) "Date"; | |
1129 h->value.len = 0; | |
1130 h->value.data = NULL; | |
1131 h->lowcase_key = (u_char *) "date"; | |
1132 } | |
1133 | |
1134 return NGX_OK; | |
1135 } | |
1136 | |
1137 if (rc == NGX_AGAIN) { | |
1138 return NGX_AGAIN; | |
1139 } | |
1140 | |
1141 /* there was error while a header line parsing */ | |
1142 | |
1143 ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, | |
1144 "upstream sent invalid header"); | |
1145 | |
1146 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
1147 } | |
1148 } | |
1149 | |
1150 | |
1151 static void | |
1152 ngx_http_uwsgi_abort_request (ngx_http_request_t * r) | |
1153 { | |
1154 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1155 "abort http uwsgi request"); | |
1156 | |
1157 return; | |
1158 } | |
1159 | |
1160 | |
1161 static void | |
1162 ngx_http_uwsgi_finalize_request (ngx_http_request_t * r, ngx_int_t rc) | |
1163 { | |
1164 ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1165 "finalize http uwsgi request"); | |
1166 | |
1167 return; | |
1168 } | |
1169 | |
1170 | |
1171 static ngx_int_t | |
1172 ngx_http_uwsgi_add_variables (ngx_conf_t * cf) | |
1173 { | |
1174 ngx_http_variable_t *var, *v; | |
1175 | |
1176 for (v = ngx_http_uwsgi_vars; v->name.len; v++) { | |
1177 var = ngx_http_add_variable (cf, &v->name, v->flags); | |
1178 if (var == NULL) { | |
1179 return NGX_ERROR; | |
1180 } | |
1181 | |
1182 var->get_handler = v->get_handler; | |
1183 var->data = v->data; | |
1184 } | |
1185 | |
1186 return NGX_OK; | |
1187 } | |
1188 | |
1189 | |
1190 static void * | |
1191 ngx_http_uwsgi_create_loc_conf (ngx_conf_t * cf) | |
1192 { | |
1193 ngx_http_uwsgi_loc_conf_t *conf; | |
1194 | |
1195 conf = ngx_pcalloc (cf->pool, sizeof (ngx_http_uwsgi_loc_conf_t)); | |
1196 if (conf == NULL) { | |
1197 return NULL; | |
1198 } | |
1199 | |
1200 conf->upstream.store = NGX_CONF_UNSET; | |
1201 conf->upstream.store_access = NGX_CONF_UNSET_UINT; | |
1202 conf->upstream.buffering = NGX_CONF_UNSET; | |
1203 conf->upstream.ignore_client_abort = NGX_CONF_UNSET; | |
1204 | |
1205 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | |
1206 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | |
1207 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | |
1208 | |
1209 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; | |
1210 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; | |
1211 | |
1212 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; | |
1213 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; | |
1214 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; | |
1215 | |
1216 conf->upstream.pass_request_headers = NGX_CONF_UNSET; | |
1217 conf->upstream.pass_request_body = NGX_CONF_UNSET; | |
1218 | |
1219 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; | |
1220 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; | |
1221 | |
1222 conf->upstream.intercept_errors = NGX_CONF_UNSET; | |
1223 | |
1224 /* "uwsgi_cyclic_temp_file" is disabled */ | |
1225 conf->upstream.cyclic_temp_file = 0; | |
1226 | |
1227 return conf; | |
1228 } | |
1229 | |
1230 | |
1231 static char * | |
1232 ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, void *parent, void *child) | |
1233 { | |
1234 ngx_http_uwsgi_loc_conf_t *prev = parent; | |
1235 ngx_http_uwsgi_loc_conf_t *conf = child; | |
1236 | |
1237 u_char *p; | |
1238 size_t size; | |
1239 uintptr_t *code; | |
1240 ngx_uint_t i; | |
1241 ngx_keyval_t *src; | |
1242 ngx_hash_init_t hash; | |
1243 ngx_http_script_compile_t sc; | |
1244 ngx_http_script_copy_code_t *copy; | |
1245 | |
1246 if (conf->upstream.store != 0) { | |
1247 ngx_conf_merge_value (conf->upstream.store, prev->upstream.store, 0); | |
1248 | |
1249 if (conf->upstream.store_lengths == NULL) { | |
1250 conf->upstream.store_lengths = prev->upstream.store_lengths; | |
1251 conf->upstream.store_values = prev->upstream.store_values; | |
1252 } | |
1253 } | |
1254 | |
1255 ngx_conf_merge_uint_value (conf->upstream.store_access, | |
1256 prev->upstream.store_access, 0600); | |
1257 | |
1258 ngx_conf_merge_value (conf->upstream.buffering, | |
1259 prev->upstream.buffering, 1); | |
1260 | |
1261 ngx_conf_merge_value (conf->upstream.ignore_client_abort, | |
1262 prev->upstream.ignore_client_abort, 0); | |
1263 | |
1264 ngx_conf_merge_msec_value (conf->upstream.connect_timeout, | |
1265 prev->upstream.connect_timeout, 60000); | |
1266 | |
1267 ngx_conf_merge_msec_value (conf->upstream.send_timeout, | |
1268 prev->upstream.send_timeout, 60000); | |
1269 | |
1270 ngx_conf_merge_msec_value (conf->upstream.read_timeout, | |
1271 prev->upstream.read_timeout, 60000); | |
1272 | |
1273 ngx_conf_merge_size_value (conf->upstream.send_lowat, | |
1274 prev->upstream.send_lowat, 0); | |
1275 | |
1276 ngx_conf_merge_size_value (conf->upstream.buffer_size, | |
1277 prev->upstream.buffer_size, | |
1278 (size_t) ngx_pagesize); | |
1279 | |
1280 | |
1281 ngx_conf_merge_bufs_value (conf->upstream.bufs, prev->upstream.bufs, | |
1282 8, ngx_pagesize); | |
1283 | |
1284 if (conf->upstream.bufs.num < 2) { | |
1285 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, | |
1286 "there must be at least 2 \"uwsgi_buffers\""); | |
1287 return NGX_CONF_ERROR; | |
1288 } | |
1289 | |
1290 | |
1291 size = conf->upstream.buffer_size; | |
1292 if (size < conf->upstream.bufs.size) { | |
1293 size = conf->upstream.bufs.size; | |
1294 } | |
1295 | |
1296 | |
1297 ngx_conf_merge_size_value (conf->upstream.busy_buffers_size_conf, | |
1298 prev->upstream.busy_buffers_size_conf, | |
1299 NGX_CONF_UNSET_SIZE); | |
1300 | |
1301 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { | |
1302 conf->upstream.busy_buffers_size = 2 * size; | |
1303 } | |
1304 else { | |
1305 conf->upstream.busy_buffers_size = | |
1306 conf->upstream.busy_buffers_size_conf; | |
1307 } | |
1308 | |
1309 if (conf->upstream.busy_buffers_size < size) { | |
1310 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, | |
1311 "\"uwsgi_busy_buffers_size\" must be equal or bigger than " | |
1312 "maximum of the value of \"uwsgi_buffer_size\" and " | |
1313 "one of the \"uwsgi_buffers\""); | |
1314 | |
1315 return NGX_CONF_ERROR; | |
1316 } | |
1317 | |
1318 if (conf->upstream.busy_buffers_size | |
1319 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) { | |
1320 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, | |
1321 "\"uwsgi_busy_buffers_size\" must be less than " | |
1322 "the size of all \"uwsgi_buffers\" minus one buffer"); | |
1323 | |
1324 return NGX_CONF_ERROR; | |
1325 } | |
1326 | |
1327 | |
1328 ngx_conf_merge_size_value (conf->upstream.temp_file_write_size_conf, | |
1329 prev->upstream.temp_file_write_size_conf, | |
1330 NGX_CONF_UNSET_SIZE); | |
1331 | |
1332 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { | |
1333 conf->upstream.temp_file_write_size = 2 * size; | |
1334 } | |
1335 else { | |
1336 conf->upstream.temp_file_write_size = | |
1337 conf->upstream.temp_file_write_size_conf; | |
1338 } | |
1339 | |
1340 if (conf->upstream.temp_file_write_size < size) { | |
1341 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, | |
1342 "\"uwsgi_temp_file_write_size\" must be equal or bigger than " | |
1343 "maximum of the value of \"uwsgi_buffer_size\" and " | |
1344 "one of the \"uwsgi_buffers\""); | |
1345 | |
1346 return NGX_CONF_ERROR; | |
1347 } | |
1348 | |
1349 | |
1350 ngx_conf_merge_size_value (conf->upstream.max_temp_file_size_conf, | |
1351 prev->upstream.max_temp_file_size_conf, | |
1352 NGX_CONF_UNSET_SIZE); | |
1353 | |
1354 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { | |
1355 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; | |
1356 } | |
1357 else { | |
1358 conf->upstream.max_temp_file_size = | |
1359 conf->upstream.max_temp_file_size_conf; | |
1360 } | |
1361 | |
1362 if (conf->upstream.max_temp_file_size != 0 | |
1363 && conf->upstream.max_temp_file_size < size) { | |
1364 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, | |
1365 "\"uwsgi_max_temp_file_size\" must be equal to zero to disable " | |
1366 "the temporary files usage or must be equal or bigger than " | |
1367 "maximum of the value of \"uwsgi_buffer_size\" and " | |
1368 "one of the \"uwsgi_buffers\""); | |
1369 | |
1370 return NGX_CONF_ERROR; | |
1371 } | |
1372 | |
1373 | |
1374 ngx_conf_merge_bitmask_value (conf->upstream.ignore_headers, | |
1375 prev->upstream.ignore_headers, | |
1376 NGX_CONF_BITMASK_SET); | |
1377 | |
1378 | |
1379 ngx_conf_merge_bitmask_value (conf->upstream.next_upstream, | |
1380 prev->upstream.next_upstream, | |
1381 (NGX_CONF_BITMASK_SET | |
1382 | NGX_HTTP_UPSTREAM_FT_ERROR | |
1383 | NGX_HTTP_UPSTREAM_FT_TIMEOUT)); | |
1384 | |
1385 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { | |
1386 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET | |
1387 | NGX_HTTP_UPSTREAM_FT_OFF; | |
1388 } | |
1389 | |
1390 if (ngx_conf_merge_path_value (cf, &conf->upstream.temp_path, | |
1391 prev->upstream.temp_path, | |
1392 &ngx_http_uwsgi_temp_path) != NGX_OK) { | |
1393 return NGX_CONF_ERROR; | |
1394 } | |
1395 | |
1396 ngx_conf_merge_value (conf->upstream.pass_request_headers, | |
1397 prev->upstream.pass_request_headers, 1); | |
1398 ngx_conf_merge_value (conf->upstream.pass_request_body, | |
1399 prev->upstream.pass_request_body, 1); | |
1400 | |
1401 ngx_conf_merge_value (conf->upstream.intercept_errors, | |
1402 prev->upstream.intercept_errors, 0); | |
1403 | |
1404 ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, ""); | |
1405 | |
1406 hash.max_size = 512; | |
1407 hash.bucket_size = ngx_align (64, ngx_cacheline_size); | |
1408 hash.name = "uwsgi_hide_headers_hash"; | |
1409 | |
1410 if (ngx_http_upstream_hide_headers_hash (cf, &conf->upstream, | |
1411 &prev->upstream, | |
1412 ngx_http_uwsgi_hide_headers, | |
1413 &hash) != NGX_OK) { | |
1414 return NGX_CONF_ERROR; | |
1415 } | |
1416 | |
1417 if (conf->upstream.upstream == NULL) { | |
1418 conf->upstream.upstream = prev->upstream.upstream; | |
1419 } | |
1420 | |
1421 if (conf->uwsgi_lengths == NULL) { | |
1422 conf->uwsgi_lengths = prev->uwsgi_lengths; | |
1423 conf->uwsgi_values = prev->uwsgi_values; | |
1424 } | |
1425 | |
1426 if (conf->modifier1 == 0) { | |
1427 conf->modifier1 = prev->modifier1; | |
1428 } | |
1429 | |
1430 if (conf->modifier2 == 0) { | |
1431 conf->modifier2 = prev->modifier2; | |
1432 } | |
1433 | |
1434 if (conf->params_source == NULL) { | |
1435 conf->flushes = prev->flushes; | |
1436 conf->params_len = prev->params_len; | |
1437 conf->params = prev->params; | |
1438 conf->params_source = prev->params_source; | |
1439 | |
1440 if (conf->params_source == NULL) { | |
1441 return NGX_CONF_OK; | |
1442 } | |
1443 } | |
1444 | |
1445 conf->params_len = ngx_array_create (cf->pool, 64, 1); | |
1446 if (conf->params_len == NULL) { | |
1447 return NGX_CONF_ERROR; | |
1448 } | |
1449 | |
1450 conf->params = ngx_array_create (cf->pool, 512, 1); | |
1451 if (conf->params == NULL) { | |
1452 return NGX_CONF_ERROR; | |
1453 } | |
1454 | |
1455 src = conf->params_source->elts; | |
1456 for (i = 0; i < conf->params_source->nelts; i++) { | |
1457 | |
1458 if (ngx_http_script_variables_count (&src[i].value) == 0) { | |
1459 copy = ngx_array_push_n (conf->params_len, | |
1460 sizeof (ngx_http_script_copy_code_t)); | |
1461 if (copy == NULL) { | |
1462 return NGX_CONF_ERROR; | |
1463 } | |
1464 | |
1465 copy->code = (ngx_http_script_code_pt) | |
1466 ngx_http_script_copy_len_code; | |
1467 copy->len = src[i].key.len; | |
1468 | |
1469 | |
1470 copy = ngx_array_push_n (conf->params_len, | |
1471 sizeof (ngx_http_script_copy_code_t)); | |
1472 if (copy == NULL) { | |
1473 return NGX_CONF_ERROR; | |
1474 } | |
1475 | |
1476 copy->code = (ngx_http_script_code_pt) | |
1477 ngx_http_script_copy_len_code; | |
1478 copy->len = src[i].value.len; | |
1479 | |
1480 | |
1481 size = (sizeof (ngx_http_script_copy_code_t) | |
1482 + src[i].key.len + src[i].value.len | |
1483 + sizeof (uintptr_t) - 1) & ~(sizeof (uintptr_t) - 1); | |
1484 | |
1485 copy = ngx_array_push_n (conf->params, size); | |
1486 if (copy == NULL) { | |
1487 return NGX_CONF_ERROR; | |
1488 } | |
1489 | |
1490 copy->code = ngx_http_script_copy_code; | |
1491 copy->len = src[i].key.len + src[i].value.len; | |
1492 | |
1493 p = (u_char *) copy + sizeof (ngx_http_script_copy_code_t); | |
1494 | |
1495 p = ngx_cpymem (p, src[i].key.data, src[i].key.len); | |
1496 ngx_memcpy (p, src[i].value.data, src[i].value.len); | |
1497 | |
1498 } | |
1499 else { | |
1500 copy = ngx_array_push_n (conf->params_len, | |
1501 sizeof (ngx_http_script_copy_code_t)); | |
1502 if (copy == NULL) { | |
1503 return NGX_CONF_ERROR; | |
1504 } | |
1505 | |
1506 copy->code = (ngx_http_script_code_pt) | |
1507 ngx_http_script_copy_len_code; | |
1508 copy->len = src[i].key.len; | |
1509 | |
1510 | |
1511 size = (sizeof (ngx_http_script_copy_code_t) | |
1512 + src[i].key.len + sizeof (uintptr_t) - 1) | |
1513 & ~(sizeof (uintptr_t) - 1); | |
1514 | |
1515 copy = ngx_array_push_n (conf->params, size); | |
1516 if (copy == NULL) { | |
1517 return NGX_CONF_ERROR; | |
1518 } | |
1519 | |
1520 copy->code = ngx_http_script_copy_code; | |
1521 copy->len = src[i].key.len; | |
1522 | |
1523 p = (u_char *) copy + sizeof (ngx_http_script_copy_code_t); | |
1524 ngx_memcpy (p, src[i].key.data, src[i].key.len); | |
1525 | |
1526 | |
1527 ngx_memzero (&sc, sizeof (ngx_http_script_compile_t)); | |
1528 | |
1529 sc.cf = cf; | |
1530 sc.source = &src[i].value; | |
1531 sc.flushes = &conf->flushes; | |
1532 sc.lengths = &conf->params_len; | |
1533 sc.values = &conf->params; | |
1534 | |
1535 if (ngx_http_script_compile (&sc) != NGX_OK) { | |
1536 return NGX_CONF_ERROR; | |
1537 } | |
1538 } | |
1539 | |
1540 code = ngx_array_push_n (conf->params_len, sizeof (uintptr_t)); | |
1541 if (code == NULL) { | |
1542 return NGX_CONF_ERROR; | |
1543 } | |
1544 | |
1545 *code = (uintptr_t) NULL; | |
1546 | |
1547 | |
1548 code = ngx_array_push_n (conf->params, sizeof (uintptr_t)); | |
1549 if (code == NULL) { | |
1550 return NGX_CONF_ERROR; | |
1551 } | |
1552 | |
1553 *code = (uintptr_t) NULL; | |
1554 } | |
1555 | |
1556 code = ngx_array_push_n (conf->params_len, sizeof (uintptr_t)); | |
1557 if (code == NULL) { | |
1558 return NGX_CONF_ERROR; | |
1559 } | |
1560 | |
1561 *code = (uintptr_t) NULL; | |
1562 | |
1563 return NGX_CONF_OK; | |
1564 } | |
1565 | |
1566 | |
1567 static char * | |
1568 ngx_http_uwsgi_pass (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) | |
1569 { | |
1570 ngx_http_uwsgi_loc_conf_t *uwcf = conf; | |
1571 | |
1572 ngx_url_t u; | |
1573 ngx_str_t *value, *url; | |
1574 ngx_uint_t n; | |
1575 ngx_http_core_loc_conf_t *clcf; | |
1576 ngx_http_script_compile_t sc; | |
1577 | |
1578 if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) { | |
1579 return "is duplicate"; | |
1580 } | |
1581 | |
1582 clcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module); | |
1583 clcf->handler = ngx_http_uwsgi_handler; | |
1584 | |
1585 value = cf->args->elts; | |
1586 | |
1587 url = &value[1]; | |
1588 | |
1589 n = ngx_http_script_variables_count (url); | |
1590 | |
1591 if (n) { | |
1592 | |
1593 ngx_memzero (&sc, sizeof (ngx_http_script_compile_t)); | |
1594 | |
1595 sc.cf = cf; | |
1596 sc.source = url; | |
1597 sc.lengths = &uwcf->uwsgi_lengths; | |
1598 sc.values = &uwcf->uwsgi_values; | |
1599 sc.variables = n; | |
1600 sc.complete_lengths = 1; | |
1601 sc.complete_values = 1; | |
1602 | |
1603 if (ngx_http_script_compile (&sc) != NGX_OK) { | |
1604 return NGX_CONF_ERROR; | |
1605 } | |
1606 | |
1607 return NGX_CONF_OK; | |
1608 } | |
1609 | |
1610 ngx_memzero (&u, sizeof (ngx_url_t)); | |
1611 | |
1612 u.url = value[1]; | |
1613 u.no_resolve = 1; | |
1614 | |
1615 uwcf->upstream.upstream = ngx_http_upstream_add (cf, &u, 0); | |
1616 if (uwcf->upstream.upstream == NULL) { | |
1617 return NGX_CONF_ERROR; | |
1618 } | |
1619 | |
1620 if (clcf->name.data[clcf->name.len - 1] == '/') { | |
1621 clcf->auto_redirect = 1; | |
1622 } | |
1623 | |
1624 return NGX_CONF_OK; | |
1625 } | |
1626 | |
1627 static char * | |
1628 ngx_http_uwsgi_modifier1 (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) | |
1629 { | |
1630 ngx_http_uwsgi_loc_conf_t *uwcf = conf; | |
1631 ngx_str_t *value; | |
1632 | |
1633 value = cf->args->elts; | |
1634 | |
1635 uwcf->modifier1 = (u_char) ngx_atoi (value[1].data, value[1].len); | |
1636 | |
1637 return NGX_CONF_OK; | |
1638 } | |
1639 | |
1640 static char * | |
1641 ngx_http_uwsgi_modifier2 (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) | |
1642 { | |
1643 ngx_http_uwsgi_loc_conf_t *uwcf = conf; | |
1644 | |
1645 ngx_str_t *value; | |
1646 | |
1647 value = cf->args->elts; | |
1648 | |
1649 uwcf->modifier2 = (u_char) ngx_atoi (value[1].data, value[1].len); | |
1650 | |
1651 | |
1652 return NGX_CONF_OK; | |
1653 } |