1
2 /*
3 * Copyright (C) Unbit S.a.s. 2009-2010
4 * Copyright (C) 2008 Manlio Perillo ([email protected])
5 * Copyright (C) Igor Sysoev
6 * Copyright (C) Nginx, Inc.
7 */
8
9
10 #include <ngx_config.h>
11 #include <ngx_core.h>
12 #include <ngx_http.h>
13
14
15 typedef struct {
16 ngx_array_t caches; /* ngx_http_file_cache_t * */
17 } ngx_http_uwsgi_main_conf_t;
18
19
20 typedef struct {
21 ngx_array_t *flushes;
22 ngx_array_t *lengths;
23 ngx_array_t *values;
24 ngx_uint_t number;
25 ngx_hash_t hash;
26 } ngx_http_uwsgi_params_t;
27
28
29 typedef struct {
30 ngx_http_upstream_conf_t upstream;
31
32 ngx_http_uwsgi_params_t params;
33 #if (NGX_HTTP_CACHE)
34 ngx_http_uwsgi_params_t params_cache;
35 #endif
36 ngx_array_t *params_source;
37
38 ngx_array_t *uwsgi_lengths;
39 ngx_array_t *uwsgi_values;
40
41 #if (NGX_HTTP_CACHE)
42 ngx_http_complex_value_t cache_key;
43 #endif
44
45 ngx_str_t uwsgi_string;
46
47 ngx_uint_t modifier1;
48 ngx_uint_t modifier2;
49
50 #if (NGX_HTTP_SSL)
51 ngx_uint_t ssl;
52 ngx_uint_t ssl_protocols;
53 ngx_str_t ssl_ciphers;
54 ngx_uint_t ssl_verify_depth;
55 ngx_str_t ssl_trusted_certificate;
56 ngx_str_t ssl_crl;
57 ngx_str_t ssl_certificate;
58 ngx_str_t ssl_certificate_key;
59 ngx_array_t *ssl_passwords;
60 #endif
61 } ngx_http_uwsgi_loc_conf_t;
62
63
64 static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r,
65 ngx_http_uwsgi_loc_conf_t *uwcf);
66 static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
67 static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
68 static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
69 static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
70 static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
71 static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
72 ngx_int_t rc);
73
74 static void *ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf);
75 static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
76 static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
77 void *child);
78 static ngx_int_t ngx_http_uwsgi_init_params(ngx_conf_t *cf,
79 ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_params_t *params,
80 ngx_keyval_t *default_params);
81
82 static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
83 void *conf);
84 static char *ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
85 void *conf);
86
87 #if (NGX_HTTP_CACHE)
88 static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r);
89 static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
90 void *conf);
91 static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
92 void *conf);
93 #endif
94
95 #if (NGX_HTTP_SSL)
96 static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
97 ngx_command_t *cmd, void *conf);
98 static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
99 ngx_http_uwsgi_loc_conf_t *uwcf);
100 #endif
101
102
103 static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = {
104 ngx_conf_check_num_bounds, 0, 255
105 };
106
107
108 static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
109 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
110 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
111 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
112 { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
113 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
114 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
115 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
116 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
117 { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
118 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
119 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
120 { ngx_null_string, 0 }
121 };
122
123
124 #if (NGX_HTTP_SSL)
125
126 static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
127 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
128 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
129 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
130 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
131 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
132 { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
133 { ngx_null_string, 0 }
134 };
135
136 #endif
137
138
139 ngx_module_t ngx_http_uwsgi_module;
140
141
142 static ngx_command_t ngx_http_uwsgi_commands[] = {
143
144 { ngx_string("uwsgi_pass"),
145 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
146 ngx_http_uwsgi_pass,
147 NGX_HTTP_LOC_CONF_OFFSET,
148 0,
149 NULL },
150
151 { ngx_string("uwsgi_modifier1"),
152 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
153 ngx_conf_set_num_slot,
154 NGX_HTTP_LOC_CONF_OFFSET,
155 offsetof(ngx_http_uwsgi_loc_conf_t, modifier1),
156 &ngx_http_uwsgi_modifier_bounds },
157
158 { ngx_string("uwsgi_modifier2"),
159 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
160 ngx_conf_set_num_slot,
161 NGX_HTTP_LOC_CONF_OFFSET,
162 offsetof(ngx_http_uwsgi_loc_conf_t, modifier2),
163 &ngx_http_uwsgi_modifier_bounds },
164
165 { ngx_string("uwsgi_store"),
166 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
167 ngx_http_uwsgi_store,
168 NGX_HTTP_LOC_CONF_OFFSET,
169 0,
170 NULL },
171
172 { ngx_string("uwsgi_store_access"),
173 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
174 ngx_conf_set_access_slot,
175 NGX_HTTP_LOC_CONF_OFFSET,
176 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.store_access),
177 NULL },
178
179 { ngx_string("uwsgi_buffering"),
180 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
181 ngx_conf_set_flag_slot,
182 NGX_HTTP_LOC_CONF_OFFSET,
183 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffering),
184 NULL },
185
186 { ngx_string("uwsgi_request_buffering"),
187 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
188 ngx_conf_set_flag_slot,
189 NGX_HTTP_LOC_CONF_OFFSET,
190 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.request_buffering),
191 NULL },
192
193 { ngx_string("uwsgi_ignore_client_abort"),
194 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
195 ngx_conf_set_flag_slot,
196 NGX_HTTP_LOC_CONF_OFFSET,
197 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort),
198 NULL },
199
200 { ngx_string("uwsgi_bind"),
201 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
202 ngx_http_upstream_bind_set_slot,
203 NGX_HTTP_LOC_CONF_OFFSET,
204 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.local),
205 NULL },
206
207 { ngx_string("uwsgi_socket_keepalive"),
208 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
209 ngx_conf_set_flag_slot,
210 NGX_HTTP_LOC_CONF_OFFSET,
211 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.socket_keepalive),
212 NULL },
213
214 { ngx_string("uwsgi_connect_timeout"),
215 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
216 ngx_conf_set_msec_slot,
217 NGX_HTTP_LOC_CONF_OFFSET,
218 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout),
219 NULL },
220
221 { ngx_string("uwsgi_send_timeout"),
222 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
223 ngx_conf_set_msec_slot,
224 NGX_HTTP_LOC_CONF_OFFSET,
225 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.send_timeout),
226 NULL },
227
228 { ngx_string("uwsgi_buffer_size"),
229 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
230 ngx_conf_set_size_slot,
231 NGX_HTTP_LOC_CONF_OFFSET,
232 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffer_size),
233 NULL },
234
235 { ngx_string("uwsgi_pass_request_headers"),
236 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
237 ngx_conf_set_flag_slot,
238 NGX_HTTP_LOC_CONF_OFFSET,
239 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers),
240 NULL },
241
242 { ngx_string("uwsgi_pass_request_body"),
243 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
244 ngx_conf_set_flag_slot,
245 NGX_HTTP_LOC_CONF_OFFSET,
246 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body),
247 NULL },
248
249 { ngx_string("uwsgi_intercept_errors"),
250 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
251 ngx_conf_set_flag_slot,
252 NGX_HTTP_LOC_CONF_OFFSET,
253 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors),
254 NULL },
255
256 { ngx_string("uwsgi_read_timeout"),
257 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
258 ngx_conf_set_msec_slot,
259 NGX_HTTP_LOC_CONF_OFFSET,
260 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.read_timeout),
261 NULL },
262
263 { ngx_string("uwsgi_buffers"),
264 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
265 ngx_conf_set_bufs_slot,
266 NGX_HTTP_LOC_CONF_OFFSET,
267 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.bufs),
268 NULL },
269
270 { ngx_string("uwsgi_busy_buffers_size"),
271 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
272 ngx_conf_set_size_slot,
273 NGX_HTTP_LOC_CONF_OFFSET,
274 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf),
275 NULL },
276
277 { ngx_string("uwsgi_force_ranges"),
278 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
279 ngx_conf_set_flag_slot,
280 NGX_HTTP_LOC_CONF_OFFSET,
281 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.force_ranges),
282 NULL },
283
284 { ngx_string("uwsgi_limit_rate"),
285 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
286 ngx_conf_set_size_slot,
287 NGX_HTTP_LOC_CONF_OFFSET,
288 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.limit_rate),
289 NULL },
290
291 #if (NGX_HTTP_CACHE)
292
293 { ngx_string("uwsgi_cache"),
294 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
295 ngx_http_uwsgi_cache,
296 NGX_HTTP_LOC_CONF_OFFSET,
297 0,
298 NULL },
299
300 { ngx_string("uwsgi_cache_key"),
301 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
302 ngx_http_uwsgi_cache_key,
303 NGX_HTTP_LOC_CONF_OFFSET,
304 0,
305 NULL },
306
307 { ngx_string("uwsgi_cache_path"),
308 NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
309 ngx_http_file_cache_set_slot,
310 NGX_HTTP_MAIN_CONF_OFFSET,
311 offsetof(ngx_http_uwsgi_main_conf_t, caches),
312 &ngx_http_uwsgi_module },
313
314 { ngx_string("uwsgi_cache_bypass"),
315 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
316 ngx_http_set_predicate_slot,
317 NGX_HTTP_LOC_CONF_OFFSET,
318 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
319 NULL },
320
321 { ngx_string("uwsgi_no_cache"),
322 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
323 ngx_http_set_predicate_slot,
324 NGX_HTTP_LOC_CONF_OFFSET,
325 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
326 NULL },
327
328 { ngx_string("uwsgi_cache_valid"),
329 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
330 ngx_http_file_cache_valid_set_slot,
331 NGX_HTTP_LOC_CONF_OFFSET,
332 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_valid),
333 NULL },
334
335 { ngx_string("uwsgi_cache_min_uses"),
336 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
337 ngx_conf_set_num_slot,
338 NGX_HTTP_LOC_CONF_OFFSET,
339 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses),
340 NULL },
341
342 { ngx_string("uwsgi_cache_max_range_offset"),
343 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
344 ngx_conf_set_off_slot,
345 NGX_HTTP_LOC_CONF_OFFSET,
346 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_max_range_offset),
347 NULL },
348
349 { ngx_string("uwsgi_cache_use_stale"),
350 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
351 ngx_conf_set_bitmask_slot,
352 NGX_HTTP_LOC_CONF_OFFSET,
353 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_use_stale),
354 &ngx_http_uwsgi_next_upstream_masks },
355
356 { ngx_string("uwsgi_cache_methods"),
357 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
358 ngx_conf_set_bitmask_slot,
359 NGX_HTTP_LOC_CONF_OFFSET,
360 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
361 &ngx_http_upstream_cache_method_mask },
362
363 { ngx_string("uwsgi_cache_lock"),
364 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
365 ngx_conf_set_flag_slot,
366 NGX_HTTP_LOC_CONF_OFFSET,
367 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
368 NULL },
369
370 { ngx_string("uwsgi_cache_lock_timeout"),
371 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
372 ngx_conf_set_msec_slot,
373 NGX_HTTP_LOC_CONF_OFFSET,
374 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
375 NULL },
376
377 { ngx_string("uwsgi_cache_lock_age"),
378 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
379 ngx_conf_set_msec_slot,
380 NGX_HTTP_LOC_CONF_OFFSET,
381 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_age),
382 NULL },
383
384 { ngx_string("uwsgi_cache_revalidate"),
385 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
386 ngx_conf_set_flag_slot,
387 NGX_HTTP_LOC_CONF_OFFSET,
388 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
389 NULL },
390
391 { ngx_string("uwsgi_cache_background_update"),
392 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
393 ngx_conf_set_flag_slot,
394 NGX_HTTP_LOC_CONF_OFFSET,
395 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update),
396 NULL },
397
398 #endif
399
400 { ngx_string("uwsgi_temp_path"),
401 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
402 ngx_conf_set_path_slot,
403 NGX_HTTP_LOC_CONF_OFFSET,
404 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_path),
405 NULL },
406
407 { ngx_string("uwsgi_max_temp_file_size"),
408 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
409 ngx_conf_set_size_slot,
410 NGX_HTTP_LOC_CONF_OFFSET,
411 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf),
412 NULL },
413
414 { ngx_string("uwsgi_temp_file_write_size"),
415 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
416 ngx_conf_set_size_slot,
417 NGX_HTTP_LOC_CONF_OFFSET,
418 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf),
419 NULL },
420
421 { ngx_string("uwsgi_next_upstream"),
422 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
423 ngx_conf_set_bitmask_slot,
424 NGX_HTTP_LOC_CONF_OFFSET,
425 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream),
426 &ngx_http_uwsgi_next_upstream_masks },
427
428 { ngx_string("uwsgi_next_upstream_tries"),
429 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
430 ngx_conf_set_num_slot,
431 NGX_HTTP_LOC_CONF_OFFSET,
432 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries),
433 NULL },
434
435 { ngx_string("uwsgi_next_upstream_timeout"),
436 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
437 ngx_conf_set_msec_slot,
438 NGX_HTTP_LOC_CONF_OFFSET,
439 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout),
440 NULL },
441
442 { ngx_string("uwsgi_param"),
443 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
444 ngx_http_upstream_param_set_slot,
445 NGX_HTTP_LOC_CONF_OFFSET,
446 offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
447 NULL },
448
449 { ngx_string("uwsgi_string"),
450 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
451 ngx_conf_set_str_slot,
452 NGX_HTTP_LOC_CONF_OFFSET,
453 offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
454 NULL },
455
456 { ngx_string("uwsgi_pass_header"),
457 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
458 ngx_conf_set_str_array_slot,
459 NGX_HTTP_LOC_CONF_OFFSET,
460 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
461 NULL },
462
463 { ngx_string("uwsgi_hide_header"),
464 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
465 ngx_conf_set_str_array_slot,
466 NGX_HTTP_LOC_CONF_OFFSET,
467 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
468 NULL },
469
470 { ngx_string("uwsgi_ignore_headers"),
471 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
472 ngx_conf_set_bitmask_slot,
473 NGX_HTTP_LOC_CONF_OFFSET,
474 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
475 &ngx_http_upstream_ignore_headers_masks },
476
477 #if (NGX_HTTP_SSL)
478
479 { ngx_string("uwsgi_ssl_session_reuse"),
480 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
481 ngx_conf_set_flag_slot,
482 NGX_HTTP_LOC_CONF_OFFSET,
483 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
484 NULL },
485
486 { ngx_string("uwsgi_ssl_protocols"),
487 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
488 ngx_conf_set_bitmask_slot,
489 NGX_HTTP_LOC_CONF_OFFSET,
490 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
491 &ngx_http_uwsgi_ssl_protocols },
492
493 { ngx_string("uwsgi_ssl_ciphers"),
494 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
495 ngx_conf_set_str_slot,
496 NGX_HTTP_LOC_CONF_OFFSET,
497 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
498 NULL },
499
500 { ngx_string("uwsgi_ssl_name"),
501 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
502 ngx_http_set_complex_value_slot,
503 NGX_HTTP_LOC_CONF_OFFSET,
504 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_name),
505 NULL },
506
507 { ngx_string("uwsgi_ssl_server_name"),
508 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
509 ngx_conf_set_flag_slot,
510 NGX_HTTP_LOC_CONF_OFFSET,
511 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_server_name),
512 NULL },
513
514 { ngx_string("uwsgi_ssl_verify"),
515 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
516 ngx_conf_set_flag_slot,
517 NGX_HTTP_LOC_CONF_OFFSET,
518 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_verify),
519 NULL },
520
521 { ngx_string("uwsgi_ssl_verify_depth"),
522 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
523 ngx_conf_set_num_slot,
524 NGX_HTTP_LOC_CONF_OFFSET,
525 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_verify_depth),
526 NULL },
527
528 { ngx_string("uwsgi_ssl_trusted_certificate"),
529 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
530 ngx_conf_set_str_slot,
531 NGX_HTTP_LOC_CONF_OFFSET,
532 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_trusted_certificate),
533 NULL },
534
535 { ngx_string("uwsgi_ssl_crl"),
536 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
537 ngx_conf_set_str_slot,
538 NGX_HTTP_LOC_CONF_OFFSET,
539 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_crl),
540 NULL },
541
542 { ngx_string("uwsgi_ssl_certificate"),
543 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
544 ngx_conf_set_str_slot,
545 NGX_HTTP_LOC_CONF_OFFSET,
546 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate),
547 NULL },
548
549 { ngx_string("uwsgi_ssl_certificate_key"),
550 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
551 ngx_conf_set_str_slot,
552 NGX_HTTP_LOC_CONF_OFFSET,
553 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key),
554 NULL },
555
556 { ngx_string("uwsgi_ssl_password_file"),
557 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
558 ngx_http_uwsgi_ssl_password_file,
559 NGX_HTTP_LOC_CONF_OFFSET,
560 0,
561 NULL },
562
563 #endif
564
565 ngx_null_command
566 };
567
568
569 static ngx_http_module_t ngx_http_uwsgi_module_ctx = {
570 NULL, /* preconfiguration */
571 NULL, /* postconfiguration */
572
573 ngx_http_uwsgi_create_main_conf, /* create main configuration */
574 NULL, /* init main configuration */
575
576 NULL, /* create server configuration */
577 NULL, /* merge server configuration */
578
579 ngx_http_uwsgi_create_loc_conf, /* create location configuration */
580 ngx_http_uwsgi_merge_loc_conf /* merge location configuration */
581 };
582
583
584 ngx_module_t ngx_http_uwsgi_module = {
585 NGX_MODULE_V1,
586 &ngx_http_uwsgi_module_ctx, /* module context */
587 ngx_http_uwsgi_commands, /* module directives */
588 NGX_HTTP_MODULE, /* module type */
589 NULL, /* init master */
590 NULL, /* init module */
591 NULL, /* init process */
592 NULL, /* init thread */
593 NULL, /* exit thread */
594 NULL, /* exit process */
595 NULL, /* exit master */
596 NGX_MODULE_V1_PADDING
597 };
598
599
600 static ngx_str_t ngx_http_uwsgi_hide_headers[] = {
601 ngx_string("X-Accel-Expires"),
602 ngx_string("X-Accel-Redirect"),
603 ngx_string("X-Accel-Limit-Rate"),
604 ngx_string("X-Accel-Buffering"),
605 ngx_string("X-Accel-Charset"),
606 ngx_null_string
607 };
608
609
610 #if (NGX_HTTP_CACHE)
611
612 static ngx_keyval_t ngx_http_uwsgi_cache_headers[] = {
613 { ngx_string("HTTP_IF_MODIFIED_SINCE"),
614 ngx_string("$upstream_cache_last_modified") },
615 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
616 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
617 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
618 { ngx_string("HTTP_RANGE"), ngx_string("") },
619 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
620 { ngx_null_string, ngx_null_string }
621 };
622
623 #endif
624
625
626 static ngx_path_init_t ngx_http_uwsgi_temp_path = {
627 ngx_string(NGX_HTTP_UWSGI_TEMP_PATH), { 1, 2, 0 }
628 };
629
630
631 static ngx_int_t
ngx_http_uwsgi_handler(ngx_http_request_t * r)632 ngx_http_uwsgi_handler(ngx_http_request_t *r)
633 {
634 ngx_int_t rc;
635 ngx_http_status_t *status;
636 ngx_http_upstream_t *u;
637 ngx_http_uwsgi_loc_conf_t *uwcf;
638 #if (NGX_HTTP_CACHE)
639 ngx_http_uwsgi_main_conf_t *uwmcf;
640 #endif
641
642 if (ngx_http_upstream_create(r) != NGX_OK) {
643 return NGX_HTTP_INTERNAL_SERVER_ERROR;
644 }
645
646 status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
647 if (status == NULL) {
648 return NGX_HTTP_INTERNAL_SERVER_ERROR;
649 }
650
651 ngx_http_set_ctx(r, status, ngx_http_uwsgi_module);
652
653 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
654
655 u = r->upstream;
656
657 if (uwcf->uwsgi_lengths == NULL) {
658
659 #if (NGX_HTTP_SSL)
660 u->ssl = (uwcf->upstream.ssl != NULL);
661
662 if (u->ssl) {
663 ngx_str_set(&u->schema, "suwsgi://");
664
665 } else {
666 ngx_str_set(&u->schema, "uwsgi://");
667 }
668 #else
669 ngx_str_set(&u->schema, "uwsgi://");
670 #endif
671
672 } else {
673 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
674 return NGX_HTTP_INTERNAL_SERVER_ERROR;
675 }
676 }
677
678 u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
679
680 u->conf = &uwcf->upstream;
681
682 #if (NGX_HTTP_CACHE)
683 uwmcf = ngx_http_get_module_main_conf(r, ngx_http_uwsgi_module);
684
685 u->caches = &uwmcf->caches;
686 u->create_key = ngx_http_uwsgi_create_key;
687 #endif
688
689 u->create_request = ngx_http_uwsgi_create_request;
690 u->reinit_request = ngx_http_uwsgi_reinit_request;
691 u->process_header = ngx_http_uwsgi_process_status_line;
692 u->abort_request = ngx_http_uwsgi_abort_request;
693 u->finalize_request = ngx_http_uwsgi_finalize_request;
694 r->state = 0;
695
696 u->buffering = uwcf->upstream.buffering;
697
698 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
699 if (u->pipe == NULL) {
700 return NGX_HTTP_INTERNAL_SERVER_ERROR;
701 }
702
703 u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
704 u->pipe->input_ctx = r;
705
706 if (!uwcf->upstream.request_buffering
707 && uwcf->upstream.pass_request_body
708 && !r->headers_in.chunked)
709 {
710 r->request_body_no_buffering = 1;
711 }
712
713 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
714
715 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
716 return rc;
717 }
718
719 return NGX_DONE;
720 }
721
722
723 static ngx_int_t
ngx_http_uwsgi_eval(ngx_http_request_t * r,ngx_http_uwsgi_loc_conf_t * uwcf)724 ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
725 {
726 size_t add;
727 ngx_url_t url;
728 ngx_http_upstream_t *u;
729
730 ngx_memzero(&url, sizeof(ngx_url_t));
731
732 if (ngx_http_script_run(r, &url.url, uwcf->uwsgi_lengths->elts, 0,
733 uwcf->uwsgi_values->elts)
734 == NULL)
735 {
736 return NGX_ERROR;
737 }
738
739 if (url.url.len > 8
740 && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
741 {
742 add = 8;
743
744 } else if (url.url.len > 9
745 && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
746 {
747
748 #if (NGX_HTTP_SSL)
749 add = 9;
750 r->upstream->ssl = 1;
751 #else
752 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
753 "suwsgi protocol requires SSL support");
754 return NGX_ERROR;
755 #endif
756
757 } else {
758 add = 0;
759 }
760
761 u = r->upstream;
762
763 if (add) {
764 u->schema.len = add;
765 u->schema.data = url.url.data;
766
767 url.url.data += add;
768 url.url.len -= add;
769
770 } else {
771 ngx_str_set(&u->schema, "uwsgi://");
772 }
773
774 url.no_resolve = 1;
775
776 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
777 if (url.err) {
778 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
779 "%s in upstream \"%V\"", url.err, &url.url);
780 }
781
782 return NGX_ERROR;
783 }
784
785 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
786 if (u->resolved == NULL) {
787 return NGX_ERROR;
788 }
789
790 if (url.addrs) {
791 u->resolved->sockaddr = url.addrs[0].sockaddr;
792 u->resolved->socklen = url.addrs[0].socklen;
793 u->resolved->name = url.addrs[0].name;
794 u->resolved->naddrs = 1;
795 }
796
797 u->resolved->host = url.host;
798 u->resolved->port = url.port;
799 u->resolved->no_port = url.no_port;
800
801 return NGX_OK;
802 }
803
804
805 #if (NGX_HTTP_CACHE)
806
807 static ngx_int_t
ngx_http_uwsgi_create_key(ngx_http_request_t * r)808 ngx_http_uwsgi_create_key(ngx_http_request_t *r)
809 {
810 ngx_str_t *key;
811 ngx_http_uwsgi_loc_conf_t *uwcf;
812
813 key = ngx_array_push(&r->cache->keys);
814 if (key == NULL) {
815 return NGX_ERROR;
816 }
817
818 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
819
820 if (ngx_http_complex_value(r, &uwcf->cache_key, key) != NGX_OK) {
821 return NGX_ERROR;
822 }
823
824 return NGX_OK;
825 }
826
827 #endif
828
829
830 static ngx_int_t
ngx_http_uwsgi_create_request(ngx_http_request_t * r)831 ngx_http_uwsgi_create_request(ngx_http_request_t *r)
832 {
833 u_char ch, *lowcase_key;
834 size_t key_len, val_len, len, allocated;
835 ngx_uint_t i, n, hash, skip_empty, header_params;
836 ngx_buf_t *b;
837 ngx_chain_t *cl, *body;
838 ngx_list_part_t *part;
839 ngx_table_elt_t *header, **ignored;
840 ngx_http_uwsgi_params_t *params;
841 ngx_http_script_code_pt code;
842 ngx_http_script_engine_t e, le;
843 ngx_http_uwsgi_loc_conf_t *uwcf;
844 ngx_http_script_len_code_pt lcode;
845
846 len = 0;
847 header_params = 0;
848 ignored = NULL;
849
850 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
851
852 #if (NGX_HTTP_CACHE)
853 params = r->upstream->cacheable ? &uwcf->params_cache : &uwcf->params;
854 #else
855 params = &uwcf->params;
856 #endif
857
858 if (params->lengths) {
859 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
860
861 ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
862 le.flushed = 1;
863
864 le.ip = params->lengths->elts;
865 le.request = r;
866
867 while (*(uintptr_t *) le.ip) {
868
869 lcode = *(ngx_http_script_len_code_pt *) le.ip;
870 key_len = lcode(&le);
871
872 lcode = *(ngx_http_script_len_code_pt *) le.ip;
873 skip_empty = lcode(&le);
874
875 for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
876 lcode = *(ngx_http_script_len_code_pt *) le.ip;
877 }
878 le.ip += sizeof(uintptr_t);
879
880 if (skip_empty && val_len == 0) {
881 continue;
882 }
883
884 len += 2 + key_len + 2 + val_len;
885 }
886 }
887
888 if (uwcf->upstream.pass_request_headers) {
889
890 allocated = 0;
891 lowcase_key = NULL;
892
893 if (params->number) {
894 n = 0;
895 part = &r->headers_in.headers.part;
896
897 while (part) {
898 n += part->nelts;
899 part = part->next;
900 }
901
902 ignored = ngx_palloc(r->pool, n * sizeof(void *));
903 if (ignored == NULL) {
904 return NGX_ERROR;
905 }
906 }
907
908 part = &r->headers_in.headers.part;
909 header = part->elts;
910
911 for (i = 0; /* void */ ; i++) {
912
913 if (i >= part->nelts) {
914 if (part->next == NULL) {
915 break;
916 }
917
918 part = part->next;
919 header = part->elts;
920 i = 0;
921 }
922
923 if (params->number) {
924 if (allocated < header[i].key.len) {
925 allocated = header[i].key.len + 16;
926 lowcase_key = ngx_pnalloc(r->pool, allocated);
927 if (lowcase_key == NULL) {
928 return NGX_ERROR;
929 }
930 }
931
932 hash = 0;
933
934 for (n = 0; n < header[i].key.len; n++) {
935 ch = header[i].key.data[n];
936
937 if (ch >= 'A' && ch <= 'Z') {
938 ch |= 0x20;
939
940 } else if (ch == '-') {
941 ch = '_';
942 }
943
944 hash = ngx_hash(hash, ch);
945 lowcase_key[n] = ch;
946 }
947
948 if (ngx_hash_find(¶ms->hash, hash, lowcase_key, n)) {
949 ignored[header_params++] = &header[i];
950 continue;
951 }
952 }
953
954 len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
955 + 2 + header[i].value.len;
956 }
957 }
958
959 len += uwcf->uwsgi_string.len;
960
961 #if 0
962 /* allow custom uwsgi packet */
963 if (len > 0 && len < 2) {
964 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
965 "uwsgi request is too little: %uz", len);
966 return NGX_ERROR;
967 }
968 #endif
969
970 if (len > 65535) {
971 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
972 "uwsgi request is too big: %uz", len);
973 return NGX_ERROR;
974 }
975
976 b = ngx_create_temp_buf(r->pool, len + 4);
977 if (b == NULL) {
978 return NGX_ERROR;
979 }
980
981 cl = ngx_alloc_chain_link(r->pool);
982 if (cl == NULL) {
983 return NGX_ERROR;
984 }
985
986 cl->buf = b;
987
988 *b->last++ = (u_char) uwcf->modifier1;
989 *b->last++ = (u_char) (len & 0xff);
990 *b->last++ = (u_char) ((len >> 8) & 0xff);
991 *b->last++ = (u_char) uwcf->modifier2;
992
993 if (params->lengths) {
994 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
995
996 e.ip = params->values->elts;
997 e.pos = b->last;
998 e.request = r;
999 e.flushed = 1;
1000
1001 le.ip = params->lengths->elts;
1002
1003 while (*(uintptr_t *) le.ip) {
1004
1005 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1006 key_len = (u_char) lcode(&le);
1007
1008 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1009 skip_empty = lcode(&le);
1010
1011 for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
1012 lcode = *(ngx_http_script_len_code_pt *) le.ip;
1013 }
1014 le.ip += sizeof(uintptr_t);
1015
1016 if (skip_empty && val_len == 0) {
1017 e.skip = 1;
1018
1019 while (*(uintptr_t *) e.ip) {
1020 code = *(ngx_http_script_code_pt *) e.ip;
1021 code((ngx_http_script_engine_t *) &e);
1022 }
1023 e.ip += sizeof(uintptr_t);
1024
1025 e.skip = 0;
1026
1027 continue;
1028 }
1029
1030 *e.pos++ = (u_char) (key_len & 0xff);
1031 *e.pos++ = (u_char) ((key_len >> 8) & 0xff);
1032
1033 code = *(ngx_http_script_code_pt *) e.ip;
1034 code((ngx_http_script_engine_t *) &e);
1035
1036 *e.pos++ = (u_char) (val_len & 0xff);
1037 *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
1038
1039 while (*(uintptr_t *) e.ip) {
1040 code = *(ngx_http_script_code_pt *) e.ip;
1041 code((ngx_http_script_engine_t *) &e);
1042 }
1043
1044 e.ip += sizeof(uintptr_t);
1045
1046 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1047 "uwsgi param: \"%*s: %*s\"",
1048 key_len, e.pos - (key_len + 2 + val_len),
1049 val_len, e.pos - val_len);
1050 }
1051
1052 b->last = e.pos;
1053 }
1054
1055 if (uwcf->upstream.pass_request_headers) {
1056
1057 part = &r->headers_in.headers.part;
1058 header = part->elts;
1059
1060 for (i = 0; /* void */ ; i++) {
1061
1062 if (i >= part->nelts) {
1063 if (part->next == NULL) {
1064 break;
1065 }
1066
1067 part = part->next;
1068 header = part->elts;
1069 i = 0;
1070 }
1071
1072 for (n = 0; n < header_params; n++) {
1073 if (&header[i] == ignored[n]) {
1074 goto next;
1075 }
1076 }
1077
1078 key_len = sizeof("HTTP_") - 1 + header[i].key.len;
1079 *b->last++ = (u_char) (key_len & 0xff);
1080 *b->last++ = (u_char) ((key_len >> 8) & 0xff);
1081
1082 b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
1083 for (n = 0; n < header[i].key.len; n++) {
1084 ch = header[i].key.data[n];
1085
1086 if (ch >= 'a' && ch <= 'z') {
1087 ch &= ~0x20;
1088
1089 } else if (ch == '-') {
1090 ch = '_';
1091 }
1092
1093 *b->last++ = ch;
1094 }
1095
1096 val_len = header[i].value.len;
1097 *b->last++ = (u_char) (val_len & 0xff);
1098 *b->last++ = (u_char) ((val_len >> 8) & 0xff);
1099 b->last = ngx_copy(b->last, header[i].value.data, val_len);
1100
1101 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1102 "uwsgi param: \"%*s: %*s\"",
1103 key_len, b->last - (key_len + 2 + val_len),
1104 val_len, b->last - val_len);
1105 next:
1106
1107 continue;
1108 }
1109 }
1110
1111 b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
1112 uwcf->uwsgi_string.len);
1113
1114 if (r->request_body_no_buffering) {
1115 r->upstream->request_bufs = cl;
1116
1117 } else if (uwcf->upstream.pass_request_body) {
1118 body = r->upstream->request_bufs;
1119 r->upstream->request_bufs = cl;
1120
1121 while (body) {
1122 b = ngx_alloc_buf(r->pool);
1123 if (b == NULL) {
1124 return NGX_ERROR;
1125 }
1126
1127 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
1128
1129 cl->next = ngx_alloc_chain_link(r->pool);
1130 if (cl->next == NULL) {
1131 return NGX_ERROR;
1132 }
1133
1134 cl = cl->next;
1135 cl->buf = b;
1136
1137 body = body->next;
1138 }
1139
1140 } else {
1141 r->upstream->request_bufs = cl;
1142 }
1143
1144 cl->next = NULL;
1145
1146 return NGX_OK;
1147 }
1148
1149
1150 static ngx_int_t
ngx_http_uwsgi_reinit_request(ngx_http_request_t * r)1151 ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
1152 {
1153 ngx_http_status_t *status;
1154
1155 status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
1156
1157 if (status == NULL) {
1158 return NGX_OK;
1159 }
1160
1161 status->code = 0;
1162 status->count = 0;
1163 status->start = NULL;
1164 status->end = NULL;
1165
1166 r->upstream->process_header = ngx_http_uwsgi_process_status_line;
1167 r->state = 0;
1168
1169 return NGX_OK;
1170 }
1171
1172
1173 static ngx_int_t
ngx_http_uwsgi_process_status_line(ngx_http_request_t * r)1174 ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
1175 {
1176 size_t len;
1177 ngx_int_t rc;
1178 ngx_http_status_t *status;
1179 ngx_http_upstream_t *u;
1180
1181 status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
1182
1183 if (status == NULL) {
1184 return NGX_ERROR;
1185 }
1186
1187 u = r->upstream;
1188
1189 rc = ngx_http_parse_status_line(r, &u->buffer, status);
1190
1191 if (rc == NGX_AGAIN) {
1192 return rc;
1193 }
1194
1195 if (rc == NGX_ERROR) {
1196 u->process_header = ngx_http_uwsgi_process_header;
1197 return ngx_http_uwsgi_process_header(r);
1198 }
1199
1200 if (u->state && u->state->status == 0) {
1201 u->state->status = status->code;
1202 }
1203
1204 u->headers_in.status_n = status->code;
1205
1206 len = status->end - status->start;
1207 u->headers_in.status_line.len = len;
1208
1209 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
1210 if (u->headers_in.status_line.data == NULL) {
1211 return NGX_ERROR;
1212 }
1213
1214 ngx_memcpy(u->headers_in.status_line.data, status->start, len);
1215
1216 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1217 "http uwsgi status %ui \"%V\"",
1218 u->headers_in.status_n, &u->headers_in.status_line);
1219
1220 u->process_header = ngx_http_uwsgi_process_header;
1221
1222 return ngx_http_uwsgi_process_header(r);
1223 }
1224
1225
1226 static ngx_int_t
ngx_http_uwsgi_process_header(ngx_http_request_t * r)1227 ngx_http_uwsgi_process_header(ngx_http_request_t *r)
1228 {
1229 ngx_str_t *status_line;
1230 ngx_int_t rc, status;
1231 ngx_table_elt_t *h;
1232 ngx_http_upstream_t *u;
1233 ngx_http_upstream_header_t *hh;
1234 ngx_http_upstream_main_conf_t *umcf;
1235
1236 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1237
1238 for ( ;; ) {
1239
1240 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
1241
1242 if (rc == NGX_OK) {
1243
1244 /* a header line has been parsed successfully */
1245
1246 h = ngx_list_push(&r->upstream->headers_in.headers);
1247 if (h == NULL) {
1248 return NGX_ERROR;
1249 }
1250
1251 h->hash = r->header_hash;
1252
1253 h->key.len = r->header_name_end - r->header_name_start;
1254 h->value.len = r->header_end - r->header_start;
1255
1256 h->key.data = ngx_pnalloc(r->pool,
1257 h->key.len + 1 + h->value.len + 1
1258 + h->key.len);
1259 if (h->key.data == NULL) {
1260 h->hash = 0;
1261 return NGX_ERROR;
1262 }
1263
1264 h->value.data = h->key.data + h->key.len + 1;
1265 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
1266
1267 ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
1268 h->key.data[h->key.len] = '\0';
1269 ngx_memcpy(h->value.data, r->header_start, h->value.len);
1270 h->value.data[h->value.len] = '\0';
1271
1272 if (h->key.len == r->lowcase_index) {
1273 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1274
1275 } else {
1276 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1277 }
1278
1279 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
1280 h->lowcase_key, h->key.len);
1281
1282 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1283 return NGX_ERROR;
1284 }
1285
1286 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1287 "http uwsgi header: \"%V: %V\"", &h->key, &h->value);
1288
1289 continue;
1290 }
1291
1292 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1293
1294 /* a whole header has been parsed successfully */
1295
1296 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1297 "http uwsgi header done");
1298
1299 u = r->upstream;
1300
1301 if (u->headers_in.status_n) {
1302 goto done;
1303 }
1304
1305 if (u->headers_in.status) {
1306 status_line = &u->headers_in.status->value;
1307
1308 status = ngx_atoi(status_line->data, 3);
1309 if (status == NGX_ERROR) {
1310 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1311 "upstream sent invalid status \"%V\"",
1312 status_line);
1313 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1314 }
1315
1316 u->headers_in.status_n = status;
1317 u->headers_in.status_line = *status_line;
1318
1319 } else if (u->headers_in.location) {
1320 u->headers_in.status_n = 302;
1321 ngx_str_set(&u->headers_in.status_line,
1322 "302 Moved Temporarily");
1323
1324 } else {
1325 u->headers_in.status_n = 200;
1326 ngx_str_set(&u->headers_in.status_line, "200 OK");
1327 }
1328
1329 if (u->state && u->state->status == 0) {
1330 u->state->status = u->headers_in.status_n;
1331 }
1332
1333 done:
1334
1335 if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
1336 && r->headers_in.upgrade)
1337 {
1338 u->upgrade = 1;
1339 }
1340
1341 return NGX_OK;
1342 }
1343
1344 if (rc == NGX_AGAIN) {
1345 return NGX_AGAIN;
1346 }
1347
1348 /* there was error while a header line parsing */
1349
1350 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1351 "upstream sent invalid header");
1352
1353 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1354 }
1355 }
1356
1357
1358 static void
ngx_http_uwsgi_abort_request(ngx_http_request_t * r)1359 ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
1360 {
1361 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1362 "abort http uwsgi request");
1363
1364 return;
1365 }
1366
1367
1368 static void
ngx_http_uwsgi_finalize_request(ngx_http_request_t * r,ngx_int_t rc)1369 ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1370 {
1371 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1372 "finalize http uwsgi request");
1373
1374 return;
1375 }
1376
1377
1378 static void *
ngx_http_uwsgi_create_main_conf(ngx_conf_t * cf)1379 ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf)
1380 {
1381 ngx_http_uwsgi_main_conf_t *conf;
1382
1383 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_main_conf_t));
1384 if (conf == NULL) {
1385 return NULL;
1386 }
1387
1388 #if (NGX_HTTP_CACHE)
1389 if (ngx_array_init(&conf->caches, cf->pool, 4,
1390 sizeof(ngx_http_file_cache_t *))
1391 != NGX_OK)
1392 {
1393 return NULL;
1394 }
1395 #endif
1396
1397 return conf;
1398 }
1399
1400
1401 static void *
ngx_http_uwsgi_create_loc_conf(ngx_conf_t * cf)1402 ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
1403 {
1404 ngx_http_uwsgi_loc_conf_t *conf;
1405
1406 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_loc_conf_t));
1407 if (conf == NULL) {
1408 return NULL;
1409 }
1410
1411 conf->modifier1 = NGX_CONF_UNSET_UINT;
1412 conf->modifier2 = NGX_CONF_UNSET_UINT;
1413
1414 conf->upstream.store = NGX_CONF_UNSET;
1415 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
1416 conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
1417 conf->upstream.buffering = NGX_CONF_UNSET;
1418 conf->upstream.request_buffering = NGX_CONF_UNSET;
1419 conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
1420 conf->upstream.force_ranges = NGX_CONF_UNSET;
1421
1422 conf->upstream.local = NGX_CONF_UNSET_PTR;
1423 conf->upstream.socket_keepalive = NGX_CONF_UNSET;
1424
1425 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
1426 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
1427 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
1428 conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
1429
1430 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
1431 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
1432 conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
1433
1434 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
1435 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
1436 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
1437
1438 conf->upstream.pass_request_headers = NGX_CONF_UNSET;
1439 conf->upstream.pass_request_body = NGX_CONF_UNSET;
1440
1441 #if (NGX_HTTP_CACHE)
1442 conf->upstream.cache = NGX_CONF_UNSET;
1443 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
1444 conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
1445 conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
1446 conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
1447 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1448 conf->upstream.cache_lock = NGX_CONF_UNSET;
1449 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
1450 conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
1451 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
1452 conf->upstream.cache_background_update = NGX_CONF_UNSET;
1453 #endif
1454
1455 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
1456 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
1457
1458 conf->upstream.intercept_errors = NGX_CONF_UNSET;
1459
1460 #if (NGX_HTTP_SSL)
1461 conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
1462 conf->upstream.ssl_server_name = NGX_CONF_UNSET;
1463 conf->upstream.ssl_verify = NGX_CONF_UNSET;
1464 conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
1465 conf->ssl_passwords = NGX_CONF_UNSET_PTR;
1466 #endif
1467
1468 /* "uwsgi_cyclic_temp_file" is disabled */
1469 conf->upstream.cyclic_temp_file = 0;
1470
1471 conf->upstream.change_buffering = 1;
1472
1473 ngx_str_set(&conf->upstream.module, "uwsgi");
1474
1475 return conf;
1476 }
1477
1478
1479 static char *
ngx_http_uwsgi_merge_loc_conf(ngx_conf_t * cf,void * parent,void * child)1480 ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1481 {
1482 ngx_http_uwsgi_loc_conf_t *prev = parent;
1483 ngx_http_uwsgi_loc_conf_t *conf = child;
1484
1485 size_t size;
1486 ngx_int_t rc;
1487 ngx_hash_init_t hash;
1488 ngx_http_core_loc_conf_t *clcf;
1489
1490 #if (NGX_HTTP_CACHE)
1491
1492 if (conf->upstream.store > 0) {
1493 conf->upstream.cache = 0;
1494 }
1495
1496 if (conf->upstream.cache > 0) {
1497 conf->upstream.store = 0;
1498 }
1499
1500 #endif
1501
1502 if (conf->upstream.store == NGX_CONF_UNSET) {
1503 ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);
1504
1505 conf->upstream.store_lengths = prev->upstream.store_lengths;
1506 conf->upstream.store_values = prev->upstream.store_values;
1507 }
1508
1509 ngx_conf_merge_uint_value(conf->upstream.store_access,
1510 prev->upstream.store_access, 0600);
1511
1512 ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
1513 prev->upstream.next_upstream_tries, 0);
1514
1515 ngx_conf_merge_value(conf->upstream.buffering,
1516 prev->upstream.buffering, 1);
1517
1518 ngx_conf_merge_value(conf->upstream.request_buffering,
1519 prev->upstream.request_buffering, 1);
1520
1521 ngx_conf_merge_value(conf->upstream.ignore_client_abort,
1522 prev->upstream.ignore_client_abort, 0);
1523
1524 ngx_conf_merge_value(conf->upstream.force_ranges,
1525 prev->upstream.force_ranges, 0);
1526
1527 ngx_conf_merge_ptr_value(conf->upstream.local,
1528 prev->upstream.local, NULL);
1529
1530 ngx_conf_merge_value(conf->upstream.socket_keepalive,
1531 prev->upstream.socket_keepalive, 0);
1532
1533 ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
1534 prev->upstream.connect_timeout, 60000);
1535
1536 ngx_conf_merge_msec_value(conf->upstream.send_timeout,
1537 prev->upstream.send_timeout, 60000);
1538
1539 ngx_conf_merge_msec_value(conf->upstream.read_timeout,
1540 prev->upstream.read_timeout, 60000);
1541
1542 ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
1543 prev->upstream.next_upstream_timeout, 0);
1544
1545 ngx_conf_merge_size_value(conf->upstream.send_lowat,
1546 prev->upstream.send_lowat, 0);
1547
1548 ngx_conf_merge_size_value(conf->upstream.buffer_size,
1549 prev->upstream.buffer_size,
1550 (size_t) ngx_pagesize);
1551
1552 ngx_conf_merge_size_value(conf->upstream.limit_rate,
1553 prev->upstream.limit_rate, 0);
1554
1555
1556 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
1557 8, ngx_pagesize);
1558
1559 if (conf->upstream.bufs.num < 2) {
1560 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1561 "there must be at least 2 \"uwsgi_buffers\"");
1562 return NGX_CONF_ERROR;
1563 }
1564
1565
1566 size = conf->upstream.buffer_size;
1567 if (size < conf->upstream.bufs.size) {
1568 size = conf->upstream.bufs.size;
1569 }
1570
1571
1572 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
1573 prev->upstream.busy_buffers_size_conf,
1574 NGX_CONF_UNSET_SIZE);
1575
1576 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
1577 conf->upstream.busy_buffers_size = 2 * size;
1578 } else {
1579 conf->upstream.busy_buffers_size =
1580 conf->upstream.busy_buffers_size_conf;
1581 }
1582
1583 if (conf->upstream.busy_buffers_size < size) {
1584 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1585 "\"uwsgi_busy_buffers_size\" must be equal to or greater "
1586 "than the maximum of the value of \"uwsgi_buffer_size\" and "
1587 "one of the \"uwsgi_buffers\"");
1588
1589 return NGX_CONF_ERROR;
1590 }
1591
1592 if (conf->upstream.busy_buffers_size
1593 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
1594 {
1595 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1596 "\"uwsgi_busy_buffers_size\" must be less than "
1597 "the size of all \"uwsgi_buffers\" minus one buffer");
1598
1599 return NGX_CONF_ERROR;
1600 }
1601
1602
1603 ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
1604 prev->upstream.temp_file_write_size_conf,
1605 NGX_CONF_UNSET_SIZE);
1606
1607 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
1608 conf->upstream.temp_file_write_size = 2 * size;
1609 } else {
1610 conf->upstream.temp_file_write_size =
1611 conf->upstream.temp_file_write_size_conf;
1612 }
1613
1614 if (conf->upstream.temp_file_write_size < size) {
1615 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1616 "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
1617 "the maximum of the value of \"uwsgi_buffer_size\" and "
1618 "one of the \"uwsgi_buffers\"");
1619
1620 return NGX_CONF_ERROR;
1621 }
1622
1623
1624 ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
1625 prev->upstream.max_temp_file_size_conf,
1626 NGX_CONF_UNSET_SIZE);
1627
1628 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
1629 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
1630 } else {
1631 conf->upstream.max_temp_file_size =
1632 conf->upstream.max_temp_file_size_conf;
1633 }
1634
1635 if (conf->upstream.max_temp_file_size != 0
1636 && conf->upstream.max_temp_file_size < size)
1637 {
1638 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1639 "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
1640 "temporary files usage or must be equal to or greater than "
1641 "the maximum of the value of \"uwsgi_buffer_size\" and "
1642 "one of the \"uwsgi_buffers\"");
1643
1644 return NGX_CONF_ERROR;
1645 }
1646
1647
1648 ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
1649 prev->upstream.ignore_headers,
1650 NGX_CONF_BITMASK_SET);
1651
1652
1653 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
1654 prev->upstream.next_upstream,
1655 (NGX_CONF_BITMASK_SET
1656 |NGX_HTTP_UPSTREAM_FT_ERROR
1657 |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
1658
1659 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
1660 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
1661 |NGX_HTTP_UPSTREAM_FT_OFF;
1662 }
1663
1664 if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
1665 prev->upstream.temp_path,
1666 &ngx_http_uwsgi_temp_path)
1667 != NGX_OK)
1668 {
1669 return NGX_CONF_ERROR;
1670 }
1671
1672 #if (NGX_HTTP_CACHE)
1673
1674 if (conf->upstream.cache == NGX_CONF_UNSET) {
1675 ngx_conf_merge_value(conf->upstream.cache,
1676 prev->upstream.cache, 0);
1677
1678 conf->upstream.cache_zone = prev->upstream.cache_zone;
1679 conf->upstream.cache_value = prev->upstream.cache_value;
1680 }
1681
1682 if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
1683 ngx_shm_zone_t *shm_zone;
1684
1685 shm_zone = conf->upstream.cache_zone;
1686
1687 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1688 "\"uwsgi_cache\" zone \"%V\" is unknown",
1689 &shm_zone->shm.name);
1690
1691 return NGX_CONF_ERROR;
1692 }
1693
1694 ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
1695 prev->upstream.cache_min_uses, 1);
1696
1697 ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
1698 prev->upstream.cache_max_range_offset,
1699 NGX_MAX_OFF_T_VALUE);
1700
1701 ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
1702 prev->upstream.cache_use_stale,
1703 (NGX_CONF_BITMASK_SET
1704 |NGX_HTTP_UPSTREAM_FT_OFF));
1705
1706 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
1707 conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
1708 |NGX_HTTP_UPSTREAM_FT_OFF;
1709 }
1710
1711 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
1712 conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
1713 }
1714
1715 if (conf->upstream.cache_methods == 0) {
1716 conf->upstream.cache_methods = prev->upstream.cache_methods;
1717 }
1718
1719 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
1720
1721 ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
1722 prev->upstream.cache_bypass, NULL);
1723
1724 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
1725 prev->upstream.no_cache, NULL);
1726
1727 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
1728 prev->upstream.cache_valid, NULL);
1729
1730 if (conf->cache_key.value.data == NULL) {
1731 conf->cache_key = prev->cache_key;
1732 }
1733
1734 if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
1735 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1736 "no \"uwsgi_cache_key\" for \"uwsgi_cache\"");
1737 }
1738
1739 ngx_conf_merge_value(conf->upstream.cache_lock,
1740 prev->upstream.cache_lock, 0);
1741
1742 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
1743 prev->upstream.cache_lock_timeout, 5000);
1744
1745 ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
1746 prev->upstream.cache_lock_age, 5000);
1747
1748 ngx_conf_merge_value(conf->upstream.cache_revalidate,
1749 prev->upstream.cache_revalidate, 0);
1750
1751 ngx_conf_merge_value(conf->upstream.cache_background_update,
1752 prev->upstream.cache_background_update, 0);
1753
1754 #endif
1755
1756 ngx_conf_merge_value(conf->upstream.pass_request_headers,
1757 prev->upstream.pass_request_headers, 1);
1758 ngx_conf_merge_value(conf->upstream.pass_request_body,
1759 prev->upstream.pass_request_body, 1);
1760
1761 ngx_conf_merge_value(conf->upstream.intercept_errors,
1762 prev->upstream.intercept_errors, 0);
1763
1764 #if (NGX_HTTP_SSL)
1765
1766 ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
1767 prev->upstream.ssl_session_reuse, 1);
1768
1769 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
1770 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
1771 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
1772
1773 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
1774 "DEFAULT");
1775
1776 if (conf->upstream.ssl_name == NULL) {
1777 conf->upstream.ssl_name = prev->upstream.ssl_name;
1778 }
1779
1780 ngx_conf_merge_value(conf->upstream.ssl_server_name,
1781 prev->upstream.ssl_server_name, 0);
1782 ngx_conf_merge_value(conf->upstream.ssl_verify,
1783 prev->upstream.ssl_verify, 0);
1784 ngx_conf_merge_uint_value(conf->ssl_verify_depth,
1785 prev->ssl_verify_depth, 1);
1786 ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
1787 prev->ssl_trusted_certificate, "");
1788 ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
1789
1790 ngx_conf_merge_str_value(conf->ssl_certificate,
1791 prev->ssl_certificate, "");
1792 ngx_conf_merge_str_value(conf->ssl_certificate_key,
1793 prev->ssl_certificate_key, "");
1794 ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
1795
1796 if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
1797 return NGX_CONF_ERROR;
1798 }
1799
1800 #endif
1801
1802 ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
1803
1804 hash.max_size = 512;
1805 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
1806 hash.name = "uwsgi_hide_headers_hash";
1807
1808 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
1809 &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
1810 != NGX_OK)
1811 {
1812 return NGX_CONF_ERROR;
1813 }
1814
1815 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
1816
1817 if (clcf->noname
1818 && conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL)
1819 {
1820 conf->upstream.upstream = prev->upstream.upstream;
1821
1822 conf->uwsgi_lengths = prev->uwsgi_lengths;
1823 conf->uwsgi_values = prev->uwsgi_values;
1824
1825 #if (NGX_HTTP_SSL)
1826 conf->upstream.ssl = prev->upstream.ssl;
1827 #endif
1828 }
1829
1830 if (clcf->lmt_excpt && clcf->handler == NULL
1831 && (conf->upstream.upstream || conf->uwsgi_lengths))
1832 {
1833 clcf->handler = ngx_http_uwsgi_handler;
1834 }
1835
1836 ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
1837 ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);
1838
1839 if (conf->params_source == NULL) {
1840 conf->params = prev->params;
1841 #if (NGX_HTTP_CACHE)
1842 conf->params_cache = prev->params_cache;
1843 #endif
1844 conf->params_source = prev->params_source;
1845 }
1846
1847 rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params, NULL);
1848 if (rc != NGX_OK) {
1849 return NGX_CONF_ERROR;
1850 }
1851
1852 #if (NGX_HTTP_CACHE)
1853
1854 if (conf->upstream.cache) {
1855 rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params_cache,
1856 ngx_http_uwsgi_cache_headers);
1857 if (rc != NGX_OK) {
1858 return NGX_CONF_ERROR;
1859 }
1860 }
1861
1862 #endif
1863
1864 /*
1865 * special handling to preserve conf->params in the "http" section
1866 * to inherit it to all servers
1867 */
1868
1869 if (prev->params.hash.buckets == NULL
1870 && conf->params_source == prev->params_source)
1871 {
1872 prev->params = conf->params;
1873 #if (NGX_HTTP_CACHE)
1874 prev->params_cache = conf->params_cache;
1875 #endif
1876 }
1877
1878 return NGX_CONF_OK;
1879 }
1880
1881
1882 static ngx_int_t
ngx_http_uwsgi_init_params(ngx_conf_t * cf,ngx_http_uwsgi_loc_conf_t * conf,ngx_http_uwsgi_params_t * params,ngx_keyval_t * default_params)1883 ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
1884 ngx_http_uwsgi_params_t *params, ngx_keyval_t *default_params)
1885 {
1886 u_char *p;
1887 size_t size;
1888 uintptr_t *code;
1889 ngx_uint_t i, nsrc;
1890 ngx_array_t headers_names, params_merged;
1891 ngx_keyval_t *h;
1892 ngx_hash_key_t *hk;
1893 ngx_hash_init_t hash;
1894 ngx_http_upstream_param_t *src, *s;
1895 ngx_http_script_compile_t sc;
1896 ngx_http_script_copy_code_t *copy;
1897
1898 if (params->hash.buckets) {
1899 return NGX_OK;
1900 }
1901
1902 if (conf->params_source == NULL && default_params == NULL) {
1903 params->hash.buckets = (void *) 1;
1904 return NGX_OK;
1905 }
1906
1907 params->lengths = ngx_array_create(cf->pool, 64, 1);
1908 if (params->lengths == NULL) {
1909 return NGX_ERROR;
1910 }
1911
1912 params->values = ngx_array_create(cf->pool, 512, 1);
1913 if (params->values == NULL) {
1914 return NGX_ERROR;
1915 }
1916
1917 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
1918 != NGX_OK)
1919 {
1920 return NGX_ERROR;
1921 }
1922
1923 if (conf->params_source) {
1924 src = conf->params_source->elts;
1925 nsrc = conf->params_source->nelts;
1926
1927 } else {
1928 src = NULL;
1929 nsrc = 0;
1930 }
1931
1932 if (default_params) {
1933 if (ngx_array_init(¶ms_merged, cf->temp_pool, 4,
1934 sizeof(ngx_http_upstream_param_t))
1935 != NGX_OK)
1936 {
1937 return NGX_ERROR;
1938 }
1939
1940 for (i = 0; i < nsrc; i++) {
1941
1942 s = ngx_array_push(¶ms_merged);
1943 if (s == NULL) {
1944 return NGX_ERROR;
1945 }
1946
1947 *s = src[i];
1948 }
1949
1950 h = default_params;
1951
1952 while (h->key.len) {
1953
1954 src = params_merged.elts;
1955 nsrc = params_merged.nelts;
1956
1957 for (i = 0; i < nsrc; i++) {
1958 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
1959 goto next;
1960 }
1961 }
1962
1963 s = ngx_array_push(¶ms_merged);
1964 if (s == NULL) {
1965 return NGX_ERROR;
1966 }
1967
1968 s->key = h->key;
1969 s->value = h->value;
1970 s->skip_empty = 1;
1971
1972 next:
1973
1974 h++;
1975 }
1976
1977 src = params_merged.elts;
1978 nsrc = params_merged.nelts;
1979 }
1980
1981 for (i = 0; i < nsrc; i++) {
1982
1983 if (src[i].key.len > sizeof("HTTP_") - 1
1984 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
1985 {
1986 hk = ngx_array_push(&headers_names);
1987 if (hk == NULL) {
1988 return NGX_ERROR;
1989 }
1990
1991 hk->key.len = src[i].key.len - 5;
1992 hk->key.data = src[i].key.data + 5;
1993 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
1994 hk->value = (void *) 1;
1995
1996 if (src[i].value.len == 0) {
1997 continue;
1998 }
1999 }
2000
2001 copy = ngx_array_push_n(params->lengths,
2002 sizeof(ngx_http_script_copy_code_t));
2003 if (copy == NULL) {
2004 return NGX_ERROR;
2005 }
2006
2007 copy->code = (ngx_http_script_code_pt) (void *)
2008 ngx_http_script_copy_len_code;
2009 copy->len = src[i].key.len;
2010
2011 copy = ngx_array_push_n(params->lengths,
2012 sizeof(ngx_http_script_copy_code_t));
2013 if (copy == NULL) {
2014 return NGX_ERROR;
2015 }
2016
2017 copy->code = (ngx_http_script_code_pt) (void *)
2018 ngx_http_script_copy_len_code;
2019 copy->len = src[i].skip_empty;
2020
2021
2022 size = (sizeof(ngx_http_script_copy_code_t)
2023 + src[i].key.len + sizeof(uintptr_t) - 1)
2024 & ~(sizeof(uintptr_t) - 1);
2025
2026 copy = ngx_array_push_n(params->values, size);
2027 if (copy == NULL) {
2028 return NGX_ERROR;
2029 }
2030
2031 copy->code = ngx_http_script_copy_code;
2032 copy->len = src[i].key.len;
2033
2034 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2035 ngx_memcpy(p, src[i].key.data, src[i].key.len);
2036
2037
2038 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2039
2040 sc.cf = cf;
2041 sc.source = &src[i].value;
2042 sc.flushes = ¶ms->flushes;
2043 sc.lengths = ¶ms->lengths;
2044 sc.values = ¶ms->values;
2045
2046 if (ngx_http_script_compile(&sc) != NGX_OK) {
2047 return NGX_ERROR;
2048 }
2049
2050 code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
2051 if (code == NULL) {
2052 return NGX_ERROR;
2053 }
2054
2055 *code = (uintptr_t) NULL;
2056
2057
2058 code = ngx_array_push_n(params->values, sizeof(uintptr_t));
2059 if (code == NULL) {
2060 return NGX_ERROR;
2061 }
2062
2063 *code = (uintptr_t) NULL;
2064 }
2065
2066 code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
2067 if (code == NULL) {
2068 return NGX_ERROR;
2069 }
2070
2071 *code = (uintptr_t) NULL;
2072
2073 params->number = headers_names.nelts;
2074
2075 hash.hash = ¶ms->hash;
2076 hash.key = ngx_hash_key_lc;
2077 hash.max_size = 512;
2078 hash.bucket_size = 64;
2079 hash.name = "uwsgi_params_hash";
2080 hash.pool = cf->pool;
2081 hash.temp_pool = NULL;
2082
2083 return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
2084 }
2085
2086
2087 static char *
ngx_http_uwsgi_pass(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2088 ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2089 {
2090 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
2091
2092 size_t add;
2093 ngx_url_t u;
2094 ngx_str_t *value, *url;
2095 ngx_uint_t n;
2096 ngx_http_core_loc_conf_t *clcf;
2097 ngx_http_script_compile_t sc;
2098
2099 if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) {
2100 return "is duplicate";
2101 }
2102
2103 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2104 clcf->handler = ngx_http_uwsgi_handler;
2105
2106 value = cf->args->elts;
2107
2108 url = &value[1];
2109
2110 n = ngx_http_script_variables_count(url);
2111
2112 if (n) {
2113
2114 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2115
2116 sc.cf = cf;
2117 sc.source = url;
2118 sc.lengths = &uwcf->uwsgi_lengths;
2119 sc.values = &uwcf->uwsgi_values;
2120 sc.variables = n;
2121 sc.complete_lengths = 1;
2122 sc.complete_values = 1;
2123
2124 if (ngx_http_script_compile(&sc) != NGX_OK) {
2125 return NGX_CONF_ERROR;
2126 }
2127
2128 #if (NGX_HTTP_SSL)
2129 uwcf->ssl = 1;
2130 #endif
2131
2132 return NGX_CONF_OK;
2133 }
2134
2135 if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
2136 add = 8;
2137
2138 } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {
2139
2140 #if (NGX_HTTP_SSL)
2141 add = 9;
2142 uwcf->ssl = 1;
2143 #else
2144 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2145 "suwsgi protocol requires SSL support");
2146 return NGX_CONF_ERROR;
2147 #endif
2148
2149 } else {
2150 add = 0;
2151 }
2152
2153 ngx_memzero(&u, sizeof(ngx_url_t));
2154
2155 u.url.len = url->len - add;
2156 u.url.data = url->data + add;
2157 u.no_resolve = 1;
2158
2159 uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
2160 if (uwcf->upstream.upstream == NULL) {
2161 return NGX_CONF_ERROR;
2162 }
2163
2164 if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
2165 clcf->auto_redirect = 1;
2166 }
2167
2168 return NGX_CONF_OK;
2169 }
2170
2171
2172 static char *
ngx_http_uwsgi_store(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2173 ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2174 {
2175 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
2176
2177 ngx_str_t *value;
2178 ngx_http_script_compile_t sc;
2179
2180 if (uwcf->upstream.store != NGX_CONF_UNSET) {
2181 return "is duplicate";
2182 }
2183
2184 value = cf->args->elts;
2185
2186 if (ngx_strcmp(value[1].data, "off") == 0) {
2187 uwcf->upstream.store = 0;
2188 return NGX_CONF_OK;
2189 }
2190
2191 #if (NGX_HTTP_CACHE)
2192
2193 if (uwcf->upstream.cache > 0) {
2194 return "is incompatible with \"uwsgi_cache\"";
2195 }
2196
2197 #endif
2198
2199 uwcf->upstream.store = 1;
2200
2201 if (ngx_strcmp(value[1].data, "on") == 0) {
2202 return NGX_CONF_OK;
2203 }
2204
2205 /* include the terminating '\0' into script */
2206 value[1].len++;
2207
2208 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2209
2210 sc.cf = cf;
2211 sc.source = &value[1];
2212 sc.lengths = &uwcf->upstream.store_lengths;
2213 sc.values = &uwcf->upstream.store_values;
2214 sc.variables = ngx_http_script_variables_count(&value[1]);
2215 sc.complete_lengths = 1;
2216 sc.complete_values = 1;
2217
2218 if (ngx_http_script_compile(&sc) != NGX_OK) {
2219 return NGX_CONF_ERROR;
2220 }
2221
2222 return NGX_CONF_OK;
2223 }
2224
2225
2226 #if (NGX_HTTP_CACHE)
2227
2228 static char *
ngx_http_uwsgi_cache(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2229 ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2230 {
2231 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
2232
2233 ngx_str_t *value;
2234 ngx_http_complex_value_t cv;
2235 ngx_http_compile_complex_value_t ccv;
2236
2237 value = cf->args->elts;
2238
2239 if (uwcf->upstream.cache != NGX_CONF_UNSET) {
2240 return "is duplicate";
2241 }
2242
2243 if (ngx_strcmp(value[1].data, "off") == 0) {
2244 uwcf->upstream.cache = 0;
2245 return NGX_CONF_OK;
2246 }
2247
2248 if (uwcf->upstream.store > 0) {
2249 return "is incompatible with \"uwsgi_store\"";
2250 }
2251
2252 uwcf->upstream.cache = 1;
2253
2254 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
2255
2256 ccv.cf = cf;
2257 ccv.value = &value[1];
2258 ccv.complex_value = &cv;
2259
2260 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
2261 return NGX_CONF_ERROR;
2262 }
2263
2264 if (cv.lengths != NULL) {
2265
2266 uwcf->upstream.cache_value = ngx_palloc(cf->pool,
2267 sizeof(ngx_http_complex_value_t));
2268 if (uwcf->upstream.cache_value == NULL) {
2269 return NGX_CONF_ERROR;
2270 }
2271
2272 *uwcf->upstream.cache_value = cv;
2273
2274 return NGX_CONF_OK;
2275 }
2276
2277 uwcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
2278 &ngx_http_uwsgi_module);
2279 if (uwcf->upstream.cache_zone == NULL) {
2280 return NGX_CONF_ERROR;
2281 }
2282
2283 return NGX_CONF_OK;
2284 }
2285
2286
2287 static char *
ngx_http_uwsgi_cache_key(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2288 ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2289 {
2290 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
2291
2292 ngx_str_t *value;
2293 ngx_http_compile_complex_value_t ccv;
2294
2295 value = cf->args->elts;
2296
2297 if (uwcf->cache_key.value.data) {
2298 return "is duplicate";
2299 }
2300
2301 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
2302
2303 ccv.cf = cf;
2304 ccv.value = &value[1];
2305 ccv.complex_value = &uwcf->cache_key;
2306
2307 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
2308 return NGX_CONF_ERROR;
2309 }
2310
2311 return NGX_CONF_OK;
2312 }
2313
2314 #endif
2315
2316
2317 #if (NGX_HTTP_SSL)
2318
2319 static char *
ngx_http_uwsgi_ssl_password_file(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)2320 ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2321 {
2322 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
2323
2324 ngx_str_t *value;
2325
2326 if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
2327 return "is duplicate";
2328 }
2329
2330 value = cf->args->elts;
2331
2332 uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
2333
2334 if (uwcf->ssl_passwords == NULL) {
2335 return NGX_CONF_ERROR;
2336 }
2337
2338 return NGX_CONF_OK;
2339 }
2340
2341
2342 static ngx_int_t
ngx_http_uwsgi_set_ssl(ngx_conf_t * cf,ngx_http_uwsgi_loc_conf_t * uwcf)2343 ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
2344 {
2345 ngx_pool_cleanup_t *cln;
2346
2347 uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2348 if (uwcf->upstream.ssl == NULL) {
2349 return NGX_ERROR;
2350 }
2351
2352 uwcf->upstream.ssl->log = cf->log;
2353
2354 if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
2355 != NGX_OK)
2356 {
2357 return NGX_ERROR;
2358 }
2359
2360 cln = ngx_pool_cleanup_add(cf->pool, 0);
2361 if (cln == NULL) {
2362 ngx_ssl_cleanup_ctx(uwcf->upstream.ssl);
2363 return NGX_ERROR;
2364 }
2365
2366 cln->handler = ngx_ssl_cleanup_ctx;
2367 cln->data = uwcf->upstream.ssl;
2368
2369 if (uwcf->ssl_certificate.len) {
2370
2371 if (uwcf->ssl_certificate_key.len == 0) {
2372 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2373 "no \"uwsgi_ssl_certificate_key\" is defined "
2374 "for certificate \"%V\"", &uwcf->ssl_certificate);
2375 return NGX_ERROR;
2376 }
2377
2378 if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate,
2379 &uwcf->ssl_certificate_key, uwcf->ssl_passwords)
2380 != NGX_OK)
2381 {
2382 return NGX_ERROR;
2383 }
2384 }
2385
2386 if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
2387 != NGX_OK)
2388 {
2389 return NGX_ERROR;
2390 }
2391
2392 if (uwcf->upstream.ssl_verify) {
2393 if (uwcf->ssl_trusted_certificate.len == 0) {
2394 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2395 "no uwsgi_ssl_trusted_certificate for uwsgi_ssl_verify");
2396 return NGX_ERROR;
2397 }
2398
2399 if (ngx_ssl_trusted_certificate(cf, uwcf->upstream.ssl,
2400 &uwcf->ssl_trusted_certificate,
2401 uwcf->ssl_verify_depth)
2402 != NGX_OK)
2403 {
2404 return NGX_ERROR;
2405 }
2406
2407 if (ngx_ssl_crl(cf, uwcf->upstream.ssl, &uwcf->ssl_crl) != NGX_OK) {
2408 return NGX_ERROR;
2409 }
2410 }
2411
2412 if (ngx_ssl_client_session_cache(cf, uwcf->upstream.ssl,
2413 uwcf->upstream.ssl_session_reuse)
2414 != NGX_OK)
2415 {
2416 return NGX_ERROR;
2417 }
2418
2419 return NGX_OK;
2420 }
2421
2422 #endif
2423