Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_scgi_module.c @ 4009:3183165283cc
Fixing proxy_set_body and proxy_pass_request_body with SSL.
Flush flag wasn't set in constructed buffer and this prevented any data
from being actually sent to upstream due to SSL buffering. Make sure
we always set flush in the last buffer we are going to sent.
See here for report:
http://nginx.org/pipermail/nginx-ru/2011-June/041552.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 Aug 2011 16:34:24 +0000 |
parents | 215fe9223419 |
children | e0a435f5f504 |
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) { | |
564 ignored = ngx_palloc(r->pool, scf->header_params * sizeof(void *)); | |
565 if (ignored == NULL) { | |
566 return NGX_ERROR; | |
567 } | |
568 } | |
569 | |
570 part = &r->headers_in.headers.part; | |
571 header = part->elts; | |
572 | |
573 for (i = 0; /* void */; i++) { | |
574 | |
575 if (i >= part->nelts) { | |
576 if (part->next == NULL) { | |
577 break; | |
578 } | |
579 | |
580 part = part->next; | |
581 header = part->elts; | |
582 i = 0; | |
583 } | |
584 | |
585 if (scf->header_params) { | |
586 if (allocated < header[i].key.len) { | |
587 allocated = header[i].key.len + 16; | |
588 lowcase_key = ngx_pnalloc(r->pool, allocated); | |
589 if (lowcase_key == NULL) { | |
590 return NGX_ERROR; | |
591 } | |
592 } | |
593 | |
594 hash = 0; | |
595 | |
596 for (n = 0; n < header[i].key.len; n++) { | |
597 ch = header[i].key.data[n]; | |
598 | |
599 if (ch >= 'A' && ch <= 'Z') { | |
600 ch |= 0x20; | |
601 | |
602 } else if (ch == '-') { | |
603 ch = '_'; | |
604 } | |
605 | |
606 hash = ngx_hash(hash, ch); | |
607 lowcase_key[n] = ch; | |
608 } | |
609 | |
610 if (ngx_hash_find(&scf->headers_hash, hash, lowcase_key, n)) { | |
611 ignored[header_params++] = &header[i]; | |
612 continue; | |
613 } | |
614 } | |
615 | |
616 len += sizeof("HTTP_") - 1 + header[i].key.len + 1 | |
617 + header[i].value.len + 1; | |
618 } | |
619 } | |
620 | |
621 /* netstring: "length:" + packet + "," */ | |
622 | |
623 b = ngx_create_temp_buf(r->pool, NGX_SIZE_T_LEN + 1 + len + 1); | |
624 if (b == NULL) { | |
625 return NGX_ERROR; | |
626 } | |
627 | |
628 cl = ngx_alloc_chain_link(r->pool); | |
629 if (cl == NULL) { | |
630 return NGX_ERROR; | |
631 } | |
632 | |
633 cl->buf = b; | |
634 | |
635 b->last = ngx_snprintf(b->last, | |
636 NGX_SIZE_T_LEN + 1 + sizeof("CONTENT_LENGTH") | |
637 + NGX_OFF_T_LEN + 1, | |
638 "%ui:CONTENT_LENGTH%Z%V%Z", | |
639 len, content_length); | |
640 | |
641 if (scf->params_len) { | |
642 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
643 | |
644 e.ip = scf->params->elts; | |
645 e.pos = b->last; | |
646 e.request = r; | |
647 e.flushed = 1; | |
648 | |
649 while (*(uintptr_t *) e.ip) { | |
650 | |
651 #if (NGX_DEBUG) | |
652 key = e.pos; | |
653 #endif | |
654 code = *(ngx_http_script_code_pt *) e.ip; | |
655 code((ngx_http_script_engine_t *) & e); | |
656 | |
657 #if (NGX_DEBUG) | |
658 val = e.pos; | |
659 #endif | |
660 while (*(uintptr_t *) e.ip) { | |
661 code = *(ngx_http_script_code_pt *) e.ip; | |
662 code((ngx_http_script_engine_t *) &e); | |
663 } | |
664 *e.pos++ = '\0'; | |
665 e.ip += sizeof(uintptr_t); | |
666 | |
667 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
668 "scgi param: \"%s: %s\"", key, val); | |
669 } | |
670 | |
671 b->last = e.pos; | |
672 } | |
673 | |
674 if (scf->upstream.pass_request_headers) { | |
675 | |
676 part = &r->headers_in.headers.part; | |
677 header = part->elts; | |
678 | |
679 for (i = 0; /* void */; i++) { | |
680 | |
681 if (i >= part->nelts) { | |
682 if (part->next == NULL) { | |
683 break; | |
684 } | |
685 | |
686 part = part->next; | |
687 header = part->elts; | |
688 i = 0; | |
689 } | |
690 | |
691 for (n = 0; n < header_params; n++) { | |
692 if (&header[i] == ignored[n]) { | |
693 goto next; | |
694 } | |
695 } | |
696 | |
697 key = b->last; | |
698 b->last = ngx_cpymem(key, "HTTP_", sizeof("HTTP_") - 1); | |
699 | |
700 for (n = 0; n < header[i].key.len; n++) { | |
701 ch = header[i].key.data[n]; | |
702 | |
703 if (ch >= 'a' && ch <= 'z') { | |
704 ch &= ~0x20; | |
705 | |
706 } else if (ch == '-') { | |
707 ch = '_'; | |
708 } | |
709 | |
710 *b->last++ = ch; | |
711 } | |
712 | |
713 *b->last++ = (u_char) 0; | |
714 | |
715 val = b->last; | |
716 b->last = ngx_copy(val, header[i].value.data, header[i].value.len); | |
717 *b->last++ = (u_char) 0; | |
718 | |
719 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
720 "scgi param: \"%s: %s\"", key, val); | |
721 | |
722 next: | |
723 | |
724 continue; | |
725 } | |
726 } | |
727 | |
728 *b->last++ = (u_char) ','; | |
729 | |
730 if (scf->upstream.pass_request_body) { | |
731 body = r->upstream->request_bufs; | |
732 r->upstream->request_bufs = cl; | |
733 | |
734 while (body) { | |
735 b = ngx_alloc_buf(r->pool); | |
736 if (b == NULL) { | |
737 return NGX_ERROR; | |
738 } | |
739 | |
740 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); | |
741 | |
742 cl->next = ngx_alloc_chain_link(r->pool); | |
743 if (cl->next == NULL) { | |
744 return NGX_ERROR; | |
745 } | |
746 | |
747 cl = cl->next; | |
748 cl->buf = b; | |
749 | |
750 body = body->next; | |
751 } | |
752 | |
753 } else { | |
754 r->upstream->request_bufs = cl; | |
755 } | |
756 | |
757 cl->next = NULL; | |
758 | |
759 return NGX_OK; | |
760 } | |
761 | |
762 | |
763 static ngx_int_t | |
764 ngx_http_scgi_reinit_request(ngx_http_request_t *r) | |
765 { | |
766 ngx_http_status_t *status; | |
767 | |
768 status = ngx_http_get_module_ctx(r, ngx_http_scgi_module); | |
769 | |
770 if (status == NULL) { | |
771 return NGX_OK; | |
772 } | |
773 | |
774 status->code = 0; | |
775 status->count = 0; | |
776 status->start = NULL; | |
777 status->end = NULL; | |
778 | |
779 r->upstream->process_header = ngx_http_scgi_process_status_line; | |
780 | |
781 return NGX_OK; | |
782 } | |
783 | |
784 | |
785 static ngx_int_t | |
786 ngx_http_scgi_process_status_line(ngx_http_request_t *r) | |
787 { | |
788 size_t len; | |
789 ngx_int_t rc; | |
790 ngx_http_status_t *status; | |
791 ngx_http_upstream_t *u; | |
792 | |
793 status = ngx_http_get_module_ctx(r, ngx_http_scgi_module); | |
794 | |
795 if (status == NULL) { | |
796 return NGX_ERROR; | |
797 } | |
798 | |
799 u = r->upstream; | |
800 | |
801 rc = ngx_http_parse_status_line(r, &u->buffer, status); | |
802 | |
803 if (rc == NGX_AGAIN) { | |
804 return rc; | |
805 } | |
806 | |
807 if (rc == NGX_ERROR) { | |
808 | |
809 r->http_version = NGX_HTTP_VERSION_9; | |
810 | |
811 u->process_header = ngx_http_scgi_process_header; | |
812 | |
813 return ngx_http_scgi_process_header(r); | |
814 } | |
815 | |
816 if (u->state) { | |
817 u->state->status = status->code; | |
818 } | |
819 | |
820 u->headers_in.status_n = status->code; | |
821 | |
822 len = status->end - status->start; | |
823 u->headers_in.status_line.len = len; | |
824 | |
825 u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); | |
826 if (u->headers_in.status_line.data == NULL) { | |
827 return NGX_ERROR; | |
828 } | |
829 | |
830 ngx_memcpy(u->headers_in.status_line.data, status->start, len); | |
831 | |
832 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
833 "http scgi status %ui \"%V\"", | |
834 u->headers_in.status_n, &u->headers_in.status_line); | |
835 | |
836 u->process_header = ngx_http_scgi_process_header; | |
837 | |
838 return ngx_http_scgi_process_header(r); | |
839 } | |
840 | |
841 | |
842 static ngx_int_t | |
843 ngx_http_scgi_process_header(ngx_http_request_t *r) | |
844 { | |
845 ngx_str_t *status_line; | |
846 ngx_int_t rc, status; | |
847 ngx_table_elt_t *h; | |
848 ngx_http_upstream_t *u; | |
849 ngx_http_upstream_header_t *hh; | |
850 ngx_http_upstream_main_conf_t *umcf; | |
851 | |
852 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | |
853 | |
854 for ( ;; ) { | |
855 | |
856 rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); | |
857 | |
858 if (rc == NGX_OK) { | |
859 | |
860 /* a header line has been parsed successfully */ | |
861 | |
862 h = ngx_list_push(&r->upstream->headers_in.headers); | |
863 if (h == NULL) { | |
864 return NGX_ERROR; | |
865 } | |
866 | |
867 h->hash = r->header_hash; | |
868 | |
869 h->key.len = r->header_name_end - r->header_name_start; | |
870 h->value.len = r->header_end - r->header_start; | |
871 | |
872 h->key.data = ngx_pnalloc(r->pool, | |
873 h->key.len + 1 + h->value.len + 1 | |
874 + h->key.len); | |
875 if (h->key.data == NULL) { | |
876 return NGX_ERROR; | |
877 } | |
878 | |
879 h->value.data = h->key.data + h->key.len + 1; | |
880 h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; | |
881 | |
882 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
883 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
884 | |
885 if (h->key.len == r->lowcase_index) { | |
886 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); | |
887 | |
888 } else { | |
889 ngx_strlow(h->lowcase_key, h->key.data, h->key.len); | |
890 } | |
891 | |
892 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, | |
893 h->lowcase_key, h->key.len); | |
894 | |
895 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | |
896 return NGX_ERROR; | |
897 } | |
898 | |
899 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
900 "http scgi header: \"%V: %V\"", &h->key, &h->value); | |
901 | |
902 continue; | |
903 } | |
904 | |
905 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
906 | |
907 /* a whole header has been parsed successfully */ | |
908 | |
909 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
910 "http scgi header done"); | |
911 | |
912 if (r->http_version > NGX_HTTP_VERSION_9) { | |
913 return NGX_OK; | |
914 } | |
915 | |
916 u = r->upstream; | |
917 | |
918 if (u->headers_in.status) { | |
919 status_line = &u->headers_in.status->value; | |
920 | |
921 status = ngx_atoi(status_line->data, 3); | |
922 if (status == NGX_ERROR) { | |
923 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
924 "upstream sent invalid status \"%V\"", | |
925 status_line); | |
926 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
927 } | |
928 | |
929 r->http_version = NGX_HTTP_VERSION_10; | |
930 u->headers_in.status_n = status; | |
931 u->headers_in.status_line = *status_line; | |
932 | |
933 } else if (u->headers_in.location) { | |
934 r->http_version = NGX_HTTP_VERSION_10; | |
935 u->headers_in.status_n = 302; | |
936 ngx_str_set(&u->headers_in.status_line, | |
937 "302 Moved Temporarily"); | |
938 | |
939 } else { | |
940 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
941 "upstream sent neither valid HTTP/1.0 header " | |
942 "nor \"Status\" header line"); | |
943 u->headers_in.status_n = 200; | |
944 ngx_str_set(&u->headers_in.status_line, "200 OK"); | |
945 } | |
946 | |
947 if (u->state) { | |
948 u->state->status = u->headers_in.status_n; | |
949 } | |
950 | |
951 return NGX_OK; | |
952 } | |
953 | |
954 if (rc == NGX_AGAIN) { | |
955 return NGX_AGAIN; | |
956 } | |
957 | |
958 /* there was error while a header line parsing */ | |
959 | |
960 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
961 "upstream sent invalid header"); | |
962 | |
963 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
964 } | |
965 } | |
966 | |
967 | |
968 static void | |
969 ngx_http_scgi_abort_request(ngx_http_request_t *r) | |
970 { | |
971 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
972 "abort http scgi request"); | |
973 | |
974 return; | |
975 } | |
976 | |
977 | |
978 static void | |
979 ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc) | |
980 { | |
981 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
982 "finalize http scgi request"); | |
983 | |
984 return; | |
985 } | |
986 | |
987 | |
988 static void * | |
989 ngx_http_scgi_create_loc_conf(ngx_conf_t *cf) | |
990 { | |
991 ngx_http_scgi_loc_conf_t *conf; | |
992 | |
993 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_scgi_loc_conf_t)); | |
994 if (conf == NULL) { | |
995 return NULL; | |
996 } | |
997 | |
998 conf->upstream.store = NGX_CONF_UNSET; | |
999 conf->upstream.store_access = NGX_CONF_UNSET_UINT; | |
1000 conf->upstream.buffering = NGX_CONF_UNSET; | |
1001 conf->upstream.ignore_client_abort = NGX_CONF_UNSET; | |
1002 | |
1003 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | |
1004 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | |
1005 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | |
1006 | |
1007 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; | |
1008 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; | |
1009 | |
1010 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; | |
1011 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; | |
1012 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; | |
1013 | |
1014 conf->upstream.pass_request_headers = NGX_CONF_UNSET; | |
1015 conf->upstream.pass_request_body = NGX_CONF_UNSET; | |
1016 | |
1017 #if (NGX_HTTP_CACHE) | |
1018 conf->upstream.cache = NGX_CONF_UNSET_PTR; | |
1019 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
|
1020 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
|
1021 conf->upstream.no_cache = NGX_CONF_UNSET_PTR; |
3637 | 1022 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; |
1023 #endif | |
1024 | |
1025 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; | |
1026 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; | |
1027 | |
1028 conf->upstream.intercept_errors = NGX_CONF_UNSET; | |
1029 | |
1030 /* "scgi_cyclic_temp_file" is disabled */ | |
1031 conf->upstream.cyclic_temp_file = 0; | |
1032 | |
3976
215fe9223419
update r3945 with more descriptive error message
Igor Sysoev <igor@sysoev.ru>
parents:
3879
diff
changeset
|
1033 ngx_str_set(&conf->upstream.module, "scgi"); |
215fe9223419
update r3945 with more descriptive error message
Igor Sysoev <igor@sysoev.ru>
parents:
3879
diff
changeset
|
1034 |
3637 | 1035 return conf; |
1036 } | |
1037 | |
1038 | |
1039 static char * | |
1040 ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
1041 { | |
1042 ngx_http_scgi_loc_conf_t *prev = parent; | |
1043 ngx_http_scgi_loc_conf_t *conf = child; | |
1044 | |
1045 u_char *p; | |
1046 size_t size; | |
1047 uintptr_t *code; | |
1048 ngx_uint_t i; | |
1049 ngx_array_t headers_names; | |
1050 ngx_keyval_t *src; | |
1051 ngx_hash_key_t *hk; | |
1052 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
|
1053 ngx_http_core_loc_conf_t *clcf; |
3637 | 1054 ngx_http_script_compile_t sc; |
1055 ngx_http_script_copy_code_t *copy; | |
1056 | |
1057 if (conf->upstream.store != 0) { | |
1058 ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); | |
1059 | |
1060 if (conf->upstream.store_lengths == NULL) { | |
1061 conf->upstream.store_lengths = prev->upstream.store_lengths; | |
1062 conf->upstream.store_values = prev->upstream.store_values; | |
1063 } | |
1064 } | |
1065 | |
1066 ngx_conf_merge_uint_value(conf->upstream.store_access, | |
1067 prev->upstream.store_access, 0600); | |
1068 | |
1069 ngx_conf_merge_value(conf->upstream.buffering, | |
1070 prev->upstream.buffering, 1); | |
1071 | |
1072 ngx_conf_merge_value(conf->upstream.ignore_client_abort, | |
1073 prev->upstream.ignore_client_abort, 0); | |
1074 | |
1075 ngx_conf_merge_msec_value(conf->upstream.connect_timeout, | |
1076 prev->upstream.connect_timeout, 60000); | |
1077 | |
1078 ngx_conf_merge_msec_value(conf->upstream.send_timeout, | |
1079 prev->upstream.send_timeout, 60000); | |
1080 | |
1081 ngx_conf_merge_msec_value(conf->upstream.read_timeout, | |
1082 prev->upstream.read_timeout, 60000); | |
1083 | |
1084 ngx_conf_merge_size_value(conf->upstream.send_lowat, | |
1085 prev->upstream.send_lowat, 0); | |
1086 | |
1087 ngx_conf_merge_size_value(conf->upstream.buffer_size, | |
1088 prev->upstream.buffer_size, | |
1089 (size_t) ngx_pagesize); | |
1090 | |
1091 | |
1092 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, | |
1093 8, ngx_pagesize); | |
1094 | |
1095 if (conf->upstream.bufs.num < 2) { | |
1096 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1097 "there must be at least 2 \"scgi_buffers\""); | |
1098 return NGX_CONF_ERROR; | |
1099 } | |
1100 | |
1101 | |
1102 size = conf->upstream.buffer_size; | |
1103 if (size < conf->upstream.bufs.size) { | |
1104 size = conf->upstream.bufs.size; | |
1105 } | |
1106 | |
1107 | |
1108 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, | |
1109 prev->upstream.busy_buffers_size_conf, | |
1110 NGX_CONF_UNSET_SIZE); | |
1111 | |
1112 if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { | |
1113 conf->upstream.busy_buffers_size = 2 * size; | |
1114 } else { | |
1115 conf->upstream.busy_buffers_size = | |
1116 conf->upstream.busy_buffers_size_conf; | |
1117 } | |
1118 | |
1119 if (conf->upstream.busy_buffers_size < size) { | |
1120 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1121 "\"scgi_busy_buffers_size\" must be equal or bigger " | |
1122 "than maximum of the value of \"scgi_buffer_size\" and " | |
1123 "one of the \"scgi_buffers\""); | |
1124 | |
1125 return NGX_CONF_ERROR; | |
1126 } | |
1127 | |
1128 if (conf->upstream.busy_buffers_size | |
1129 > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) | |
1130 { | |
1131 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1132 "\"scgi_busy_buffers_size\" must be less than " | |
1133 "the size of all \"scgi_buffers\" minus one buffer"); | |
1134 | |
1135 return NGX_CONF_ERROR; | |
1136 } | |
1137 | |
1138 | |
1139 ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf, | |
1140 prev->upstream.temp_file_write_size_conf, | |
1141 NGX_CONF_UNSET_SIZE); | |
1142 | |
1143 if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { | |
1144 conf->upstream.temp_file_write_size = 2 * size; | |
1145 } else { | |
1146 conf->upstream.temp_file_write_size = | |
1147 conf->upstream.temp_file_write_size_conf; | |
1148 } | |
1149 | |
1150 if (conf->upstream.temp_file_write_size < size) { | |
1151 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1152 "\"scgi_temp_file_write_size\" must be equal or bigger than " | |
1153 "maximum of the value of \"scgi_buffer_size\" and " | |
1154 "one of the \"scgi_buffers\""); | |
1155 | |
1156 return NGX_CONF_ERROR; | |
1157 } | |
1158 | |
1159 | |
1160 ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf, | |
1161 prev->upstream.max_temp_file_size_conf, | |
1162 NGX_CONF_UNSET_SIZE); | |
1163 | |
1164 if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { | |
1165 conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; | |
1166 } else { | |
1167 conf->upstream.max_temp_file_size = | |
1168 conf->upstream.max_temp_file_size_conf; | |
1169 } | |
1170 | |
1171 if (conf->upstream.max_temp_file_size != 0 | |
1172 && conf->upstream.max_temp_file_size < size) { | |
1173 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1174 "\"scgi_max_temp_file_size\" must be equal to zero to disable " | |
1175 "the temporary files usage or must be equal or bigger than " | |
1176 "maximum of the value of \"scgi_buffer_size\" and " | |
1177 "one of the \"scgi_buffers\""); | |
1178 | |
1179 return NGX_CONF_ERROR; | |
1180 } | |
1181 | |
1182 | |
1183 ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers, | |
1184 prev->upstream.ignore_headers, | |
1185 NGX_CONF_BITMASK_SET); | |
1186 | |
1187 | |
1188 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, | |
1189 prev->upstream.next_upstream, | |
1190 (NGX_CONF_BITMASK_SET | |
1191 |NGX_HTTP_UPSTREAM_FT_ERROR | |
1192 |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); | |
1193 | |
1194 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { | |
1195 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET | |
1196 |NGX_HTTP_UPSTREAM_FT_OFF; | |
1197 } | |
1198 | |
1199 if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path, | |
1200 prev->upstream.temp_path, | |
1201 &ngx_http_scgi_temp_path) | |
1202 != NGX_OK) | |
1203 { | |
1204 return NGX_CONF_ERROR; | |
1205 } | |
1206 | |
1207 #if (NGX_HTTP_CACHE) | |
1208 | |
1209 ngx_conf_merge_ptr_value(conf->upstream.cache, | |
1210 prev->upstream.cache, NULL); | |
1211 | |
1212 if (conf->upstream.cache && conf->upstream.cache->data == NULL) { | |
1213 ngx_shm_zone_t *shm_zone; | |
1214 | |
1215 shm_zone = conf->upstream.cache; | |
1216 | |
1217 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1218 "\"scgi_cache\" zone \"%V\" is unknown", | |
1219 &shm_zone->shm.name); | |
1220 | |
1221 return NGX_CONF_ERROR; | |
1222 } | |
1223 | |
1224 ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, | |
1225 prev->upstream.cache_min_uses, 1); | |
1226 | |
1227 ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, | |
1228 prev->upstream.cache_use_stale, | |
1229 (NGX_CONF_BITMASK_SET | |
1230 |NGX_HTTP_UPSTREAM_FT_OFF)); | |
1231 | |
1232 if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) { | |
1233 conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET | |
1234 |NGX_HTTP_UPSTREAM_FT_OFF; | |
1235 } | |
1236 | |
1237 if (conf->upstream.cache_methods == 0) { | |
1238 conf->upstream.cache_methods = prev->upstream.cache_methods; | |
1239 } | |
1240 | |
1241 conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD; | |
1242 | |
3699
b0a0686a85bb
proxy_cache_pass, fastcgi_cache_bypass, uwsgi_cache_bypass, scgi_cache_bypass
Igor Sysoev <igor@sysoev.ru>
parents:
3693
diff
changeset
|
1243 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
|
1244 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
|
1245 |
3637 | 1246 ngx_conf_merge_ptr_value(conf->upstream.no_cache, |
1247 prev->upstream.no_cache, NULL); | |
1248 | |
1249 ngx_conf_merge_ptr_value(conf->upstream.cache_valid, | |
1250 prev->upstream.cache_valid, NULL); | |
1251 | |
1252 if (conf->cache_key.value.data == NULL) { | |
1253 conf->cache_key = prev->cache_key; | |
1254 } | |
1255 | |
1256 #endif | |
1257 | |
1258 ngx_conf_merge_value(conf->upstream.pass_request_headers, | |
1259 prev->upstream.pass_request_headers, 1); | |
1260 ngx_conf_merge_value(conf->upstream.pass_request_body, | |
1261 prev->upstream.pass_request_body, 1); | |
1262 | |
1263 ngx_conf_merge_value(conf->upstream.intercept_errors, | |
1264 prev->upstream.intercept_errors, 0); | |
1265 | |
1266 hash.max_size = 512; | |
1267 hash.bucket_size = ngx_align(64, ngx_cacheline_size); | |
1268 hash.name = "scgi_hide_headers_hash"; | |
1269 | |
1270 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
|
1271 &prev->upstream, ngx_http_scgi_hide_headers, &hash) |
3637 | 1272 != NGX_OK) |
1273 { | |
1274 return NGX_CONF_ERROR; | |
1275 } | |
1276 | |
1277 if (conf->upstream.upstream == NULL) { | |
1278 conf->upstream.upstream = prev->upstream.upstream; | |
1279 } | |
1280 | |
1281 if (conf->scgi_lengths == NULL) { | |
1282 conf->scgi_lengths = prev->scgi_lengths; | |
1283 conf->scgi_values = prev->scgi_values; | |
1284 } | |
1285 | |
3731
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1286 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
|
1287 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
|
1288 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
|
1289 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
|
1290 } |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1291 } |
72cc5b789021
inherit proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass inside
Igor Sysoev <igor@sysoev.ru>
parents:
3729
diff
changeset
|
1292 |
3637 | 1293 if (conf->params_source == NULL) { |
1294 conf->flushes = prev->flushes; | |
1295 conf->params_len = prev->params_len; | |
1296 conf->params = prev->params; | |
1297 conf->params_source = prev->params_source; | |
1298 conf->headers_hash = prev->headers_hash; | |
1299 | |
1300 #if (NGX_HTTP_CACHE) | |
1301 | |
1302 if (conf->params_source == NULL) { | |
1303 | |
1304 if ((conf->upstream.cache == NULL) | |
1305 == (prev->upstream.cache == NULL)) | |
1306 { | |
1307 return NGX_CONF_OK; | |
1308 } | |
1309 | |
1310 /* 6 is a number of ngx_http_scgi_cache_headers entries */ | |
1311 conf->params_source = ngx_array_create(cf->pool, 6, | |
1312 sizeof(ngx_keyval_t)); | |
1313 if (conf->params_source == NULL) { | |
1314 return NGX_CONF_ERROR; | |
1315 } | |
1316 } | |
1317 #else | |
1318 | |
1319 if (conf->params_source == NULL) { | |
1320 return NGX_CONF_OK; | |
1321 } | |
1322 | |
1323 #endif | |
1324 } | |
1325 | |
1326 conf->params_len = ngx_array_create(cf->pool, 64, 1); | |
1327 if (conf->params_len == NULL) { | |
1328 return NGX_CONF_ERROR; | |
1329 } | |
1330 | |
1331 conf->params = ngx_array_create(cf->pool, 512, 1); | |
1332 if (conf->params == NULL) { | |
1333 return NGX_CONF_ERROR; | |
1334 } | |
1335 | |
1336 if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | |
1337 != NGX_OK) | |
1338 { | |
1339 return NGX_CONF_ERROR; | |
1340 } | |
1341 | |
1342 src = conf->params_source->elts; | |
1343 | |
1344 #if (NGX_HTTP_CACHE) | |
1345 | |
1346 if (conf->upstream.cache) { | |
1347 ngx_keyval_t *h, *s; | |
1348 | |
1349 for (h = ngx_http_scgi_cache_headers; h->key.len; h++) { | |
1350 | |
1351 for (i = 0; i < conf->params_source->nelts; i++) { | |
1352 if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) { | |
1353 goto next; | |
1354 } | |
1355 } | |
1356 | |
1357 s = ngx_array_push(conf->params_source); | |
1358 if (s == NULL) { | |
1359 return NGX_CONF_ERROR; | |
1360 } | |
1361 | |
1362 *s = *h; | |
1363 | |
1364 src = conf->params_source->elts; | |
1365 | |
1366 next: | |
1367 | |
1368 h++; | |
1369 } | |
1370 } | |
1371 | |
1372 #endif | |
1373 | |
1374 for (i = 0; i < conf->params_source->nelts; i++) { | |
1375 | |
1376 if (src[i].key.len > sizeof("HTTP_") - 1 | |
1377 && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0) | |
1378 { | |
1379 hk = ngx_array_push(&headers_names); | |
1380 if (hk == NULL) { | |
1381 return NGX_CONF_ERROR; | |
1382 } | |
1383 | |
1384 hk->key.len = src[i].key.len - 5; | |
1385 hk->key.data = src[i].key.data + 5; | |
1386 hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len); | |
1387 hk->value = (void *) 1; | |
1388 | |
1389 if (src[i].value.len == 0) { | |
1390 continue; | |
1391 } | |
1392 } | |
1393 | |
1394 copy = ngx_array_push_n(conf->params_len, | |
1395 sizeof(ngx_http_script_copy_code_t)); | |
1396 if (copy == NULL) { | |
1397 return NGX_CONF_ERROR; | |
1398 } | |
1399 | |
1400 copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; | |
1401 copy->len = src[i].key.len + 1; | |
1402 | |
1403 | |
1404 size = (sizeof(ngx_http_script_copy_code_t) | |
1405 + src[i].key.len + 1 + sizeof(uintptr_t) - 1) | |
1406 & ~(sizeof(uintptr_t) - 1); | |
1407 | |
1408 copy = ngx_array_push_n(conf->params, size); | |
1409 if (copy == NULL) { | |
1410 return NGX_CONF_ERROR; | |
1411 } | |
1412 | |
1413 copy->code = ngx_http_script_copy_code; | |
1414 copy->len = src[i].key.len + 1; | |
1415 | |
1416 p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); | |
1417 (void) ngx_cpystrn(p, src[i].key.data, src[i].key.len + 1); | |
1418 | |
1419 | |
1420 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1421 | |
1422 sc.cf = cf; | |
1423 sc.source = &src[i].value; | |
1424 sc.flushes = &conf->flushes; | |
1425 sc.lengths = &conf->params_len; | |
1426 sc.values = &conf->params; | |
1427 | |
1428 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1429 return NGX_CONF_ERROR; | |
1430 } | |
1431 | |
1432 code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t)); | |
1433 if (code == NULL) { | |
1434 return NGX_CONF_ERROR; | |
1435 } | |
1436 | |
1437 *code = (uintptr_t) NULL; | |
1438 | |
1439 | |
1440 code = ngx_array_push_n(conf->params, 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_len, sizeof(uintptr_t)); | |
1449 if (code == NULL) { | |
1450 return NGX_CONF_ERROR; | |
1451 } | |
1452 | |
1453 *code = (uintptr_t) NULL; | |
1454 | |
1455 code = ngx_array_push_n(conf->params, sizeof(uintptr_t)); | |
1456 if (code == NULL) { | |
1457 return NGX_CONF_ERROR; | |
1458 } | |
1459 | |
1460 *code = (uintptr_t) NULL; | |
1461 | |
1462 conf->header_params = headers_names.nelts; | |
1463 | |
1464 hash.hash = &conf->headers_hash; | |
1465 hash.key = ngx_hash_key_lc; | |
1466 hash.max_size = 512; | |
1467 hash.bucket_size = 64; | |
1468 hash.name = "scgi_params_hash"; | |
1469 hash.pool = cf->pool; | |
1470 hash.temp_pool = NULL; | |
1471 | |
1472 if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK) | |
1473 { | |
1474 return NGX_CONF_ERROR; | |
1475 } | |
1476 | |
1477 return NGX_CONF_OK; | |
1478 } | |
1479 | |
1480 | |
1481 static char * | |
1482 ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1483 { | |
1484 ngx_http_scgi_loc_conf_t *scf = conf; | |
1485 | |
1486 ngx_url_t u; | |
1487 ngx_str_t *value, *url; | |
1488 ngx_uint_t n; | |
1489 ngx_http_core_loc_conf_t *clcf; | |
1490 ngx_http_script_compile_t sc; | |
1491 | |
1492 if (scf->upstream.upstream || scf->scgi_lengths) { | |
1493 return "is duplicate"; | |
1494 } | |
1495 | |
1496 clcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module); | |
1497 clcf->handler = ngx_http_scgi_handler; | |
1498 | |
1499 value = cf->args->elts; | |
1500 | |
1501 url = &value[1]; | |
1502 | |
1503 n = ngx_http_script_variables_count(url); | |
1504 | |
1505 if (n) { | |
1506 | |
1507 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1508 | |
1509 sc.cf = cf; | |
1510 sc.source = url; | |
1511 sc.lengths = &scf->scgi_lengths; | |
1512 sc.values = &scf->scgi_values; | |
1513 sc.variables = n; | |
1514 sc.complete_lengths = 1; | |
1515 sc.complete_values = 1; | |
1516 | |
1517 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1518 return NGX_CONF_ERROR; | |
1519 } | |
1520 | |
1521 return NGX_CONF_OK; | |
1522 } | |
1523 | |
1524 ngx_memzero(&u, sizeof(ngx_url_t)); | |
1525 | |
1526 u.url = value[1]; | |
1527 u.no_resolve = 1; | |
1528 | |
1529 scf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); | |
1530 if (scf->upstream.upstream == NULL) { | |
1531 return NGX_CONF_ERROR; | |
1532 } | |
1533 | |
1534 if (clcf->name.data[clcf->name.len - 1] == '/') { | |
1535 clcf->auto_redirect = 1; | |
1536 } | |
1537 | |
1538 return NGX_CONF_OK; | |
1539 } | |
1540 | |
1541 | |
1542 static char * | |
1543 ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1544 { | |
1545 ngx_http_scgi_loc_conf_t *scf = conf; | |
1546 | |
1547 ngx_str_t *value; | |
1548 ngx_http_script_compile_t sc; | |
1549 | |
1550 if (scf->upstream.store != NGX_CONF_UNSET || scf->upstream.store_lengths) { | |
1551 return "is duplicate"; | |
1552 } | |
1553 | |
1554 value = cf->args->elts; | |
1555 | |
1556 if (ngx_strcmp(value[1].data, "off") == 0) { | |
1557 scf->upstream.store = 0; | |
1558 return NGX_CONF_OK; | |
1559 } | |
1560 | |
1561 #if (NGX_HTTP_CACHE) | |
1562 | |
1563 if (scf->upstream.cache != NGX_CONF_UNSET_PTR | |
1564 && scf->upstream.cache != NULL) | |
1565 { | |
1566 return "is incompatible with \"scgi_cache\""; | |
1567 } | |
1568 | |
1569 #endif | |
1570 | |
1571 if (ngx_strcmp(value[1].data, "on") == 0) { | |
1572 scf->upstream.store = 1; | |
1573 return NGX_CONF_OK; | |
1574 } | |
1575 | |
1576 /* include the terminating '\0' into script */ | |
1577 value[1].len++; | |
1578 | |
1579 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1580 | |
1581 sc.cf = cf; | |
1582 sc.source = &value[1]; | |
1583 sc.lengths = &scf->upstream.store_lengths; | |
1584 sc.values = &scf->upstream.store_values; | |
1585 sc.variables = ngx_http_script_variables_count(&value[1]);; | |
1586 sc.complete_lengths = 1; | |
1587 sc.complete_values = 1; | |
1588 | |
1589 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1590 return NGX_CONF_ERROR; | |
1591 } | |
1592 | |
1593 return NGX_CONF_OK; | |
1594 } | |
1595 | |
1596 | |
1597 #if (NGX_HTTP_CACHE) | |
1598 | |
1599 static char * | |
1600 ngx_http_scgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1601 { | |
1602 ngx_http_scgi_loc_conf_t *scf = conf; | |
1603 | |
1604 ngx_str_t *value; | |
1605 | |
1606 value = cf->args->elts; | |
1607 | |
1608 if (scf->upstream.cache != NGX_CONF_UNSET_PTR) { | |
1609 return "is duplicate"; | |
1610 } | |
1611 | |
1612 if (ngx_strcmp(value[1].data, "off") == 0) { | |
1613 scf->upstream.cache = NULL; | |
1614 return NGX_CONF_OK; | |
1615 } | |
1616 | |
1617 if (scf->upstream.store > 0 || scf->upstream.store_lengths) { | |
1618 return "is incompatible with \"scgi_store\""; | |
1619 } | |
1620 | |
1621 scf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, | |
1622 &ngx_http_scgi_module); | |
1623 if (scf->upstream.cache == NULL) { | |
1624 return NGX_CONF_ERROR; | |
1625 } | |
1626 | |
1627 return NGX_CONF_OK; | |
1628 } | |
1629 | |
1630 | |
1631 static char * | |
1632 ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1633 { | |
1634 ngx_http_scgi_loc_conf_t *scf = conf; | |
1635 | |
1636 ngx_str_t *value; | |
1637 ngx_http_compile_complex_value_t ccv; | |
1638 | |
1639 value = cf->args->elts; | |
1640 | |
1641 if (scf->cache_key.value.len) { | |
1642 return "is duplicate"; | |
1643 } | |
1644 | |
1645 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
1646 | |
1647 ccv.cf = cf; | |
1648 ccv.value = &value[1]; | |
1649 ccv.complex_value = &scf->cache_key; | |
1650 | |
1651 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
1652 return NGX_CONF_ERROR; | |
1653 } | |
1654 | |
1655 return NGX_CONF_OK; | |
1656 } | |
1657 | |
1658 #endif |