Mercurial > hg > nginx
annotate src/http/modules/ngx_http_scgi_module.c @ 4253:6efec8b1ff52 stable-1.0
Merging r4193, r4194:
Autoindex fixes:
*) Autoindex: escape '?' in file names.
For files with '?' in their names autoindex generated links with '?' not
escaped. This resulted in effectively truncated links as '?' indicates
query string start.
This is an updated version of the patch originally posted at [1]. It
introduces generic NGX_ESCAPE_URI_COMPONENT which escapes everything but
unreserved characters as per RFC 3986. This approach also renders unneeded
special colon processing (as colon is percent-encoded now), it's dropped
accordingly.
[1] http://nginx.org/pipermail/nginx-devel/2010-February/000112.html
*) Autoindex: escape html in file names.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 01 Nov 2011 14:09:15 +0000 |
parents | 94049ec3eeda |
children | e4b8255e44c3 94b995c7c614 |
rev | line source |
---|---|
3637 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 * Copyright (C) Manlio Perillo (manlio.perillo@gmail.com) | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_http_upstream_conf_t upstream; | |
15 | |
16 ngx_array_t *flushes; | |
17 ngx_array_t *params_len; | |
18 ngx_array_t *params; | |
19 ngx_array_t *params_source; | |
20 | |
21 ngx_hash_t headers_hash; | |
22 ngx_uint_t header_params; | |
23 | |
24 ngx_array_t *scgi_lengths; | |
25 ngx_array_t *scgi_values; | |
26 | |
27 #if (NGX_HTTP_CACHE) | |
28 ngx_http_complex_value_t cache_key; | |
29 #endif | |
30 } ngx_http_scgi_loc_conf_t; | |
31 | |
32 | |
33 static ngx_int_t ngx_http_scgi_eval(ngx_http_request_t *r, | |
34 ngx_http_scgi_loc_conf_t *scf); | |
35 static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r); | |
36 static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r); | |
37 static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r); | |
38 static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r); | |
39 static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r); | |
40 static void ngx_http_scgi_abort_request(ngx_http_request_t *r); | |
41 static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc); | |
42 | |
43 static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf); | |
44 static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, | |
45 void *child); | |
46 | |
47 static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
48 static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, | |
49 void *conf); | |
50 | |
51 #if (NGX_HTTP_CACHE) | |
52 static ngx_int_t ngx_http_scgi_create_key(ngx_http_request_t *r); | |
53 static char *ngx_http_scgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, | |
54 void *conf); | |
55 static char *ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, | |
56 void *conf); | |
57 #endif | |
58 | |
59 | |
60 static ngx_conf_bitmask_t ngx_http_scgi_next_upstream_masks[] = { | |
61 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, | |
62 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, | |
63 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, | |
64 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, | |
65 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, | |
66 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, | |
67 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, | |
68 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, | |
69 { ngx_null_string, 0 } | |
70 }; | |
71 | |
72 | |
73 ngx_module_t ngx_http_scgi_module; | |
74 | |
75 | |
76 static ngx_command_t ngx_http_scgi_commands[] = { | |
77 | |
78 { ngx_string("scgi_pass"), | |
79 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, | |
80 ngx_http_scgi_pass, | |
81 NGX_HTTP_LOC_CONF_OFFSET, | |
82 0, | |
83 NULL }, | |
84 | |
85 { ngx_string("scgi_store"), | |
86 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
87 ngx_http_scgi_store, | |
88 NGX_HTTP_LOC_CONF_OFFSET, | |
89 0, | |
90 NULL }, | |
91 | |
92 { ngx_string("scgi_store_access"), | |
93 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, | |
94 ngx_conf_set_access_slot, | |
95 NGX_HTTP_LOC_CONF_OFFSET, | |
96 offsetof(ngx_http_scgi_loc_conf_t, upstream.store_access), | |
97 NULL }, | |
98 | |
4252 | 99 { ngx_string("scgi_buffering"), |
100 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
101 ngx_conf_set_flag_slot, | |
102 NGX_HTTP_LOC_CONF_OFFSET, | |
103 offsetof(ngx_http_scgi_loc_conf_t, upstream.buffering), | |
104 NULL }, | |
105 | |
3637 | 106 { ngx_string("scgi_ignore_client_abort"), |
107 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
108 ngx_conf_set_flag_slot, | |
109 NGX_HTTP_LOC_CONF_OFFSET, | |
110 offsetof(ngx_http_scgi_loc_conf_t, upstream.ignore_client_abort), | |
111 NULL }, | |
112 | |
113 { ngx_string("scgi_bind"), | |
114 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
115 ngx_http_upstream_bind_set_slot, | |
116 NGX_HTTP_LOC_CONF_OFFSET, | |
117 offsetof(ngx_http_scgi_loc_conf_t, upstream.local), | |
118 NULL }, | |
119 | |
120 { ngx_string("scgi_connect_timeout"), | |
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
122 ngx_conf_set_msec_slot, | |
123 NGX_HTTP_LOC_CONF_OFFSET, | |
124 offsetof(ngx_http_scgi_loc_conf_t, upstream.connect_timeout), | |
125 NULL }, | |
126 | |
127 { ngx_string("scgi_send_timeout"), | |
128 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
129 ngx_conf_set_msec_slot, | |
130 NGX_HTTP_LOC_CONF_OFFSET, | |
131 offsetof(ngx_http_scgi_loc_conf_t, upstream.send_timeout), | |
132 NULL }, | |
133 | |
134 { ngx_string("scgi_buffer_size"), | |
135 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
136 ngx_conf_set_size_slot, | |
137 NGX_HTTP_LOC_CONF_OFFSET, | |
138 offsetof(ngx_http_scgi_loc_conf_t, upstream.buffer_size), | |
139 NULL }, | |
140 | |
141 { ngx_string("scgi_pass_request_headers"), | |
142 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
143 ngx_conf_set_flag_slot, | |
144 NGX_HTTP_LOC_CONF_OFFSET, | |
145 offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_request_headers), | |
146 NULL }, | |
147 | |
148 { ngx_string("scgi_pass_request_body"), | |
149 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
150 ngx_conf_set_flag_slot, | |
151 NGX_HTTP_LOC_CONF_OFFSET, | |
152 offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_request_body), | |
153 NULL }, | |
154 | |
155 { ngx_string("scgi_intercept_errors"), | |
156 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
157 ngx_conf_set_flag_slot, | |
158 NGX_HTTP_LOC_CONF_OFFSET, | |
159 offsetof(ngx_http_scgi_loc_conf_t, upstream.intercept_errors), | |
160 NULL }, | |
161 | |
162 { ngx_string("scgi_read_timeout"), | |
163 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
164 ngx_conf_set_msec_slot, | |
165 NGX_HTTP_LOC_CONF_OFFSET, | |
166 offsetof(ngx_http_scgi_loc_conf_t, upstream.read_timeout), | |
167 NULL }, | |
168 | |
169 { ngx_string("scgi_buffers"), | |
170 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
171 ngx_conf_set_bufs_slot, | |
172 NGX_HTTP_LOC_CONF_OFFSET, | |
173 offsetof(ngx_http_scgi_loc_conf_t, upstream.bufs), | |
174 NULL }, | |
175 | |
176 { ngx_string("scgi_busy_buffers_size"), | |
177 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
178 ngx_conf_set_size_slot, | |
179 NGX_HTTP_LOC_CONF_OFFSET, | |
180 offsetof(ngx_http_scgi_loc_conf_t, upstream.busy_buffers_size_conf), | |
181 NULL }, | |
182 | |
183 #if (NGX_HTTP_CACHE) | |
184 | |
185 { ngx_string("scgi_cache"), | |
3729 | 186 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3637 | 187 ngx_http_scgi_cache, |
188 NGX_HTTP_LOC_CONF_OFFSET, | |
189 0, | |
190 NULL }, | |
191 | |
192 { ngx_string("scgi_cache_key"), | |
3729 | 193 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3637 | 194 ngx_http_scgi_cache_key, |
195 NGX_HTTP_LOC_CONF_OFFSET, | |
196 0, | |
197 NULL }, | |
198 | |
199 { ngx_string("scgi_cache_path"), | |
200 NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, | |
201 ngx_http_file_cache_set_slot, | |
202 0, | |
203 0, | |
204 &ngx_http_scgi_module }, | |
205 | |
3699
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
206 { ngx_string("scgi_cache_bypass"), |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
207 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
208 ngx_http_set_predicate_slot, |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
209 NGX_HTTP_LOC_CONF_OFFSET, |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
210 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_bypass), |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
211 NULL }, |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
212 |
3637 | 213 { ngx_string("scgi_no_cache"), |
214 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
3692
045ea40cbfe8
use ngx_http_test_predicates(), ngx_http_set_predicate_slot()
Igor Sysoev <igor@sysoev.ru>
parents:
3670
diff
changeset
|
215 ngx_http_set_predicate_slot, |
3637 | 216 NGX_HTTP_LOC_CONF_OFFSET, |
217 offsetof(ngx_http_scgi_loc_conf_t, upstream.no_cache), | |
218 NULL }, | |
219 | |
220 { ngx_string("scgi_cache_valid"), | |
221 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
222 ngx_http_file_cache_valid_set_slot, | |
223 NGX_HTTP_LOC_CONF_OFFSET, | |
224 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_valid), | |
225 NULL }, | |
226 | |
227 { ngx_string("scgi_cache_min_uses"), | |
228 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
229 ngx_conf_set_num_slot, | |
230 NGX_HTTP_LOC_CONF_OFFSET, | |
231 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_min_uses), | |
232 NULL }, | |
233 | |
234 { ngx_string("scgi_cache_use_stale"), | |
235 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
236 ngx_conf_set_bitmask_slot, | |
237 NGX_HTTP_LOC_CONF_OFFSET, | |
238 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_use_stale), | |
239 &ngx_http_scgi_next_upstream_masks }, | |
240 | |
241 { ngx_string("scgi_cache_methods"), | |
242 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
243 ngx_conf_set_bitmask_slot, | |
244 NGX_HTTP_LOC_CONF_OFFSET, | |
245 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_methods), | |
246 &ngx_http_upstream_cache_method_mask }, | |
247 | |
248 #endif | |
249 | |
250 { ngx_string("scgi_temp_path"), | |
251 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, | |
252 ngx_conf_set_path_slot, | |
253 NGX_HTTP_LOC_CONF_OFFSET, | |
254 offsetof(ngx_http_scgi_loc_conf_t, upstream.temp_path), | |
255 NULL }, | |
256 | |
257 { ngx_string("scgi_max_temp_file_size"), | |
258 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
259 ngx_conf_set_size_slot, | |
260 NGX_HTTP_LOC_CONF_OFFSET, | |
261 offsetof(ngx_http_scgi_loc_conf_t, upstream.max_temp_file_size_conf), | |
262 NULL }, | |
263 | |
264 { ngx_string("scgi_temp_file_write_size"), | |
265 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
266 ngx_conf_set_size_slot, | |
267 NGX_HTTP_LOC_CONF_OFFSET, | |
268 offsetof(ngx_http_scgi_loc_conf_t, upstream.temp_file_write_size_conf), | |
269 NULL }, | |
270 | |
271 { ngx_string("scgi_next_upstream"), | |
272 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
273 ngx_conf_set_bitmask_slot, | |
274 NGX_HTTP_LOC_CONF_OFFSET, | |
275 offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream), | |
276 &ngx_http_scgi_next_upstream_masks }, | |
277 | |
278 { ngx_string("scgi_param"), | |
279 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
280 ngx_conf_set_keyval_slot, | |
281 NGX_HTTP_LOC_CONF_OFFSET, | |
282 offsetof(ngx_http_scgi_loc_conf_t, params_source), | |
283 NULL }, | |
284 | |
285 { ngx_string("scgi_pass_header"), | |
3729 | 286 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3637 | 287 ngx_conf_set_str_array_slot, |
288 NGX_HTTP_LOC_CONF_OFFSET, | |
289 offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_headers), | |
290 NULL }, | |
291 | |
292 { ngx_string("scgi_hide_header"), | |
3729 | 293 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3637 | 294 ngx_conf_set_str_array_slot, |
295 NGX_HTTP_LOC_CONF_OFFSET, | |
296 offsetof(ngx_http_scgi_loc_conf_t, upstream.hide_headers), | |
297 NULL }, | |
298 | |
299 { ngx_string("scgi_ignore_headers"), | |
300 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
301 ngx_conf_set_bitmask_slot, | |
302 NGX_HTTP_LOC_CONF_OFFSET, | |
303 offsetof(ngx_http_scgi_loc_conf_t, upstream.ignore_headers), | |
3667
12bd9e26fadb
use shared ngx_http_upstream_ignore_headers_masks[]
Igor Sysoev <igor@sysoev.ru>
parents:
3637
diff
changeset
|
304 &ngx_http_upstream_ignore_headers_masks }, |
3637 | 305 |
306 ngx_null_command | |
307 }; | |
308 | |
309 | |
310 static ngx_http_module_t ngx_http_scgi_module_ctx = { | |
311 NULL, /* preconfiguration */ | |
312 NULL, /* postconfiguration */ | |
313 | |
314 NULL, /* create main configuration */ | |
315 NULL, /* init main configuration */ | |
316 | |
317 NULL, /* create server configuration */ | |
318 NULL, /* merge server configuration */ | |
319 | |
320 ngx_http_scgi_create_loc_conf, /* create location configuration */ | |
321 ngx_http_scgi_merge_loc_conf /* merge location configuration */ | |
322 }; | |
323 | |
324 | |
325 ngx_module_t ngx_http_scgi_module = { | |
326 NGX_MODULE_V1, | |
327 &ngx_http_scgi_module_ctx, /* module context */ | |
328 ngx_http_scgi_commands, /* module directives */ | |
329 NGX_HTTP_MODULE, /* module type */ | |
330 NULL, /* init master */ | |
331 NULL, /* init module */ | |
332 NULL, /* init process */ | |
333 NULL, /* init thread */ | |
334 NULL, /* exit thread */ | |
335 NULL, /* exit process */ | |
336 NULL, /* exit master */ | |
337 NGX_MODULE_V1_PADDING | |
338 }; | |
339 | |
340 | |
341 static ngx_str_t ngx_http_scgi_hide_headers[] = { | |
342 ngx_string("Status"), | |
343 ngx_string("X-Accel-Expires"), | |
344 ngx_string("X-Accel-Redirect"), | |
345 ngx_string("X-Accel-Limit-Rate"), | |
346 ngx_string("X-Accel-Buffering"), | |
347 ngx_string("X-Accel-Charset"), | |
348 ngx_null_string | |
349 }; | |
350 | |
351 | |
352 #if (NGX_HTTP_CACHE) | |
353 | |
354 static ngx_keyval_t ngx_http_scgi_cache_headers[] = { | |
355 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") }, | |
356 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") }, | |
357 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") }, | |
358 { ngx_string("HTTP_IF_MATCH"), ngx_string("") }, | |
359 { ngx_string("HTTP_RANGE"), ngx_string("") }, | |
360 { ngx_string("HTTP_IF_RANGE"), ngx_string("") }, | |
361 { ngx_null_string, ngx_null_string } | |
362 }; | |
363 | |
364 #endif | |
365 | |
366 | |
367 static ngx_path_init_t ngx_http_scgi_temp_path = { | |
368 ngx_string(NGX_HTTP_SCGI_TEMP_PATH), { 1, 2, 0 } | |
369 }; | |
370 | |
371 | |
372 static ngx_int_t | |
373 ngx_http_scgi_handler(ngx_http_request_t *r) | |
374 { | |
375 ngx_int_t rc; | |
376 ngx_http_status_t *status; | |
377 ngx_http_upstream_t *u; | |
378 ngx_http_scgi_loc_conf_t *scf; | |
379 | |
380 if (r->subrequest_in_memory) { | |
381 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
382 "ngx_http_scgi_module does not support " | |
383 "subrequests in memory"); | |
384 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
385 } | |
386 | |
387 if (ngx_http_upstream_create(r) != NGX_OK) { | |
388 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
389 } | |
390 | |
391 status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t)); | |
392 if (status == NULL) { | |
393 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
394 } | |
395 | |
396 ngx_http_set_ctx(r, status, ngx_http_scgi_module); | |
397 | |
398 scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module); | |
399 | |
400 if (scf->scgi_lengths) { | |
401 if (ngx_http_scgi_eval(r, scf) != NGX_OK) { | |
402 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
403 } | |
404 } | |
405 | |
406 u = r->upstream; | |
407 | |
408 ngx_str_set(&u->schema, "scgi://"); | |
409 u->output.tag = (ngx_buf_tag_t) &ngx_http_scgi_module; | |
410 | |
411 u->conf = &scf->upstream; | |
412 | |
413 #if (NGX_HTTP_CACHE) | |
414 u->create_key = ngx_http_scgi_create_key; | |
415 #endif | |
416 u->create_request = ngx_http_scgi_create_request; | |
417 u->reinit_request = ngx_http_scgi_reinit_request; | |
418 u->process_header = ngx_http_scgi_process_status_line; | |
419 u->abort_request = ngx_http_scgi_abort_request; | |
420 u->finalize_request = ngx_http_scgi_finalize_request; | |
421 | |
4252 | 422 u->buffering = scf->upstream.buffering; |
3637 | 423 |
424 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); | |
425 if (u->pipe == NULL) { | |
426 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
427 } | |
428 | |
429 u->pipe->input_filter = ngx_event_pipe_copy_input_filter; | |
430 u->pipe->input_ctx = r; | |
431 | |
432 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); | |
433 | |
434 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
435 return rc; | |
436 } | |
437 | |
438 return NGX_DONE; | |
439 } | |
440 | |
441 | |
442 static ngx_int_t | |
443 ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf) | |
444 { | |
445 ngx_url_t url; | |
446 ngx_http_upstream_t *u; | |
447 | |
448 ngx_memzero(&url, sizeof(ngx_url_t)); | |
449 | |
450 if (ngx_http_script_run(r, &url.url, scf->scgi_lengths->elts, 0, | |
451 scf->scgi_values->elts) | |
452 == NULL) | |
453 { | |
454 return NGX_ERROR; | |
455 } | |
456 | |
457 url.no_resolve = 1; | |
458 | |
459 if (ngx_parse_url(r->pool, &url) != NGX_OK) { | |
460 if (url.err) { | |
461 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
462 "%s in upstream \"%V\"", url.err, &url.url); | |
463 } | |
464 | |
465 return NGX_ERROR; | |
466 } | |
467 | |
468 u = r->upstream; | |
469 | |
470 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); | |
471 if (u->resolved == NULL) { | |
472 return NGX_ERROR; | |
473 } | |
474 | |
475 if (url.addrs && url.addrs[0].sockaddr) { | |
476 u->resolved->sockaddr = url.addrs[0].sockaddr; | |
477 u->resolved->socklen = url.addrs[0].socklen; | |
478 u->resolved->naddrs = 1; | |
479 u->resolved->host = url.addrs[0].name; | |
480 | |
481 } else { | |
482 u->resolved->host = url.host; | |
483 u->resolved->port = url.port; | |
3879
502a6b0acf3f
fix case when a host in fastcgi_pass, scgi_pass, and uwsgi_pass
Igor Sysoev <igor@sysoev.ru>
parents:
3731
diff
changeset
|
484 u->resolved->no_port = url.no_port; |
3637 | 485 } |
486 | |
487 return NGX_OK; | |
488 } | |
489 | |
490 | |
491 #if (NGX_HTTP_CACHE) | |
492 | |
493 static ngx_int_t | |
494 ngx_http_scgi_create_key(ngx_http_request_t *r) | |
495 { | |
496 ngx_str_t *key; | |
497 ngx_http_scgi_loc_conf_t *scf; | |
498 | |
499 key = ngx_array_push(&r->cache->keys); | |
500 if (key == NULL) { | |
501 return NGX_ERROR; | |
502 } | |
503 | |
504 scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module); | |
505 | |
506 if (ngx_http_complex_value(r, &scf->cache_key, key) != NGX_OK) { | |
507 return NGX_ERROR; | |
508 } | |
509 | |
510 return NGX_OK; | |
511 } | |
512 | |
513 #endif | |
514 | |
515 | |
516 static ngx_int_t | |
517 ngx_http_scgi_create_request(ngx_http_request_t *r) | |
518 { | |
519 u_char ch, *key, *val, *lowcase_key; | |
520 size_t len, allocated; | |
521 ngx_buf_t *b; | |
522 ngx_str_t *content_length; | |
523 ngx_uint_t i, n, hash, header_params; | |
524 ngx_chain_t *cl, *body; | |
525 ngx_list_part_t *part; | |
526 ngx_table_elt_t *header, **ignored; | |
527 ngx_http_script_code_pt code; | |
528 ngx_http_script_engine_t e, le; | |
529 ngx_http_scgi_loc_conf_t *scf; | |
530 ngx_http_script_len_code_pt lcode; | |
531 static ngx_str_t zero = ngx_string("0"); | |
532 | |
533 content_length = r->headers_in.content_length ? | |
534 &r->headers_in.content_length->value : &zero; | |
535 | |
536 len = sizeof("CONTENT_LENGTH") + content_length->len + 1; | |
537 | |
538 header_params = 0; | |
539 ignored = NULL; | |
540 | |
541 scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module); | |
542 | |
543 if (scf->params_len) { | |
544 ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); | |
545 | |
546 ngx_http_script_flush_no_cacheable_variables(r, scf->flushes); | |
547 le.flushed = 1; | |
548 | |
549 le.ip = scf->params_len->elts; | |
550 le.request = r; | |
551 | |
552 while (*(uintptr_t *) le.ip) { | |
553 | |
554 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
555 len += lcode(&le); | |
556 | |
557 while (*(uintptr_t *) le.ip) { | |
558 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
559 len += lcode(&le) + 1; | |
560 } | |
561 le.ip += sizeof(uintptr_t); | |
562 } | |
563 } | |
564 | |
565 if (scf->upstream.pass_request_headers) { | |
566 | |
567 allocated = 0; | |
568 lowcase_key = NULL; | |
569 | |
570 if (scf->header_params) { | |
4050 | 571 n = 0; |
572 part = &r->headers_in.headers.part; | |
573 | |
574 while (part) { | |
575 n += part->nelts; | |
576 part = part->next; | |
577 } | |
578 | |
579 ignored = ngx_palloc(r->pool, n * sizeof(void *)); | |
3637 | 580 if (ignored == NULL) { |
581 return NGX_ERROR; | |
582 } | |
583 } | |
584 | |
585 part = &r->headers_in.headers.part; | |
586 header = part->elts; | |
587 | |
588 for (i = 0; /* void */; i++) { | |
589 | |
590 if (i >= part->nelts) { | |
591 if (part->next == NULL) { | |
592 break; | |
593 } | |
594 | |
595 part = part->next; | |
596 header = part->elts; | |
597 i = 0; | |
598 } | |
599 | |
600 if (scf->header_params) { | |
601 if (allocated < header[i].key.len) { | |
602 allocated = header[i].key.len + 16; | |
603 lowcase_key = ngx_pnalloc(r->pool, allocated); | |
604 if (lowcase_key == NULL) { | |
605 return NGX_ERROR; | |
606 } | |
607 } | |
608 | |
609 hash = 0; | |
610 | |
611 for (n = 0; n < header[i].key.len; n++) { | |
612 ch = header[i].key.data[n]; | |
613 | |
614 if (ch >= 'A' && ch <= 'Z') { | |
615 ch |= 0x20; | |
616 | |
617 } else if (ch == '-') { | |
618 ch = '_'; | |
619 } | |
620 | |
621 hash = ngx_hash(hash, ch); | |
622 lowcase_key[n] = ch; | |
623 } | |
624 | |
625 if (ngx_hash_find(&scf->headers_hash, hash, lowcase_key, n)) { | |
626 ignored[header_params++] = &header[i]; | |
627 continue; | |
628 } | |
629 } | |
630 | |
631 len += sizeof("HTTP_") - 1 + header[i].key.len + 1 | |
632 + header[i].value.len + 1; | |
633 } | |
634 } | |
635 | |
636 /* netstring: "length:" + packet + "," */ | |
637 | |
638 b = ngx_create_temp_buf(r->pool, NGX_SIZE_T_LEN + 1 + len + 1); | |
639 if (b == NULL) { | |
640 return NGX_ERROR; | |
641 } | |
642 | |
643 cl = ngx_alloc_chain_link(r->pool); | |
644 if (cl == NULL) { | |
645 return NGX_ERROR; | |
646 } | |
647 | |
648 cl->buf = b; | |
649 | |
650 b->last = ngx_snprintf(b->last, | |
651 NGX_SIZE_T_LEN + 1 + sizeof("CONTENT_LENGTH") | |
652 + NGX_OFF_T_LEN + 1, | |
653 "%ui:CONTENT_LENGTH%Z%V%Z", | |
654 len, content_length); | |
655 | |
656 if (scf->params_len) { | |
657 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
658 | |
659 e.ip = scf->params->elts; | |
660 e.pos = b->last; | |
661 e.request = r; | |
662 e.flushed = 1; | |
663 | |
664 while (*(uintptr_t *) e.ip) { | |
665 | |
666 #if (NGX_DEBUG) | |
667 key = e.pos; | |
668 #endif | |
669 code = *(ngx_http_script_code_pt *) e.ip; | |
670 code((ngx_http_script_engine_t *) & e); | |
671 | |
672 #if (NGX_DEBUG) | |
673 val = e.pos; | |
674 #endif | |
675 while (*(uintptr_t *) e.ip) { | |
676 code = *(ngx_http_script_code_pt *) e.ip; | |
677 code((ngx_http_script_engine_t *) &e); | |
678 } | |
679 *e.pos++ = '\0'; | |
680 e.ip += sizeof(uintptr_t); | |
681 | |
682 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
683 "scgi param: \"%s: %s\"", key, val); | |
684 } | |
685 | |
686 b->last = e.pos; | |
687 } | |
688 | |
689 if (scf->upstream.pass_request_headers) { | |
690 | |
691 part = &r->headers_in.headers.part; | |
692 header = part->elts; | |
693 | |
694 for (i = 0; /* void */; i++) { | |
695 | |
696 if (i >= part->nelts) { | |
697 if (part->next == NULL) { | |
698 break; | |
699 } | |
700 | |
701 part = part->next; | |
702 header = part->elts; | |
703 i = 0; | |
704 } | |
705 | |
706 for (n = 0; n < header_params; n++) { | |
707 if (&header[i] == ignored[n]) { | |
708 goto next; | |
709 } | |
710 } | |
711 | |
712 key = b->last; | |
713 b->last = ngx_cpymem(key, "HTTP_", sizeof("HTTP_") - 1); | |
714 | |
715 for (n = 0; n < header[i].key.len; n++) { | |
716 ch = header[i].key.data[n]; | |
717 | |
718 if (ch >= 'a' && ch <= 'z') { | |
719 ch &= ~0x20; | |
720 | |
721 } else if (ch == '-') { | |
722 ch = '_'; | |
723 } | |
724 | |
725 *b->last++ = ch; | |
726 } | |
727 | |
728 *b->last++ = (u_char) 0; | |
729 | |
730 val = b->last; | |
731 b->last = ngx_copy(val, header[i].value.data, header[i].value.len); | |
732 *b->last++ = (u_char) 0; | |
733 | |
734 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
735 "scgi param: \"%s: %s\"", key, val); | |
736 | |
737 next: | |
738 | |
739 continue; | |
740 } | |
741 } | |
742 | |
743 *b->last++ = (u_char) ','; | |
744 | |
745 if (scf->upstream.pass_request_body) { | |
746 body = r->upstream->request_bufs; | |
747 r->upstream->request_bufs = cl; | |
748 | |
749 while (body) { | |
750 b = ngx_alloc_buf(r->pool); | |
751 if (b == NULL) { | |
752 return NGX_ERROR; | |
753 } | |
754 | |
755 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); | |
756 | |
757 cl->next = ngx_alloc_chain_link(r->pool); | |
758 if (cl->next == NULL) { | |
759 return NGX_ERROR; | |
760 } | |
761 | |
762 cl = cl->next; | |
763 cl->buf = b; | |
764 | |
765 body = body->next; | |
766 } | |
767 | |
768 } else { | |
769 r->upstream->request_bufs = cl; | |
770 } | |
771 | |
772 cl->next = NULL; | |
773 | |
774 return NGX_OK; | |
775 } | |
776 | |
777 | |
778 static ngx_int_t | |
779 ngx_http_scgi_reinit_request(ngx_http_request_t *r) | |
780 { | |
781 ngx_http_status_t *status; | |
782 | |
783 status = ngx_http_get_module_ctx(r, ngx_http_scgi_module); | |
784 | |
785 if (status == NULL) { | |
786 return NGX_OK; | |
787 } | |
788 | |
789 status->code = 0; | |
790 status->count = 0; | |
791 status->start = NULL; | |
792 status->end = NULL; | |
793 | |
794 r->upstream->process_header = ngx_http_scgi_process_status_line; | |
795 | |
796 return NGX_OK; | |
797 } | |
798 | |
799 | |
800 static ngx_int_t | |
801 ngx_http_scgi_process_status_line(ngx_http_request_t *r) | |
802 { | |
803 size_t len; | |
804 ngx_int_t rc; | |
805 ngx_http_status_t *status; | |
806 ngx_http_upstream_t *u; | |
807 | |
808 status = ngx_http_get_module_ctx(r, ngx_http_scgi_module); | |
809 | |
810 if (status == NULL) { | |
811 return NGX_ERROR; | |
812 } | |
813 | |
814 u = r->upstream; | |
815 | |
816 rc = ngx_http_parse_status_line(r, &u->buffer, status); | |
817 | |
818 if (rc == NGX_AGAIN) { | |
819 return rc; | |
820 } | |
821 | |
822 if (rc == NGX_ERROR) { | |
823 | |
824 r->http_version = NGX_HTTP_VERSION_9; | |
825 | |
826 u->process_header = ngx_http_scgi_process_header; | |
827 | |
828 return ngx_http_scgi_process_header(r); | |
829 } | |
830 | |
831 if (u->state) { | |
832 u->state->status = status->code; | |
833 } | |
834 | |
835 u->headers_in.status_n = status->code; | |
836 | |
837 len = status->end - status->start; | |
838 u->headers_in.status_line.len = len; | |
839 | |
840 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); | |
841 if (u->headers_in.status_line.data == NULL) { | |
842 return NGX_ERROR; | |
843 } | |
844 | |
845 ngx_memcpy(u->headers_in.status_line.data, status->start, len); | |
846 | |
847 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
848 "http scgi status %ui \"%V\"", | |
849 u->headers_in.status_n, &u->headers_in.status_line); | |
850 | |
851 u->process_header = ngx_http_scgi_process_header; | |
852 | |
853 return ngx_http_scgi_process_header(r); | |
854 } | |
855 | |
856 | |
857 static ngx_int_t | |
858 ngx_http_scgi_process_header(ngx_http_request_t *r) | |
859 { | |
860 ngx_str_t *status_line; | |
861 ngx_int_t rc, status; | |
862 ngx_table_elt_t *h; | |
863 ngx_http_upstream_t *u; | |
864 ngx_http_upstream_header_t *hh; | |
865 ngx_http_upstream_main_conf_t *umcf; | |
866 | |
867 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | |
868 | |
869 for ( ;; ) { | |
870 | |
871 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); | |
872 | |
873 if (rc == NGX_OK) { | |
874 | |
875 /* a header line has been parsed successfully */ | |
876 | |
877 h = ngx_list_push(&r->upstream->headers_in.headers); | |
878 if (h == NULL) { | |
879 return NGX_ERROR; | |
880 } | |
881 | |
882 h->hash = r->header_hash; | |
883 | |
884 h->key.len = r->header_name_end - r->header_name_start; | |
885 h->value.len = r->header_end - r->header_start; | |
886 | |
887 h->key.data = ngx_pnalloc(r->pool, | |
888 h->key.len + 1 + h->value.len + 1 | |
889 + h->key.len); | |
890 if (h->key.data == NULL) { | |
891 return NGX_ERROR; | |
892 } | |
893 | |
894 h->value.data = h->key.data + h->key.len + 1; | |
895 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; | |
896 | |
897 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
898 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
899 | |
900 if (h->key.len == r->lowcase_index) { | |
901 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); | |
902 | |
903 } else { | |
904 ngx_strlow(h->lowcase_key, h->key.data, h->key.len); | |
905 } | |
906 | |
907 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, | |
908 h->lowcase_key, h->key.len); | |
909 | |
910 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | |
911 return NGX_ERROR; | |
912 } | |
913 | |
914 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
915 "http scgi header: \"%V: %V\"", &h->key, &h->value); | |
916 | |
917 continue; | |
918 } | |
919 | |
920 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
921 | |
922 /* a whole header has been parsed successfully */ | |
923 | |
924 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
925 "http scgi header done"); | |
926 | |
927 if (r->http_version > NGX_HTTP_VERSION_9) { | |
928 return NGX_OK; | |
929 } | |
930 | |
931 u = r->upstream; | |
932 | |
933 if (u->headers_in.status) { | |
934 status_line = &u->headers_in.status->value; | |
935 | |
936 status = ngx_atoi(status_line->data, 3); | |
937 if (status == NGX_ERROR) { | |
938 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
939 "upstream sent invalid status \"%V\"", | |
940 status_line); | |
941 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
942 } | |
943 | |
944 r->http_version = NGX_HTTP_VERSION_10; | |
945 u->headers_in.status_n = status; | |
946 u->headers_in.status_line = *status_line; | |
947 | |
948 } else if (u->headers_in.location) { | |
949 r->http_version = NGX_HTTP_VERSION_10; | |
950 u->headers_in.status_n = 302; | |
951 ngx_str_set(&u->headers_in.status_line, | |
952 "302 Moved Temporarily"); | |
953 | |
954 } else { | |
955 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
956 "upstream sent neither valid HTTP/1.0 header " | |
957 "nor \"Status\" header line"); | |
958 u->headers_in.status_n = 200; | |
959 ngx_str_set(&u->headers_in.status_line, "200 OK"); | |
960 } | |
961 | |
962 if (u->state) { | |
963 u->state->status = u->headers_in.status_n; | |
964 } | |
965 | |
966 return NGX_OK; | |
967 } | |
968 | |
969 if (rc == NGX_AGAIN) { | |
970 return NGX_AGAIN; | |
971 } | |
972 | |
973 /* there was error while a header line parsing */ | |
974 | |
975 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
976 "upstream sent invalid header"); | |
977 | |
978 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
979 } | |
980 } | |
981 | |
982 | |
983 static void | |
984 ngx_http_scgi_abort_request(ngx_http_request_t *r) | |
985 { | |
986 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
987 "abort http scgi request"); | |
988 | |
989 return; | |
990 } | |
991 | |
992 | |
993 static void | |
994 ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc) | |
995 { | |
996 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
997 "finalize http scgi request"); | |
998 | |
999 return; | |
1000 } | |
1001 | |
1002 | |
1003 static void * | |
1004 ngx_http_scgi_create_loc_conf(ngx_conf_t *cf) | |
1005 { | |
1006 ngx_http_scgi_loc_conf_t *conf; | |
1007 | |
1008 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_scgi_loc_conf_t)); | |
1009 if (conf == NULL) { | |
1010 return NULL; | |
1011 } | |
1012 | |
1013 conf->upstream.store = NGX_CONF_UNSET; | |
1014 conf->upstream.store_access = NGX_CONF_UNSET_UINT; | |
1015 conf->upstream.buffering = NGX_CONF_UNSET; | |
1016 conf->upstream.ignore_client_abort = NGX_CONF_UNSET; | |
1017 | |
1018 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | |
1019 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | |
1020 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | |
1021 | |
1022 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; | |
1023 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; | |
1024 | |
1025 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; | |
1026 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; | |
1027 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; | |
1028 | |
1029 conf->upstream.pass_request_headers = NGX_CONF_UNSET; | |
1030 conf->upstream.pass_request_body = NGX_CONF_UNSET; | |
1031 | |
1032 #if (NGX_HTTP_CACHE) | |
1033 conf->upstream.cache = NGX_CONF_UNSET_PTR; | |
1034 conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; | |
3699
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
1035 conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; |
3693
e3bcc2f4c418
fix scgi_no_cache and uwsgi_no_cache initialization
Igor Sysoev <igor@sysoev.ru>
parents:
3692
diff
changeset
|
1036 conf->upstream.no_cache = NGX_CONF_UNSET_PTR; |
3637 | 1037 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; |
1038 #endif | |
1039 | |
1040 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; | |
1041 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; | |
1042 | |
1043 conf->upstream.intercept_errors = NGX_CONF_UNSET; | |
1044 | |
1045 /* "scgi_cyclic_temp_file" is disabled */ | |
1046 conf->upstream.cyclic_temp_file = 0; | |
1047 | |
4252 | 1048 conf->upstream.change_buffering = 1; |
1049 | |
4045
2d062c031fff
Merge of r3964, r3977, r3978:
Igor Sysoev <igor@sysoev.ru>
parents:
3879
diff
changeset
|
1050 ngx_str_set(&conf->upstream.module, "scgi"); |
2d062c031fff
Merge of r3964, r3977, r3978:
Igor Sysoev <igor@sysoev.ru>
parents:
3879
diff
changeset
|
1051 |
3637 | 1052 return conf; |
1053 } | |
1054 | |
1055 | |
1056 static char * | |
1057 ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
1058 { | |
1059 ngx_http_scgi_loc_conf_t *prev = parent; | |
1060 ngx_http_scgi_loc_conf_t *conf = child; | |
1061 | |
1062 u_char *p; | |
1063 size_t size; | |
1064 uintptr_t *code; | |
1065 ngx_uint_t i; | |
1066 ngx_array_t headers_names; | |
1067 ngx_keyval_t *src; | |
1068 ngx_hash_key_t *hk; | |
1069 ngx_hash_init_t hash; | |
3731
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1070 ngx_http_core_loc_conf_t *clcf; |
3637 | 1071 ngx_http_script_compile_t sc; |
1072 ngx_http_script_copy_code_t *copy; | |
1073 | |
1074 if (conf->upstream.store != 0) { | |
1075 ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); | |
1076 | |
1077 if (conf->upstream.store_lengths == NULL) { | |
1078 conf->upstream.store_lengths = prev->upstream.store_lengths; | |
1079 conf->upstream.store_values = prev->upstream.store_values; | |
1080 } | |
1081 } | |
1082 | |
1083 ngx_conf_merge_uint_value(conf->upstream.store_access, | |
1084 prev->upstream.store_access, 0600); | |
1085 | |
1086 ngx_conf_merge_value(conf->upstream.buffering, | |
1087 prev->upstream.buffering, 1); | |
1088 | |
1089 ngx_conf_merge_value(conf->upstream.ignore_client_abort, | |
1090 prev->upstream.ignore_client_abort, 0); | |
1091 | |
1092 ngx_conf_merge_msec_value(conf->upstream.connect_timeout, | |
1093 prev->upstream.connect_timeout, 60000); | |
1094 | |
1095 ngx_conf_merge_msec_value(conf->upstream.send_timeout, | |
1096 prev->upstream.send_timeout, 60000); | |
1097 | |
1098 ngx_conf_merge_msec_value(conf->upstream.read_timeout, | |
1099 prev->upstream.read_timeout, 60000); | |
1100 | |
1101 ngx_conf_merge_size_value(conf->upstream.send_lowat, | |
1102 prev->upstream.send_lowat, 0); | |
1103 | |
1104 ngx_conf_merge_size_value(conf->upstream.buffer_size, | |
1105 prev->upstream.buffer_size, | |
1106 (size_t) ngx_pagesize); | |
1107 | |
1108 | |
1109 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, | |
1110 8, ngx_pagesize); | |
1111 | |
1112 if (conf->upstream.bufs.num < 2) { | |
1113 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1114 "there must be at least 2 \"scgi_buffers\""); | |
1115 return NGX_CONF_ERROR; | |
1116 } | |
1117 | |
1118 | |
1119 size = conf->upstream.buffer_size; | |
1120 if (size < conf->upstream.bufs.size) { | |
1121 size = conf->upstream.bufs.size; | |
1122 } | |
1123 | |
1124 | |
1125 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, | |
1126 prev->upstream.busy_buffers_size_conf, | |
1127 NGX_CONF_UNSET_SIZE); | |
1128 | |
1129 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { | |
1130 conf->upstream.busy_buffers_size = 2 * size; | |
1131 } else { | |
1132 conf->upstream.busy_buffers_size = | |
1133 conf->upstream.busy_buffers_size_conf; | |
1134 } | |
1135 | |
1136 if (conf->upstream.busy_buffers_size < size) { | |
1137 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1138 "\"scgi_busy_buffers_size\" must be equal or bigger " | |
1139 "than maximum of the value of \"scgi_buffer_size\" and " | |
1140 "one of the \"scgi_buffers\""); | |
1141 | |
1142 return NGX_CONF_ERROR; | |
1143 } | |
1144 | |
1145 if (conf->upstream.busy_buffers_size | |
1146 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) | |
1147 { | |
1148 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1149 "\"scgi_busy_buffers_size\" must be less than " | |
1150 "the size of all \"scgi_buffers\" minus one buffer"); | |
1151 | |
1152 return NGX_CONF_ERROR; | |
1153 } | |
1154 | |
1155 | |
1156 ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf, | |
1157 prev->upstream.temp_file_write_size_conf, | |
1158 NGX_CONF_UNSET_SIZE); | |
1159 | |
1160 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { | |
1161 conf->upstream.temp_file_write_size = 2 * size; | |
1162 } else { | |
1163 conf->upstream.temp_file_write_size = | |
1164 conf->upstream.temp_file_write_size_conf; | |
1165 } | |
1166 | |
1167 if (conf->upstream.temp_file_write_size < size) { | |
1168 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1169 "\"scgi_temp_file_write_size\" must be equal or bigger than " | |
1170 "maximum of the value of \"scgi_buffer_size\" and " | |
1171 "one of the \"scgi_buffers\""); | |
1172 | |
1173 return NGX_CONF_ERROR; | |
1174 } | |
1175 | |
1176 | |
1177 ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf, | |
1178 prev->upstream.max_temp_file_size_conf, | |
1179 NGX_CONF_UNSET_SIZE); | |
1180 | |
1181 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { | |
1182 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; | |
1183 } else { | |
1184 conf->upstream.max_temp_file_size = | |
1185 conf->upstream.max_temp_file_size_conf; | |
1186 } | |
1187 | |
1188 if (conf->upstream.max_temp_file_size != 0 | |
1189 && conf->upstream.max_temp_file_size < size) { | |
1190 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1191 "\"scgi_max_temp_file_size\" must be equal to zero to disable " | |
1192 "the temporary files usage or must be equal or bigger than " | |
1193 "maximum of the value of \"scgi_buffer_size\" and " | |
1194 "one of the \"scgi_buffers\""); | |
1195 | |
1196 return NGX_CONF_ERROR; | |
1197 } | |
1198 | |
1199 | |
1200 ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers, | |
1201 prev->upstream.ignore_headers, | |
1202 NGX_CONF_BITMASK_SET); | |
1203 | |
1204 | |
1205 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, | |
1206 prev->upstream.next_upstream, | |
1207 (NGX_CONF_BITMASK_SET | |
1208 |NGX_HTTP_UPSTREAM_FT_ERROR | |
1209 |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); | |
1210 | |
1211 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { | |
1212 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET | |
1213 |NGX_HTTP_UPSTREAM_FT_OFF; | |
1214 } | |
1215 | |
1216 if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path, | |
1217 prev->upstream.temp_path, | |
1218 &ngx_http_scgi_temp_path) | |
1219 != NGX_OK) | |
1220 { | |
1221 return NGX_CONF_ERROR; | |
1222 } | |
1223 | |
1224 #if (NGX_HTTP_CACHE) | |
1225 | |
1226 ngx_conf_merge_ptr_value(conf->upstream.cache, | |
1227 prev->upstream.cache, NULL); | |
1228 | |
1229 if (conf->upstream.cache && conf->upstream.cache->data == NULL) { | |
1230 ngx_shm_zone_t *shm_zone; | |
1231 | |
1232 shm_zone = conf->upstream.cache; | |
1233 | |
1234 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1235 "\"scgi_cache\" zone \"%V\" is unknown", | |
1236 &shm_zone->shm.name); | |
1237 | |
1238 return NGX_CONF_ERROR; | |
1239 } | |
1240 | |
1241 ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, | |
1242 prev->upstream.cache_min_uses, 1); | |
1243 | |
1244 ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, | |
1245 prev->upstream.cache_use_stale, | |
1246 (NGX_CONF_BITMASK_SET | |
1247 |NGX_HTTP_UPSTREAM_FT_OFF)); | |
1248 | |
1249 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) { | |
1250 conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET | |
1251 |NGX_HTTP_UPSTREAM_FT_OFF; | |
1252 } | |
1253 | |
1254 if (conf->upstream.cache_methods == 0) { | |
1255 conf->upstream.cache_methods = prev->upstream.cache_methods; | |
1256 } | |
1257 | |
1258 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; | |
1259 | |
3699
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
1260 ngx_conf_merge_ptr_value(conf->upstream.cache_bypass, |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
1261 prev->upstream.cache_bypass, NULL); |
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
1262 |
3637 | 1263 ngx_conf_merge_ptr_value(conf->upstream.no_cache, |
1264 prev->upstream.no_cache, NULL); | |
1265 | |
1266 ngx_conf_merge_ptr_value(conf->upstream.cache_valid, | |
1267 prev->upstream.cache_valid, NULL); | |
1268 | |
1269 if (conf->cache_key.value.data == NULL) { | |
1270 conf->cache_key = prev->cache_key; | |
1271 } | |
1272 | |
1273 #endif | |
1274 | |
1275 ngx_conf_merge_value(conf->upstream.pass_request_headers, | |
1276 prev->upstream.pass_request_headers, 1); | |
1277 ngx_conf_merge_value(conf->upstream.pass_request_body, | |
1278 prev->upstream.pass_request_body, 1); | |
1279 | |
1280 ngx_conf_merge_value(conf->upstream.intercept_errors, | |
1281 prev->upstream.intercept_errors, 0); | |
1282 | |
1283 hash.max_size = 512; | |
1284 hash.bucket_size = ngx_align(64, ngx_cacheline_size); | |
1285 hash.name = "scgi_hide_headers_hash"; | |
1286 | |
1287 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, | |
3670
2728c4e4a9ae
do not use a cache headers set to hide
Igor Sysoev <igor@sysoev.ru>
parents:
3668
diff
changeset
|
1288 &prev->upstream, ngx_http_scgi_hide_headers, &hash) |
3637 | 1289 != NGX_OK) |
1290 { | |
1291 return NGX_CONF_ERROR; | |
1292 } | |
1293 | |
1294 if (conf->upstream.upstream == NULL) { | |
1295 conf->upstream.upstream = prev->upstream.upstream; | |
1296 } | |
1297 | |
1298 if (conf->scgi_lengths == NULL) { | |
1299 conf->scgi_lengths = prev->scgi_lengths; | |
1300 conf->scgi_values = prev->scgi_values; | |
1301 } | |
1302 | |
3731
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1303 if (conf->upstream.upstream || conf->scgi_lengths) { |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1304 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1305 if (clcf->handler == NULL && clcf->lmt_excpt) { |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1306 clcf->handler = ngx_http_scgi_handler; |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1307 } |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1308 } |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1309 |
3637 | 1310 if (conf->params_source == NULL) { |
1311 conf->flushes = prev->flushes; | |
1312 conf->params_len = prev->params_len; | |
1313 conf->params = prev->params; | |
1314 conf->params_source = prev->params_source; | |
1315 conf->headers_hash = prev->headers_hash; | |
1316 | |
1317 #if (NGX_HTTP_CACHE) | |
1318 | |
1319 if (conf->params_source == NULL) { | |
1320 | |
1321 if ((conf->upstream.cache == NULL) | |
1322 == (prev->upstream.cache == NULL)) | |
1323 { | |
1324 return NGX_CONF_OK; | |
1325 } | |
1326 | |
1327 /* 6 is a number of ngx_http_scgi_cache_headers entries */ | |
1328 conf->params_source = ngx_array_create(cf->pool, 6, | |
1329 sizeof(ngx_keyval_t)); | |
1330 if (conf->params_source == NULL) { | |
1331 return NGX_CONF_ERROR; | |
1332 } | |
1333 } | |
1334 #else | |
1335 | |
1336 if (conf->params_source == NULL) { | |
1337 return NGX_CONF_OK; | |
1338 } | |
1339 | |
1340 #endif | |
1341 } | |
1342 | |
1343 conf->params_len = ngx_array_create(cf->pool, 64, 1); | |
1344 if (conf->params_len == NULL) { | |
1345 return NGX_CONF_ERROR; | |
1346 } | |
1347 | |
1348 conf->params = ngx_array_create(cf->pool, 512, 1); | |
1349 if (conf->params == NULL) { | |
1350 return NGX_CONF_ERROR; | |
1351 } | |
1352 | |
1353 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | |
1354 != NGX_OK) | |
1355 { | |
1356 return NGX_CONF_ERROR; | |
1357 } | |
1358 | |
1359 src = conf->params_source->elts; | |
1360 | |
1361 #if (NGX_HTTP_CACHE) | |
1362 | |
1363 if (conf->upstream.cache) { | |
1364 ngx_keyval_t *h, *s; | |
1365 | |
1366 for (h = ngx_http_scgi_cache_headers; h->key.len; h++) { | |
1367 | |
1368 for (i = 0; i < conf->params_source->nelts; i++) { | |
1369 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { | |
1370 goto next; | |
1371 } | |
1372 } | |
1373 | |
1374 s = ngx_array_push(conf->params_source); | |
1375 if (s == NULL) { | |
1376 return NGX_CONF_ERROR; | |
1377 } | |
1378 | |
1379 *s = *h; | |
1380 | |
1381 src = conf->params_source->elts; | |
1382 | |
1383 next: | |
1384 | |
1385 h++; | |
1386 } | |
1387 } | |
1388 | |
1389 #endif | |
1390 | |
1391 for (i = 0; i < conf->params_source->nelts; i++) { | |
1392 | |
1393 if (src[i].key.len > sizeof("HTTP_") - 1 | |
1394 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) | |
1395 { | |
1396 hk = ngx_array_push(&headers_names); | |
1397 if (hk == NULL) { | |
1398 return NGX_CONF_ERROR; | |
1399 } | |
1400 | |
1401 hk->key.len = src[i].key.len - 5; | |
1402 hk->key.data = src[i].key.data + 5; | |
1403 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); | |
1404 hk->value = (void *) 1; | |
1405 | |
1406 if (src[i].value.len == 0) { | |
1407 continue; | |
1408 } | |
1409 } | |
1410 | |
1411 copy = ngx_array_push_n(conf->params_len, | |
1412 sizeof(ngx_http_script_copy_code_t)); | |
1413 if (copy == NULL) { | |
1414 return NGX_CONF_ERROR; | |
1415 } | |
1416 | |
1417 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | |
1418 copy->len = src[i].key.len + 1; | |
1419 | |
1420 | |
1421 size = (sizeof(ngx_http_script_copy_code_t) | |
1422 + src[i].key.len + 1 + sizeof(uintptr_t) - 1) | |
1423 & ~(sizeof(uintptr_t) - 1); | |
1424 | |
1425 copy = ngx_array_push_n(conf->params, size); | |
1426 if (copy == NULL) { | |
1427 return NGX_CONF_ERROR; | |
1428 } | |
1429 | |
1430 copy->code = ngx_http_script_copy_code; | |
1431 copy->len = src[i].key.len + 1; | |
1432 | |
1433 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1434 (void) ngx_cpystrn(p, src[i].key.data, src[i].key.len + 1); | |
1435 | |
1436 | |
1437 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1438 | |
1439 sc.cf = cf; | |
1440 sc.source = &src[i].value; | |
1441 sc.flushes = &conf->flushes; | |
1442 sc.lengths = &conf->params_len; | |
1443 sc.values = &conf->params; | |
1444 | |
1445 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1446 return NGX_CONF_ERROR; | |
1447 } | |
1448 | |
1449 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | |
1450 if (code == NULL) { | |
1451 return NGX_CONF_ERROR; | |
1452 } | |
1453 | |
1454 *code = (uintptr_t) NULL; | |
1455 | |
1456 | |
1457 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | |
1458 if (code == NULL) { | |
1459 return NGX_CONF_ERROR; | |
1460 } | |
1461 | |
1462 *code = (uintptr_t) NULL; | |
1463 } | |
1464 | |
1465 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | |
1466 if (code == NULL) { | |
1467 return NGX_CONF_ERROR; | |
1468 } | |
1469 | |
1470 *code = (uintptr_t) NULL; | |
1471 | |
1472 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | |
1473 if (code == NULL) { | |
1474 return NGX_CONF_ERROR; | |
1475 } | |
1476 | |
1477 *code = (uintptr_t) NULL; | |
1478 | |
1479 conf->header_params = headers_names.nelts; | |
1480 | |
1481 hash.hash = &conf->headers_hash; | |
1482 hash.key = ngx_hash_key_lc; | |
1483 hash.max_size = 512; | |
1484 hash.bucket_size = 64; | |
1485 hash.name = "scgi_params_hash"; | |
1486 hash.pool = cf->pool; | |
1487 hash.temp_pool = NULL; | |
1488 | |
1489 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) | |
1490 { | |
1491 return NGX_CONF_ERROR; | |
1492 } | |
1493 | |
1494 return NGX_CONF_OK; | |
1495 } | |
1496 | |
1497 | |
1498 static char * | |
1499 ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1500 { | |
1501 ngx_http_scgi_loc_conf_t *scf = conf; | |
1502 | |
1503 ngx_url_t u; | |
1504 ngx_str_t *value, *url; | |
1505 ngx_uint_t n; | |
1506 ngx_http_core_loc_conf_t *clcf; | |
1507 ngx_http_script_compile_t sc; | |
1508 | |
1509 if (scf->upstream.upstream || scf->scgi_lengths) { | |
1510 return "is duplicate"; | |
1511 } | |
1512 | |
1513 clcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module); | |
1514 clcf->handler = ngx_http_scgi_handler; | |
1515 | |
1516 value = cf->args->elts; | |
1517 | |
1518 url = &value[1]; | |
1519 | |
1520 n = ngx_http_script_variables_count(url); | |
1521 | |
1522 if (n) { | |
1523 | |
1524 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1525 | |
1526 sc.cf = cf; | |
1527 sc.source = url; | |
1528 sc.lengths = &scf->scgi_lengths; | |
1529 sc.values = &scf->scgi_values; | |
1530 sc.variables = n; | |
1531 sc.complete_lengths = 1; | |
1532 sc.complete_values = 1; | |
1533 | |
1534 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1535 return NGX_CONF_ERROR; | |
1536 } | |
1537 | |
1538 return NGX_CONF_OK; | |
1539 } | |
1540 | |
1541 ngx_memzero(&u, sizeof(ngx_url_t)); | |
1542 | |
1543 u.url = value[1]; | |
1544 u.no_resolve = 1; | |
1545 | |
1546 scf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); | |
1547 if (scf->upstream.upstream == NULL) { | |
1548 return NGX_CONF_ERROR; | |
1549 } | |
1550 | |
1551 if (clcf->name.data[clcf->name.len - 1] == '/') { | |
1552 clcf->auto_redirect = 1; | |
1553 } | |
1554 | |
1555 return NGX_CONF_OK; | |
1556 } | |
1557 | |
1558 | |
1559 static char * | |
1560 ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1561 { | |
1562 ngx_http_scgi_loc_conf_t *scf = conf; | |
1563 | |
1564 ngx_str_t *value; | |
1565 ngx_http_script_compile_t sc; | |
1566 | |
1567 if (scf->upstream.store != NGX_CONF_UNSET || scf->upstream.store_lengths) { | |
1568 return "is duplicate"; | |
1569 } | |
1570 | |
1571 value = cf->args->elts; | |
1572 | |
1573 if (ngx_strcmp(value[1].data, "off") == 0) { | |
1574 scf->upstream.store = 0; | |
1575 return NGX_CONF_OK; | |
1576 } | |
1577 | |
1578 #if (NGX_HTTP_CACHE) | |
1579 | |
1580 if (scf->upstream.cache != NGX_CONF_UNSET_PTR | |
1581 && scf->upstream.cache != NULL) | |
1582 { | |
1583 return "is incompatible with \"scgi_cache\""; | |
1584 } | |
1585 | |
1586 #endif | |
1587 | |
1588 if (ngx_strcmp(value[1].data, "on") == 0) { | |
1589 scf->upstream.store = 1; | |
1590 return NGX_CONF_OK; | |
1591 } | |
1592 | |
1593 /* include the terminating '\0' into script */ | |
1594 value[1].len++; | |
1595 | |
1596 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1597 | |
1598 sc.cf = cf; | |
1599 sc.source = &value[1]; | |
1600 sc.lengths = &scf->upstream.store_lengths; | |
1601 sc.values = &scf->upstream.store_values; | |
1602 sc.variables = ngx_http_script_variables_count(&value[1]);; | |
1603 sc.complete_lengths = 1; | |
1604 sc.complete_values = 1; | |
1605 | |
1606 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1607 return NGX_CONF_ERROR; | |
1608 } | |
1609 | |
1610 return NGX_CONF_OK; | |
1611 } | |
1612 | |
1613 | |
1614 #if (NGX_HTTP_CACHE) | |
1615 | |
1616 static char * | |
1617 ngx_http_scgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1618 { | |
1619 ngx_http_scgi_loc_conf_t *scf = conf; | |
1620 | |
1621 ngx_str_t *value; | |
1622 | |
1623 value = cf->args->elts; | |
1624 | |
1625 if (scf->upstream.cache != NGX_CONF_UNSET_PTR) { | |
1626 return "is duplicate"; | |
1627 } | |
1628 | |
1629 if (ngx_strcmp(value[1].data, "off") == 0) { | |
1630 scf->upstream.cache = NULL; | |
1631 return NGX_CONF_OK; | |
1632 } | |
1633 | |
1634 if (scf->upstream.store > 0 || scf->upstream.store_lengths) { | |
1635 return "is incompatible with \"scgi_store\""; | |
1636 } | |
1637 | |
1638 scf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, | |
1639 &ngx_http_scgi_module); | |
1640 if (scf->upstream.cache == NULL) { | |
1641 return NGX_CONF_ERROR; | |
1642 } | |
1643 | |
1644 return NGX_CONF_OK; | |
1645 } | |
1646 | |
1647 | |
1648 static char * | |
1649 ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1650 { | |
1651 ngx_http_scgi_loc_conf_t *scf = conf; | |
1652 | |
1653 ngx_str_t *value; | |
1654 ngx_http_compile_complex_value_t ccv; | |
1655 | |
1656 value = cf->args->elts; | |
1657 | |
1658 if (scf->cache_key.value.len) { | |
1659 return "is duplicate"; | |
1660 } | |
1661 | |
1662 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
1663 | |
1664 ccv.cf = cf; | |
1665 ccv.value = &value[1]; | |
1666 ccv.complex_value = &scf->cache_key; | |
1667 | |
1668 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
1669 return NGX_CONF_ERROR; | |
1670 } | |
1671 | |
1672 return NGX_CONF_OK; | |
1673 } | |
1674 | |
1675 #endif |