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