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(&params->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(&params_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(&params_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(&params_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 = &params->flushes;
2043         sc.lengths = &params->lengths;
2044         sc.values = &params->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 = &params->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