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