3 * Copyright (C) Unbit S.a.s. 2009-2010
4 * Copyright (C) 2008 Manlio Perillo (manlio.perillo@gmail.com)
5 * Copyright (C) Igor Sysoev
6 * Copyright (C) Nginx, Inc.
10 #include <ngx_config.h>
16 ngx_http_upstream_conf_t upstream
;
19 ngx_array_t
*params_len
;
21 ngx_array_t
*params_source
;
23 ngx_hash_t headers_hash
;
24 ngx_uint_t header_params
;
26 ngx_array_t
*uwsgi_lengths
;
27 ngx_array_t
*uwsgi_values
;
30 ngx_http_complex_value_t cache_key
;
33 ngx_str_t uwsgi_string
;
37 } ngx_http_uwsgi_loc_conf_t
;
40 static ngx_int_t
ngx_http_uwsgi_eval(ngx_http_request_t
*r
,
41 ngx_http_uwsgi_loc_conf_t
*uwcf
);
42 static ngx_int_t
ngx_http_uwsgi_create_request(ngx_http_request_t
*r
);
43 static ngx_int_t
ngx_http_uwsgi_reinit_request(ngx_http_request_t
*r
);
44 static ngx_int_t
ngx_http_uwsgi_process_status_line(ngx_http_request_t
*r
);
45 static ngx_int_t
ngx_http_uwsgi_process_header(ngx_http_request_t
*r
);
46 static void ngx_http_uwsgi_abort_request(ngx_http_request_t
*r
);
47 static void ngx_http_uwsgi_finalize_request(ngx_http_request_t
*r
,
50 static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t
*cf
);
51 static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
*cf
, void *parent
,
53 static ngx_int_t
ngx_http_uwsgi_merge_params(ngx_conf_t
*cf
,
54 ngx_http_uwsgi_loc_conf_t
*conf
, ngx_http_uwsgi_loc_conf_t
*prev
);
56 static char *ngx_http_uwsgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
58 static char *ngx_http_uwsgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
62 static ngx_int_t
ngx_http_uwsgi_create_key(ngx_http_request_t
*r
);
63 static char *ngx_http_uwsgi_cache(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
65 static char *ngx_http_uwsgi_cache_key(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
70 static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds
= {
71 ngx_conf_check_num_bounds
, 0, 255
75 static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks
[] = {
76 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR
},
77 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT
},
78 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
},
79 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500
},
80 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503
},
81 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404
},
82 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING
},
83 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF
},
84 { ngx_null_string
, 0 }
88 ngx_module_t ngx_http_uwsgi_module
;
91 static ngx_command_t ngx_http_uwsgi_commands
[] = {
93 { ngx_string("uwsgi_pass"),
94 NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1
,
96 NGX_HTTP_LOC_CONF_OFFSET
,
100 { ngx_string("uwsgi_modifier1"),
101 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
102 ngx_conf_set_num_slot
,
103 NGX_HTTP_LOC_CONF_OFFSET
,
104 offsetof(ngx_http_uwsgi_loc_conf_t
, modifier1
),
105 &ngx_http_uwsgi_modifier_bounds
},
107 { ngx_string("uwsgi_modifier2"),
108 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
109 ngx_conf_set_num_slot
,
110 NGX_HTTP_LOC_CONF_OFFSET
,
111 offsetof(ngx_http_uwsgi_loc_conf_t
, modifier2
),
112 &ngx_http_uwsgi_modifier_bounds
},
114 { ngx_string("uwsgi_store"),
115 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
116 ngx_http_uwsgi_store
,
117 NGX_HTTP_LOC_CONF_OFFSET
,
121 { ngx_string("uwsgi_store_access"),
122 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE123
,
123 ngx_conf_set_access_slot
,
124 NGX_HTTP_LOC_CONF_OFFSET
,
125 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.store_access
),
128 { ngx_string("uwsgi_buffering"),
129 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
130 ngx_conf_set_flag_slot
,
131 NGX_HTTP_LOC_CONF_OFFSET
,
132 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.buffering
),
135 { ngx_string("uwsgi_ignore_client_abort"),
136 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
137 ngx_conf_set_flag_slot
,
138 NGX_HTTP_LOC_CONF_OFFSET
,
139 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.ignore_client_abort
),
142 { ngx_string("uwsgi_bind"),
143 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
144 ngx_http_upstream_bind_set_slot
,
145 NGX_HTTP_LOC_CONF_OFFSET
,
146 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.local
),
149 { ngx_string("uwsgi_connect_timeout"),
150 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
151 ngx_conf_set_msec_slot
,
152 NGX_HTTP_LOC_CONF_OFFSET
,
153 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.connect_timeout
),
156 { ngx_string("uwsgi_send_timeout"),
157 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
158 ngx_conf_set_msec_slot
,
159 NGX_HTTP_LOC_CONF_OFFSET
,
160 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.send_timeout
),
163 { ngx_string("uwsgi_buffer_size"),
164 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
165 ngx_conf_set_size_slot
,
166 NGX_HTTP_LOC_CONF_OFFSET
,
167 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.buffer_size
),
170 { ngx_string("uwsgi_pass_request_headers"),
171 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
172 ngx_conf_set_flag_slot
,
173 NGX_HTTP_LOC_CONF_OFFSET
,
174 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.pass_request_headers
),
177 { ngx_string("uwsgi_pass_request_body"),
178 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
179 ngx_conf_set_flag_slot
,
180 NGX_HTTP_LOC_CONF_OFFSET
,
181 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.pass_request_body
),
184 { ngx_string("uwsgi_intercept_errors"),
185 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
186 ngx_conf_set_flag_slot
,
187 NGX_HTTP_LOC_CONF_OFFSET
,
188 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.intercept_errors
),
191 { ngx_string("uwsgi_read_timeout"),
192 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
193 ngx_conf_set_msec_slot
,
194 NGX_HTTP_LOC_CONF_OFFSET
,
195 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.read_timeout
),
198 { ngx_string("uwsgi_buffers"),
199 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
200 ngx_conf_set_bufs_slot
,
201 NGX_HTTP_LOC_CONF_OFFSET
,
202 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.bufs
),
205 { ngx_string("uwsgi_busy_buffers_size"),
206 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
207 ngx_conf_set_size_slot
,
208 NGX_HTTP_LOC_CONF_OFFSET
,
209 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.busy_buffers_size_conf
),
214 { ngx_string("uwsgi_cache"),
215 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
216 ngx_http_uwsgi_cache
,
217 NGX_HTTP_LOC_CONF_OFFSET
,
221 { ngx_string("uwsgi_cache_key"),
222 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
223 ngx_http_uwsgi_cache_key
,
224 NGX_HTTP_LOC_CONF_OFFSET
,
228 { ngx_string("uwsgi_cache_path"),
229 NGX_HTTP_MAIN_CONF
|NGX_CONF_2MORE
,
230 ngx_http_file_cache_set_slot
,
233 &ngx_http_uwsgi_module
},
235 { ngx_string("uwsgi_cache_bypass"),
236 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
237 ngx_http_set_predicate_slot
,
238 NGX_HTTP_LOC_CONF_OFFSET
,
239 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_bypass
),
242 { ngx_string("uwsgi_no_cache"),
243 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
244 ngx_http_set_predicate_slot
,
245 NGX_HTTP_LOC_CONF_OFFSET
,
246 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.no_cache
),
249 { ngx_string("uwsgi_cache_valid"),
250 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
251 ngx_http_file_cache_valid_set_slot
,
252 NGX_HTTP_LOC_CONF_OFFSET
,
253 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_valid
),
256 { ngx_string("uwsgi_cache_min_uses"),
257 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
258 ngx_conf_set_num_slot
,
259 NGX_HTTP_LOC_CONF_OFFSET
,
260 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_min_uses
),
263 { ngx_string("uwsgi_cache_use_stale"),
264 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
265 ngx_conf_set_bitmask_slot
,
266 NGX_HTTP_LOC_CONF_OFFSET
,
267 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_use_stale
),
268 &ngx_http_uwsgi_next_upstream_masks
},
270 { ngx_string("uwsgi_cache_methods"),
271 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
272 ngx_conf_set_bitmask_slot
,
273 NGX_HTTP_LOC_CONF_OFFSET
,
274 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_methods
),
275 &ngx_http_upstream_cache_method_mask
},
277 { ngx_string("uwsgi_cache_lock"),
278 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
279 ngx_conf_set_flag_slot
,
280 NGX_HTTP_LOC_CONF_OFFSET
,
281 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_lock
),
284 { ngx_string("uwsgi_cache_lock_timeout"),
285 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
286 ngx_conf_set_msec_slot
,
287 NGX_HTTP_LOC_CONF_OFFSET
,
288 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.cache_lock_timeout
),
293 { ngx_string("uwsgi_temp_path"),
294 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1234
,
295 ngx_conf_set_path_slot
,
296 NGX_HTTP_LOC_CONF_OFFSET
,
297 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.temp_path
),
300 { ngx_string("uwsgi_max_temp_file_size"),
301 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
302 ngx_conf_set_size_slot
,
303 NGX_HTTP_LOC_CONF_OFFSET
,
304 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.max_temp_file_size_conf
),
307 { ngx_string("uwsgi_temp_file_write_size"),
308 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
309 ngx_conf_set_size_slot
,
310 NGX_HTTP_LOC_CONF_OFFSET
,
311 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.temp_file_write_size_conf
),
314 { ngx_string("uwsgi_next_upstream"),
315 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
316 ngx_conf_set_bitmask_slot
,
317 NGX_HTTP_LOC_CONF_OFFSET
,
318 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.next_upstream
),
319 &ngx_http_uwsgi_next_upstream_masks
},
321 { ngx_string("uwsgi_param"),
322 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE23
,
323 ngx_http_upstream_param_set_slot
,
324 NGX_HTTP_LOC_CONF_OFFSET
,
325 offsetof(ngx_http_uwsgi_loc_conf_t
, params_source
),
328 { ngx_string("uwsgi_string"),
329 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
330 ngx_conf_set_str_slot
,
331 NGX_HTTP_LOC_CONF_OFFSET
,
332 offsetof(ngx_http_uwsgi_loc_conf_t
, uwsgi_string
),
335 { ngx_string("uwsgi_pass_header"),
336 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
337 ngx_conf_set_str_array_slot
,
338 NGX_HTTP_LOC_CONF_OFFSET
,
339 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.pass_headers
),
342 { ngx_string("uwsgi_hide_header"),
343 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
344 ngx_conf_set_str_array_slot
,
345 NGX_HTTP_LOC_CONF_OFFSET
,
346 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.hide_headers
),
349 { ngx_string("uwsgi_ignore_headers"),
350 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
351 ngx_conf_set_bitmask_slot
,
352 NGX_HTTP_LOC_CONF_OFFSET
,
353 offsetof(ngx_http_uwsgi_loc_conf_t
, upstream
.ignore_headers
),
354 &ngx_http_upstream_ignore_headers_masks
},
360 static ngx_http_module_t ngx_http_uwsgi_module_ctx
= {
361 NULL
, /* preconfiguration */
362 NULL
, /* postconfiguration */
364 NULL
, /* create main configuration */
365 NULL
, /* init main configuration */
367 NULL
, /* create server configuration */
368 NULL
, /* merge server configuration */
370 ngx_http_uwsgi_create_loc_conf
, /* create location configuration */
371 ngx_http_uwsgi_merge_loc_conf
/* merge location configuration */
375 ngx_module_t ngx_http_uwsgi_module
= {
377 &ngx_http_uwsgi_module_ctx
, /* module context */
378 ngx_http_uwsgi_commands
, /* module directives */
379 NGX_HTTP_MODULE
, /* module type */
380 NULL
, /* init master */
381 NULL
, /* init module */
382 NULL
, /* init process */
383 NULL
, /* init thread */
384 NULL
, /* exit thread */
385 NULL
, /* exit process */
386 NULL
, /* exit master */
387 NGX_MODULE_V1_PADDING
391 static ngx_str_t ngx_http_uwsgi_hide_headers
[] = {
392 ngx_string("X-Accel-Expires"),
393 ngx_string("X-Accel-Redirect"),
394 ngx_string("X-Accel-Limit-Rate"),
395 ngx_string("X-Accel-Buffering"),
396 ngx_string("X-Accel-Charset"),
403 static ngx_keyval_t ngx_http_uwsgi_cache_headers
[] = {
404 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
405 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
406 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
407 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
408 { ngx_string("HTTP_RANGE"), ngx_string("") },
409 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
410 { ngx_null_string
, ngx_null_string
}
416 static ngx_path_init_t ngx_http_uwsgi_temp_path
= {
417 ngx_string(NGX_HTTP_UWSGI_TEMP_PATH
), { 1, 2, 0 }
422 ngx_http_uwsgi_handler(ngx_http_request_t
*r
)
425 ngx_http_status_t
*status
;
426 ngx_http_upstream_t
*u
;
427 ngx_http_uwsgi_loc_conf_t
*uwcf
;
429 if (r
->subrequest_in_memory
) {
430 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
431 "ngx_http_uwsgi_module does not support "
432 "subrequests in memory");
433 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
436 if (ngx_http_upstream_create(r
) != NGX_OK
) {
437 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
440 status
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_status_t
));
441 if (status
== NULL
) {
442 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
445 ngx_http_set_ctx(r
, status
, ngx_http_uwsgi_module
);
447 uwcf
= ngx_http_get_module_loc_conf(r
, ngx_http_uwsgi_module
);
449 if (uwcf
->uwsgi_lengths
) {
450 if (ngx_http_uwsgi_eval(r
, uwcf
) != NGX_OK
) {
451 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
457 ngx_str_set(&u
->schema
, "uwsgi://");
458 u
->output
.tag
= (ngx_buf_tag_t
) &ngx_http_uwsgi_module
;
460 u
->conf
= &uwcf
->upstream
;
463 u
->create_key
= ngx_http_uwsgi_create_key
;
465 u
->create_request
= ngx_http_uwsgi_create_request
;
466 u
->reinit_request
= ngx_http_uwsgi_reinit_request
;
467 u
->process_header
= ngx_http_uwsgi_process_status_line
;
468 u
->abort_request
= ngx_http_uwsgi_abort_request
;
469 u
->finalize_request
= ngx_http_uwsgi_finalize_request
;
472 u
->buffering
= uwcf
->upstream
.buffering
;
474 u
->pipe
= ngx_pcalloc(r
->pool
, sizeof(ngx_event_pipe_t
));
475 if (u
->pipe
== NULL
) {
476 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
479 u
->pipe
->input_filter
= ngx_event_pipe_copy_input_filter
;
480 u
->pipe
->input_ctx
= r
;
482 rc
= ngx_http_read_client_request_body(r
, ngx_http_upstream_init
);
484 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
) {
493 ngx_http_uwsgi_eval(ngx_http_request_t
*r
, ngx_http_uwsgi_loc_conf_t
* uwcf
)
496 ngx_http_upstream_t
*u
;
498 ngx_memzero(&url
, sizeof(ngx_url_t
));
500 if (ngx_http_script_run(r
, &url
.url
, uwcf
->uwsgi_lengths
->elts
, 0,
501 uwcf
->uwsgi_values
->elts
)
509 if (ngx_parse_url(r
->pool
, &url
) != NGX_OK
) {
511 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
512 "%s in upstream \"%V\"", url
.err
, &url
.url
);
520 u
->resolved
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_upstream_resolved_t
));
521 if (u
->resolved
== NULL
) {
525 if (url
.addrs
&& url
.addrs
[0].sockaddr
) {
526 u
->resolved
->sockaddr
= url
.addrs
[0].sockaddr
;
527 u
->resolved
->socklen
= url
.addrs
[0].socklen
;
528 u
->resolved
->naddrs
= 1;
529 u
->resolved
->host
= url
.addrs
[0].name
;
532 u
->resolved
->host
= url
.host
;
533 u
->resolved
->port
= url
.port
;
534 u
->resolved
->no_port
= url
.no_port
;
544 ngx_http_uwsgi_create_key(ngx_http_request_t
*r
)
547 ngx_http_uwsgi_loc_conf_t
*uwcf
;
549 key
= ngx_array_push(&r
->cache
->keys
);
554 uwcf
= ngx_http_get_module_loc_conf(r
, ngx_http_uwsgi_module
);
556 if (ngx_http_complex_value(r
, &uwcf
->cache_key
, key
) != NGX_OK
) {
567 ngx_http_uwsgi_create_request(ngx_http_request_t
*r
)
569 u_char ch
, *lowcase_key
;
570 size_t key_len
, val_len
, len
, allocated
;
571 ngx_uint_t i
, n
, hash
, skip_empty
, header_params
;
573 ngx_chain_t
*cl
, *body
;
574 ngx_list_part_t
*part
;
575 ngx_table_elt_t
*header
, **ignored
;
576 ngx_http_script_code_pt code
;
577 ngx_http_script_engine_t e
, le
;
578 ngx_http_uwsgi_loc_conf_t
*uwcf
;
579 ngx_http_script_len_code_pt lcode
;
585 uwcf
= ngx_http_get_module_loc_conf(r
, ngx_http_uwsgi_module
);
587 if (uwcf
->params_len
) {
588 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
590 ngx_http_script_flush_no_cacheable_variables(r
, uwcf
->flushes
);
593 le
.ip
= uwcf
->params_len
->elts
;
596 while (*(uintptr_t *) le
.ip
) {
598 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
599 key_len
= lcode(&le
);
601 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
602 skip_empty
= lcode(&le
);
604 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode (&le
)) {
605 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
607 le
.ip
+= sizeof(uintptr_t);
609 if (skip_empty
&& val_len
== 0) {
613 len
+= 2 + key_len
+ 2 + val_len
;
617 if (uwcf
->upstream
.pass_request_headers
) {
622 if (uwcf
->header_params
) {
624 part
= &r
->headers_in
.headers
.part
;
631 ignored
= ngx_palloc(r
->pool
, n
* sizeof(void *));
632 if (ignored
== NULL
) {
637 part
= &r
->headers_in
.headers
.part
;
640 for (i
= 0; /* void */ ; i
++) {
642 if (i
>= part
->nelts
) {
643 if (part
->next
== NULL
) {
652 if (uwcf
->header_params
) {
653 if (allocated
< header
[i
].key
.len
) {
654 allocated
= header
[i
].key
.len
+ 16;
655 lowcase_key
= ngx_pnalloc(r
->pool
, allocated
);
656 if (lowcase_key
== NULL
) {
663 for (n
= 0; n
< header
[i
].key
.len
; n
++) {
664 ch
= header
[i
].key
.data
[n
];
666 if (ch
>= 'A' && ch
<= 'Z') {
669 } else if (ch
== '-') {
673 hash
= ngx_hash(hash
, ch
);
677 if (ngx_hash_find(&uwcf
->headers_hash
, hash
, lowcase_key
, n
)) {
678 ignored
[header_params
++] = &header
[i
];
683 len
+= 2 + sizeof("HTTP_") - 1 + header
[i
].key
.len
684 + 2 + header
[i
].value
.len
;
688 len
+= uwcf
->uwsgi_string
.len
;
691 /* allow custom uwsgi packet */
692 if (len
> 0 && len
< 2) {
693 ngx_log_error (NGX_LOG_ALERT
, r
->connection
->log
, 0,
694 "uwsgi request is too little: %uz", len
);
699 b
= ngx_create_temp_buf(r
->pool
, len
+ 4);
704 cl
= ngx_alloc_chain_link(r
->pool
);
711 *b
->last
++ = (u_char
) uwcf
->modifier1
;
712 *b
->last
++ = (u_char
) (len
& 0xff);
713 *b
->last
++ = (u_char
) ((len
>> 8) & 0xff);
714 *b
->last
++ = (u_char
) uwcf
->modifier2
;
716 if (uwcf
->params_len
) {
717 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
719 e
.ip
= uwcf
->params
->elts
;
724 le
.ip
= uwcf
->params_len
->elts
;
726 while (*(uintptr_t *) le
.ip
) {
728 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
729 key_len
= (u_char
) lcode (&le
);
731 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
732 skip_empty
= lcode(&le
);
734 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode(&le
)) {
735 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
737 le
.ip
+= sizeof(uintptr_t);
739 if (skip_empty
&& val_len
== 0) {
742 while (*(uintptr_t *) e
.ip
) {
743 code
= *(ngx_http_script_code_pt
*) e
.ip
;
744 code((ngx_http_script_engine_t
*) &e
);
746 e
.ip
+= sizeof(uintptr_t);
753 *e
.pos
++ = (u_char
) (key_len
& 0xff);
754 *e
.pos
++ = (u_char
) ((key_len
>> 8) & 0xff);
756 code
= *(ngx_http_script_code_pt
*) e
.ip
;
757 code((ngx_http_script_engine_t
*) & e
);
759 *e
.pos
++ = (u_char
) (val_len
& 0xff);
760 *e
.pos
++ = (u_char
) ((val_len
>> 8) & 0xff);
762 while (*(uintptr_t *) e
.ip
) {
763 code
= *(ngx_http_script_code_pt
*) e
.ip
;
764 code((ngx_http_script_engine_t
*) & e
);
767 e
.ip
+= sizeof(uintptr_t);
769 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
770 "uwsgi param: \"%*s: %*s\"",
771 key_len
, e
.pos
- (key_len
+ 2 + val_len
),
772 val_len
, e
.pos
- val_len
);
778 if (uwcf
->upstream
.pass_request_headers
) {
780 part
= &r
->headers_in
.headers
.part
;
783 for (i
= 0; /* void */ ; i
++) {
785 if (i
>= part
->nelts
) {
786 if (part
->next
== NULL
) {
795 for (n
= 0; n
< header_params
; n
++) {
796 if (&header
[i
] == ignored
[n
]) {
801 key_len
= sizeof("HTTP_") - 1 + header
[i
].key
.len
;
802 *b
->last
++ = (u_char
) (key_len
& 0xff);
803 *b
->last
++ = (u_char
) ((key_len
>> 8) & 0xff);
805 b
->last
= ngx_cpymem(b
->last
, "HTTP_", sizeof("HTTP_") - 1);
806 for (n
= 0; n
< header
[i
].key
.len
; n
++) {
807 ch
= header
[i
].key
.data
[n
];
809 if (ch
>= 'a' && ch
<= 'z') {
812 } else if (ch
== '-') {
819 val_len
= header
[i
].value
.len
;
820 *b
->last
++ = (u_char
) (val_len
& 0xff);
821 *b
->last
++ = (u_char
) ((val_len
>> 8) & 0xff);
822 b
->last
= ngx_copy(b
->last
, header
[i
].value
.data
, val_len
);
824 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
825 "uwsgi param: \"%*s: %*s\"",
826 key_len
, b
->last
- (key_len
+ 2 + val_len
),
827 val_len
, b
->last
- val_len
);
834 b
->last
= ngx_copy(b
->last
, uwcf
->uwsgi_string
.data
,
835 uwcf
->uwsgi_string
.len
);
837 if (uwcf
->upstream
.pass_request_body
) {
838 body
= r
->upstream
->request_bufs
;
839 r
->upstream
->request_bufs
= cl
;
842 b
= ngx_alloc_buf(r
->pool
);
847 ngx_memcpy(b
, body
->buf
, sizeof(ngx_buf_t
));
849 cl
->next
= ngx_alloc_chain_link(r
->pool
);
850 if (cl
->next
== NULL
) {
861 r
->upstream
->request_bufs
= cl
;
871 ngx_http_uwsgi_reinit_request(ngx_http_request_t
*r
)
873 ngx_http_status_t
*status
;
875 status
= ngx_http_get_module_ctx(r
, ngx_http_uwsgi_module
);
877 if (status
== NULL
) {
883 status
->start
= NULL
;
886 r
->upstream
->process_header
= ngx_http_uwsgi_process_status_line
;
894 ngx_http_uwsgi_process_status_line(ngx_http_request_t
*r
)
898 ngx_http_status_t
*status
;
899 ngx_http_upstream_t
*u
;
901 status
= ngx_http_get_module_ctx(r
, ngx_http_uwsgi_module
);
903 if (status
== NULL
) {
909 rc
= ngx_http_parse_status_line(r
, &u
->buffer
, status
);
911 if (rc
== NGX_AGAIN
) {
915 if (rc
== NGX_ERROR
) {
916 u
->process_header
= ngx_http_uwsgi_process_header
;
917 return ngx_http_uwsgi_process_header(r
);
921 u
->state
->status
= status
->code
;
924 u
->headers_in
.status_n
= status
->code
;
926 len
= status
->end
- status
->start
;
927 u
->headers_in
.status_line
.len
= len
;
929 u
->headers_in
.status_line
.data
= ngx_pnalloc(r
->pool
, len
);
930 if (u
->headers_in
.status_line
.data
== NULL
) {
934 ngx_memcpy(u
->headers_in
.status_line
.data
, status
->start
, len
);
936 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
937 "http uwsgi status %ui \"%V\"",
938 u
->headers_in
.status_n
, &u
->headers_in
.status_line
);
940 u
->process_header
= ngx_http_uwsgi_process_header
;
942 return ngx_http_uwsgi_process_header(r
);
947 ngx_http_uwsgi_process_header(ngx_http_request_t
*r
)
949 ngx_str_t
*status_line
;
950 ngx_int_t rc
, status
;
952 ngx_http_upstream_t
*u
;
953 ngx_http_upstream_header_t
*hh
;
954 ngx_http_upstream_main_conf_t
*umcf
;
956 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
960 rc
= ngx_http_parse_header_line(r
, &r
->upstream
->buffer
, 1);
964 /* a header line has been parsed successfully */
966 h
= ngx_list_push(&r
->upstream
->headers_in
.headers
);
971 h
->hash
= r
->header_hash
;
973 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
974 h
->value
.len
= r
->header_end
- r
->header_start
;
976 h
->key
.data
= ngx_pnalloc(r
->pool
,
977 h
->key
.len
+ 1 + h
->value
.len
+ 1
979 if (h
->key
.data
== NULL
) {
983 h
->value
.data
= h
->key
.data
+ h
->key
.len
+ 1;
984 h
->lowcase_key
= h
->key
.data
+ h
->key
.len
+ 1 + h
->value
.len
+ 1;
986 ngx_memcpy(h
->key
.data
, r
->header_name_start
, h
->key
.len
);
987 h
->key
.data
[h
->key
.len
] = '\0';
988 ngx_memcpy(h
->value
.data
, r
->header_start
, h
->value
.len
);
989 h
->value
.data
[h
->value
.len
] = '\0';
991 if (h
->key
.len
== r
->lowcase_index
) {
992 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
995 ngx_strlow(h
->lowcase_key
, h
->key
.data
, h
->key
.len
);
998 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
->hash
,
999 h
->lowcase_key
, h
->key
.len
);
1001 if (hh
&& hh
->handler(r
, h
, hh
->offset
) != NGX_OK
) {
1005 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1006 "http uwsgi header: \"%V: %V\"", &h
->key
, &h
->value
);
1011 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1013 /* a whole header has been parsed successfully */
1015 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1016 "http uwsgi header done");
1020 if (u
->headers_in
.status_n
) {
1024 if (u
->headers_in
.status
) {
1025 status_line
= &u
->headers_in
.status
->value
;
1027 status
= ngx_atoi(status_line
->data
, 3);
1028 if (status
== NGX_ERROR
) {
1029 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1030 "upstream sent invalid status \"%V\"",
1032 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1035 u
->headers_in
.status_n
= status
;
1036 u
->headers_in
.status_line
= *status_line
;
1038 } else if (u
->headers_in
.location
) {
1039 u
->headers_in
.status_n
= 302;
1040 ngx_str_set(&u
->headers_in
.status_line
,
1041 "302 Moved Temporarily");
1044 u
->headers_in
.status_n
= 200;
1045 ngx_str_set(&u
->headers_in
.status_line
, "200 OK");
1049 u
->state
->status
= u
->headers_in
.status_n
;
1054 if (u
->headers_in
.status_n
== NGX_HTTP_SWITCHING_PROTOCOLS
1055 && r
->headers_in
.upgrade
)
1063 if (rc
== NGX_AGAIN
) {
1067 /* there was error while a header line parsing */
1069 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1070 "upstream sent invalid header");
1072 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1078 ngx_http_uwsgi_abort_request(ngx_http_request_t
*r
)
1080 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1081 "abort http uwsgi request");
1088 ngx_http_uwsgi_finalize_request(ngx_http_request_t
*r
, ngx_int_t rc
)
1090 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1091 "finalize http uwsgi request");
1098 ngx_http_uwsgi_create_loc_conf(ngx_conf_t
*cf
)
1100 ngx_http_uwsgi_loc_conf_t
*conf
;
1102 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_uwsgi_loc_conf_t
));
1107 conf
->modifier1
= NGX_CONF_UNSET_UINT
;
1108 conf
->modifier2
= NGX_CONF_UNSET_UINT
;
1110 conf
->upstream
.store
= NGX_CONF_UNSET
;
1111 conf
->upstream
.store_access
= NGX_CONF_UNSET_UINT
;
1112 conf
->upstream
.buffering
= NGX_CONF_UNSET
;
1113 conf
->upstream
.ignore_client_abort
= NGX_CONF_UNSET
;
1115 conf
->upstream
.local
= NGX_CONF_UNSET_PTR
;
1117 conf
->upstream
.connect_timeout
= NGX_CONF_UNSET_MSEC
;
1118 conf
->upstream
.send_timeout
= NGX_CONF_UNSET_MSEC
;
1119 conf
->upstream
.read_timeout
= NGX_CONF_UNSET_MSEC
;
1121 conf
->upstream
.send_lowat
= NGX_CONF_UNSET_SIZE
;
1122 conf
->upstream
.buffer_size
= NGX_CONF_UNSET_SIZE
;
1124 conf
->upstream
.busy_buffers_size_conf
= NGX_CONF_UNSET_SIZE
;
1125 conf
->upstream
.max_temp_file_size_conf
= NGX_CONF_UNSET_SIZE
;
1126 conf
->upstream
.temp_file_write_size_conf
= NGX_CONF_UNSET_SIZE
;
1128 conf
->upstream
.pass_request_headers
= NGX_CONF_UNSET
;
1129 conf
->upstream
.pass_request_body
= NGX_CONF_UNSET
;
1131 #if (NGX_HTTP_CACHE)
1132 conf
->upstream
.cache
= NGX_CONF_UNSET_PTR
;
1133 conf
->upstream
.cache_min_uses
= NGX_CONF_UNSET_UINT
;
1134 conf
->upstream
.cache_bypass
= NGX_CONF_UNSET_PTR
;
1135 conf
->upstream
.no_cache
= NGX_CONF_UNSET_PTR
;
1136 conf
->upstream
.cache_valid
= NGX_CONF_UNSET_PTR
;
1137 conf
->upstream
.cache_lock
= NGX_CONF_UNSET
;
1138 conf
->upstream
.cache_lock_timeout
= NGX_CONF_UNSET_MSEC
;
1141 conf
->upstream
.hide_headers
= NGX_CONF_UNSET_PTR
;
1142 conf
->upstream
.pass_headers
= NGX_CONF_UNSET_PTR
;
1144 conf
->upstream
.intercept_errors
= NGX_CONF_UNSET
;
1146 /* "uwsgi_cyclic_temp_file" is disabled */
1147 conf
->upstream
.cyclic_temp_file
= 0;
1149 conf
->upstream
.change_buffering
= 1;
1151 ngx_str_set(&conf
->upstream
.module
, "uwsgi");
1158 ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
1160 ngx_http_uwsgi_loc_conf_t
*prev
= parent
;
1161 ngx_http_uwsgi_loc_conf_t
*conf
= child
;
1164 ngx_hash_init_t hash
;
1165 ngx_http_core_loc_conf_t
*clcf
;
1167 if (conf
->upstream
.store
!= 0) {
1168 ngx_conf_merge_value(conf
->upstream
.store
, prev
->upstream
.store
, 0);
1170 if (conf
->upstream
.store_lengths
== NULL
) {
1171 conf
->upstream
.store_lengths
= prev
->upstream
.store_lengths
;
1172 conf
->upstream
.store_values
= prev
->upstream
.store_values
;
1176 ngx_conf_merge_uint_value(conf
->upstream
.store_access
,
1177 prev
->upstream
.store_access
, 0600);
1179 ngx_conf_merge_value(conf
->upstream
.buffering
,
1180 prev
->upstream
.buffering
, 1);
1182 ngx_conf_merge_value(conf
->upstream
.ignore_client_abort
,
1183 prev
->upstream
.ignore_client_abort
, 0);
1185 ngx_conf_merge_ptr_value(conf
->upstream
.local
,
1186 prev
->upstream
.local
, NULL
);
1188 ngx_conf_merge_msec_value(conf
->upstream
.connect_timeout
,
1189 prev
->upstream
.connect_timeout
, 60000);
1191 ngx_conf_merge_msec_value(conf
->upstream
.send_timeout
,
1192 prev
->upstream
.send_timeout
, 60000);
1194 ngx_conf_merge_msec_value(conf
->upstream
.read_timeout
,
1195 prev
->upstream
.read_timeout
, 60000);
1197 ngx_conf_merge_size_value(conf
->upstream
.send_lowat
,
1198 prev
->upstream
.send_lowat
, 0);
1200 ngx_conf_merge_size_value(conf
->upstream
.buffer_size
,
1201 prev
->upstream
.buffer_size
,
1202 (size_t) ngx_pagesize
);
1205 ngx_conf_merge_bufs_value(conf
->upstream
.bufs
, prev
->upstream
.bufs
,
1208 if (conf
->upstream
.bufs
.num
< 2) {
1209 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1210 "there must be at least 2 \"uwsgi_buffers\"");
1211 return NGX_CONF_ERROR
;
1215 size
= conf
->upstream
.buffer_size
;
1216 if (size
< conf
->upstream
.bufs
.size
) {
1217 size
= conf
->upstream
.bufs
.size
;
1221 ngx_conf_merge_size_value(conf
->upstream
.busy_buffers_size_conf
,
1222 prev
->upstream
.busy_buffers_size_conf
,
1223 NGX_CONF_UNSET_SIZE
);
1225 if (conf
->upstream
.busy_buffers_size_conf
== NGX_CONF_UNSET_SIZE
) {
1226 conf
->upstream
.busy_buffers_size
= 2 * size
;
1228 conf
->upstream
.busy_buffers_size
=
1229 conf
->upstream
.busy_buffers_size_conf
;
1232 if (conf
->upstream
.busy_buffers_size
< size
) {
1233 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1234 "\"uwsgi_busy_buffers_size\" must be equal to or greater "
1235 "than the maximum of the value of \"uwsgi_buffer_size\" and "
1236 "one of the \"uwsgi_buffers\"");
1238 return NGX_CONF_ERROR
;
1241 if (conf
->upstream
.busy_buffers_size
1242 > (conf
->upstream
.bufs
.num
- 1) * conf
->upstream
.bufs
.size
)
1244 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1245 "\"uwsgi_busy_buffers_size\" must be less than "
1246 "the size of all \"uwsgi_buffers\" minus one buffer");
1248 return NGX_CONF_ERROR
;
1252 ngx_conf_merge_size_value(conf
->upstream
.temp_file_write_size_conf
,
1253 prev
->upstream
.temp_file_write_size_conf
,
1254 NGX_CONF_UNSET_SIZE
);
1256 if (conf
->upstream
.temp_file_write_size_conf
== NGX_CONF_UNSET_SIZE
) {
1257 conf
->upstream
.temp_file_write_size
= 2 * size
;
1259 conf
->upstream
.temp_file_write_size
=
1260 conf
->upstream
.temp_file_write_size_conf
;
1263 if (conf
->upstream
.temp_file_write_size
< size
) {
1264 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1265 "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
1266 "the maximum of the value of \"uwsgi_buffer_size\" and "
1267 "one of the \"uwsgi_buffers\"");
1269 return NGX_CONF_ERROR
;
1273 ngx_conf_merge_size_value(conf
->upstream
.max_temp_file_size_conf
,
1274 prev
->upstream
.max_temp_file_size_conf
,
1275 NGX_CONF_UNSET_SIZE
);
1277 if (conf
->upstream
.max_temp_file_size_conf
== NGX_CONF_UNSET_SIZE
) {
1278 conf
->upstream
.max_temp_file_size
= 1024 * 1024 * 1024;
1280 conf
->upstream
.max_temp_file_size
=
1281 conf
->upstream
.max_temp_file_size_conf
;
1284 if (conf
->upstream
.max_temp_file_size
!= 0
1285 && conf
->upstream
.max_temp_file_size
< size
) {
1286 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1287 "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
1288 "temporary files usage or must be equal to or greater than "
1289 "the maximum of the value of \"uwsgi_buffer_size\" and "
1290 "one of the \"uwsgi_buffers\"");
1292 return NGX_CONF_ERROR
;
1296 ngx_conf_merge_bitmask_value(conf
->upstream
.ignore_headers
,
1297 prev
->upstream
.ignore_headers
,
1298 NGX_CONF_BITMASK_SET
);
1301 ngx_conf_merge_bitmask_value(conf
->upstream
.next_upstream
,
1302 prev
->upstream
.next_upstream
,
1303 (NGX_CONF_BITMASK_SET
1304 |NGX_HTTP_UPSTREAM_FT_ERROR
1305 |NGX_HTTP_UPSTREAM_FT_TIMEOUT
));
1307 if (conf
->upstream
.next_upstream
& NGX_HTTP_UPSTREAM_FT_OFF
) {
1308 conf
->upstream
.next_upstream
= NGX_CONF_BITMASK_SET
1309 |NGX_HTTP_UPSTREAM_FT_OFF
;
1312 if (ngx_conf_merge_path_value(cf
, &conf
->upstream
.temp_path
,
1313 prev
->upstream
.temp_path
,
1314 &ngx_http_uwsgi_temp_path
)
1317 return NGX_CONF_ERROR
;
1320 #if (NGX_HTTP_CACHE)
1322 ngx_conf_merge_ptr_value(conf
->upstream
.cache
,
1323 prev
->upstream
.cache
, NULL
);
1325 if (conf
->upstream
.cache
&& conf
->upstream
.cache
->data
== NULL
) {
1326 ngx_shm_zone_t
*shm_zone
;
1328 shm_zone
= conf
->upstream
.cache
;
1330 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1331 "\"uwsgi_cache\" zone \"%V\" is unknown",
1332 &shm_zone
->shm
.name
);
1334 return NGX_CONF_ERROR
;
1337 ngx_conf_merge_uint_value(conf
->upstream
.cache_min_uses
,
1338 prev
->upstream
.cache_min_uses
, 1);
1340 ngx_conf_merge_bitmask_value(conf
->upstream
.cache_use_stale
,
1341 prev
->upstream
.cache_use_stale
,
1342 (NGX_CONF_BITMASK_SET
1343 |NGX_HTTP_UPSTREAM_FT_OFF
));
1345 if (conf
->upstream
.cache_use_stale
& NGX_HTTP_UPSTREAM_FT_OFF
) {
1346 conf
->upstream
.cache_use_stale
= NGX_CONF_BITMASK_SET
1347 |NGX_HTTP_UPSTREAM_FT_OFF
;
1350 if (conf
->upstream
.cache_use_stale
& NGX_HTTP_UPSTREAM_FT_ERROR
) {
1351 conf
->upstream
.cache_use_stale
|= NGX_HTTP_UPSTREAM_FT_NOLIVE
;
1354 if (conf
->upstream
.cache_methods
== 0) {
1355 conf
->upstream
.cache_methods
= prev
->upstream
.cache_methods
;
1358 conf
->upstream
.cache_methods
|= NGX_HTTP_GET
|NGX_HTTP_HEAD
;
1360 ngx_conf_merge_ptr_value(conf
->upstream
.cache_bypass
,
1361 prev
->upstream
.cache_bypass
, NULL
);
1363 ngx_conf_merge_ptr_value(conf
->upstream
.no_cache
,
1364 prev
->upstream
.no_cache
, NULL
);
1366 ngx_conf_merge_ptr_value(conf
->upstream
.cache_valid
,
1367 prev
->upstream
.cache_valid
, NULL
);
1369 if (conf
->cache_key
.value
.data
== NULL
) {
1370 conf
->cache_key
= prev
->cache_key
;
1373 ngx_conf_merge_value(conf
->upstream
.cache_lock
,
1374 prev
->upstream
.cache_lock
, 0);
1376 ngx_conf_merge_msec_value(conf
->upstream
.cache_lock_timeout
,
1377 prev
->upstream
.cache_lock_timeout
, 5000);
1381 ngx_conf_merge_value(conf
->upstream
.pass_request_headers
,
1382 prev
->upstream
.pass_request_headers
, 1);
1383 ngx_conf_merge_value(conf
->upstream
.pass_request_body
,
1384 prev
->upstream
.pass_request_body
, 1);
1386 ngx_conf_merge_value(conf
->upstream
.intercept_errors
,
1387 prev
->upstream
.intercept_errors
, 0);
1389 ngx_conf_merge_str_value(conf
->uwsgi_string
, prev
->uwsgi_string
, "");
1391 hash
.max_size
= 512;
1392 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
1393 hash
.name
= "uwsgi_hide_headers_hash";
1395 if (ngx_http_upstream_hide_headers_hash(cf
, &conf
->upstream
,
1396 &prev
->upstream
, ngx_http_uwsgi_hide_headers
, &hash
)
1399 return NGX_CONF_ERROR
;
1402 if (conf
->upstream
.upstream
== NULL
) {
1403 conf
->upstream
.upstream
= prev
->upstream
.upstream
;
1406 if (conf
->uwsgi_lengths
== NULL
) {
1407 conf
->uwsgi_lengths
= prev
->uwsgi_lengths
;
1408 conf
->uwsgi_values
= prev
->uwsgi_values
;
1411 if (conf
->upstream
.upstream
|| conf
->uwsgi_lengths
) {
1412 clcf
= ngx_http_conf_get_module_loc_conf(cf
, ngx_http_core_module
);
1413 if (clcf
->handler
== NULL
&& clcf
->lmt_excpt
) {
1414 clcf
->handler
= ngx_http_uwsgi_handler
;
1418 ngx_conf_merge_uint_value(conf
->modifier1
, prev
->modifier1
, 0);
1419 ngx_conf_merge_uint_value(conf
->modifier2
, prev
->modifier2
, 0);
1421 if (ngx_http_uwsgi_merge_params(cf
, conf
, prev
) != NGX_OK
) {
1422 return NGX_CONF_ERROR
;
1430 ngx_http_uwsgi_merge_params(ngx_conf_t
*cf
, ngx_http_uwsgi_loc_conf_t
*conf
,
1431 ngx_http_uwsgi_loc_conf_t
*prev
)
1437 ngx_array_t headers_names
;
1438 #if (NGX_HTTP_CACHE)
1439 ngx_array_t params_merged
;
1442 ngx_hash_init_t hash
;
1443 ngx_http_upstream_param_t
*src
;
1444 ngx_http_script_compile_t sc
;
1445 ngx_http_script_copy_code_t
*copy
;
1447 if (conf
->params_source
== NULL
) {
1448 conf
->params_source
= prev
->params_source
;
1450 if (prev
->headers_hash
.buckets
1451 #if (NGX_HTTP_CACHE)
1452 && ((conf
->upstream
.cache
== NULL
)
1453 == (prev
->upstream
.cache
== NULL
))
1457 conf
->flushes
= prev
->flushes
;
1458 conf
->params_len
= prev
->params_len
;
1459 conf
->params
= prev
->params
;
1460 conf
->headers_hash
= prev
->headers_hash
;
1461 conf
->header_params
= prev
->header_params
;
1467 if (conf
->params_source
== NULL
1468 #if (NGX_HTTP_CACHE)
1469 && (conf
->upstream
.cache
== NULL
)
1473 conf
->headers_hash
.buckets
= (void *) 1;
1477 conf
->params_len
= ngx_array_create(cf
->pool
, 64, 1);
1478 if (conf
->params_len
== NULL
) {
1482 conf
->params
= ngx_array_create(cf
->pool
, 512, 1);
1483 if (conf
->params
== NULL
) {
1487 if (ngx_array_init(&headers_names
, cf
->temp_pool
, 4, sizeof(ngx_hash_key_t
))
1493 if (conf
->params_source
) {
1494 src
= conf
->params_source
->elts
;
1495 nsrc
= conf
->params_source
->nelts
;
1502 #if (NGX_HTTP_CACHE)
1504 if (conf
->upstream
.cache
) {
1506 ngx_http_upstream_param_t
*s
;
1508 if (ngx_array_init(¶ms_merged
, cf
->temp_pool
, 4,
1509 sizeof(ngx_http_upstream_param_t
))
1515 for (i
= 0; i
< nsrc
; i
++) {
1517 s
= ngx_array_push(¶ms_merged
);
1525 h
= ngx_http_uwsgi_cache_headers
;
1527 while (h
->key
.len
) {
1529 src
= params_merged
.elts
;
1530 nsrc
= params_merged
.nelts
;
1532 for (i
= 0; i
< nsrc
; i
++) {
1533 if (ngx_strcasecmp(h
->key
.data
, src
[i
].key
.data
) == 0) {
1538 s
= ngx_array_push(¶ms_merged
);
1544 s
->value
= h
->value
;
1552 src
= params_merged
.elts
;
1553 nsrc
= params_merged
.nelts
;
1558 for (i
= 0; i
< nsrc
; i
++) {
1560 if (src
[i
].key
.len
> sizeof("HTTP_") - 1
1561 && ngx_strncmp(src
[i
].key
.data
, "HTTP_", sizeof("HTTP_") - 1) == 0)
1563 hk
= ngx_array_push(&headers_names
);
1568 hk
->key
.len
= src
[i
].key
.len
- 5;
1569 hk
->key
.data
= src
[i
].key
.data
+ 5;
1570 hk
->key_hash
= ngx_hash_key_lc(hk
->key
.data
, hk
->key
.len
);
1571 hk
->value
= (void *) 1;
1573 if (src
[i
].value
.len
== 0) {
1578 copy
= ngx_array_push_n(conf
->params_len
,
1579 sizeof(ngx_http_script_copy_code_t
));
1584 copy
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
1585 copy
->len
= src
[i
].key
.len
;
1587 copy
= ngx_array_push_n(conf
->params_len
,
1588 sizeof(ngx_http_script_copy_code_t
));
1593 copy
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
1594 copy
->len
= src
[i
].skip_empty
;
1597 size
= (sizeof(ngx_http_script_copy_code_t
)
1598 + src
[i
].key
.len
+ sizeof(uintptr_t) - 1)
1599 & ~(sizeof(uintptr_t) - 1);
1601 copy
= ngx_array_push_n(conf
->params
, size
);
1606 copy
->code
= ngx_http_script_copy_code
;
1607 copy
->len
= src
[i
].key
.len
;
1609 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
1610 ngx_memcpy(p
, src
[i
].key
.data
, src
[i
].key
.len
);
1613 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1616 sc
.source
= &src
[i
].value
;
1617 sc
.flushes
= &conf
->flushes
;
1618 sc
.lengths
= &conf
->params_len
;
1619 sc
.values
= &conf
->params
;
1621 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1625 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
1630 *code
= (uintptr_t) NULL
;
1633 code
= ngx_array_push_n(conf
->params
, sizeof(uintptr_t));
1638 *code
= (uintptr_t) NULL
;
1641 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
1646 *code
= (uintptr_t) NULL
;
1648 conf
->header_params
= headers_names
.nelts
;
1650 hash
.hash
= &conf
->headers_hash
;
1651 hash
.key
= ngx_hash_key_lc
;
1652 hash
.max_size
= 512;
1653 hash
.bucket_size
= 64;
1654 hash
.name
= "uwsgi_params_hash";
1655 hash
.pool
= cf
->pool
;
1656 hash
.temp_pool
= NULL
;
1658 return ngx_hash_init(&hash
, headers_names
.elts
, headers_names
.nelts
);
1663 ngx_http_uwsgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1665 ngx_http_uwsgi_loc_conf_t
*uwcf
= conf
;
1668 ngx_str_t
*value
, *url
;
1670 ngx_http_core_loc_conf_t
*clcf
;
1671 ngx_http_script_compile_t sc
;
1673 if (uwcf
->upstream
.upstream
|| uwcf
->uwsgi_lengths
) {
1674 return "is duplicate";
1677 clcf
= ngx_http_conf_get_module_loc_conf (cf
, ngx_http_core_module
);
1678 clcf
->handler
= ngx_http_uwsgi_handler
;
1680 value
= cf
->args
->elts
;
1684 n
= ngx_http_script_variables_count(url
);
1688 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1692 sc
.lengths
= &uwcf
->uwsgi_lengths
;
1693 sc
.values
= &uwcf
->uwsgi_values
;
1695 sc
.complete_lengths
= 1;
1696 sc
.complete_values
= 1;
1698 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1699 return NGX_CONF_ERROR
;
1705 ngx_memzero(&u
, sizeof(ngx_url_t
));
1710 uwcf
->upstream
.upstream
= ngx_http_upstream_add(cf
, &u
, 0);
1711 if (uwcf
->upstream
.upstream
== NULL
) {
1712 return NGX_CONF_ERROR
;
1715 if (clcf
->name
.data
[clcf
->name
.len
- 1] == '/') {
1716 clcf
->auto_redirect
= 1;
1724 ngx_http_uwsgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1726 ngx_http_uwsgi_loc_conf_t
*uwcf
= conf
;
1729 ngx_http_script_compile_t sc
;
1731 if (uwcf
->upstream
.store
!= NGX_CONF_UNSET
|| uwcf
->upstream
.store_lengths
)
1733 return "is duplicate";
1736 value
= cf
->args
->elts
;
1738 if (ngx_strcmp(value
[1].data
, "off") == 0) {
1739 uwcf
->upstream
.store
= 0;
1743 #if (NGX_HTTP_CACHE)
1745 if (uwcf
->upstream
.cache
!= NGX_CONF_UNSET_PTR
1746 && uwcf
->upstream
.cache
!= NULL
)
1748 return "is incompatible with \"uwsgi_cache\"";
1753 if (ngx_strcmp(value
[1].data
, "on") == 0) {
1754 uwcf
->upstream
.store
= 1;
1758 /* include the terminating '\0' into script */
1761 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1764 sc
.source
= &value
[1];
1765 sc
.lengths
= &uwcf
->upstream
.store_lengths
;
1766 sc
.values
= &uwcf
->upstream
.store_values
;
1767 sc
.variables
= ngx_http_script_variables_count(&value
[1]);;
1768 sc
.complete_lengths
= 1;
1769 sc
.complete_values
= 1;
1771 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1772 return NGX_CONF_ERROR
;
1779 #if (NGX_HTTP_CACHE)
1782 ngx_http_uwsgi_cache(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1784 ngx_http_uwsgi_loc_conf_t
*uwcf
= conf
;
1788 value
= cf
->args
->elts
;
1790 if (uwcf
->upstream
.cache
!= NGX_CONF_UNSET_PTR
) {
1791 return "is duplicate";
1794 if (ngx_strcmp(value
[1].data
, "off") == 0) {
1795 uwcf
->upstream
.cache
= NULL
;
1799 if (uwcf
->upstream
.store
> 0 || uwcf
->upstream
.store_lengths
) {
1800 return "is incompatible with \"uwsgi_store\"";
1803 uwcf
->upstream
.cache
= ngx_shared_memory_add(cf
, &value
[1], 0,
1804 &ngx_http_uwsgi_module
);
1805 if (uwcf
->upstream
.cache
== NULL
) {
1806 return NGX_CONF_ERROR
;
1814 ngx_http_uwsgi_cache_key(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
1816 ngx_http_uwsgi_loc_conf_t
*uwcf
= conf
;
1819 ngx_http_compile_complex_value_t ccv
;
1821 value
= cf
->args
->elts
;
1823 if (uwcf
->cache_key
.value
.data
) {
1824 return "is duplicate";
1827 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
1830 ccv
.value
= &value
[1];
1831 ccv
.complex_value
= &uwcf
->cache_key
;
1833 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
1834 return NGX_CONF_ERROR
;