3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
14 ngx_http_upstream_conf_t upstream
;
19 ngx_array_t
*params_len
;
21 ngx_array_t
*params_source
;
22 ngx_array_t
*catch_stderr
;
24 ngx_array_t
*fastcgi_lengths
;
25 ngx_array_t
*fastcgi_values
;
27 ngx_hash_t headers_hash
;
28 ngx_uint_t header_params
;
33 ngx_http_complex_value_t cache_key
;
37 ngx_regex_t
*split_regex
;
40 } ngx_http_fastcgi_loc_conf_t
;
44 ngx_http_fastcgi_st_version
= 0,
45 ngx_http_fastcgi_st_type
,
46 ngx_http_fastcgi_st_request_id_hi
,
47 ngx_http_fastcgi_st_request_id_lo
,
48 ngx_http_fastcgi_st_content_length_hi
,
49 ngx_http_fastcgi_st_content_length_lo
,
50 ngx_http_fastcgi_st_padding_length
,
51 ngx_http_fastcgi_st_reserved
,
52 ngx_http_fastcgi_st_data
,
53 ngx_http_fastcgi_st_padding
54 } ngx_http_fastcgi_state_e
;
60 } ngx_http_fastcgi_split_part_t
;
64 ngx_http_fastcgi_state_e state
;
71 unsigned fastcgi_stdout
:1;
72 unsigned large_stderr
:1;
74 ngx_array_t
*split_parts
;
76 ngx_str_t script_name
;
78 } ngx_http_fastcgi_ctx_t
;
81 #define NGX_HTTP_FASTCGI_RESPONDER 1
83 #define NGX_HTTP_FASTCGI_KEEP_CONN 1
85 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
86 #define NGX_HTTP_FASTCGI_ABORT_REQUEST 2
87 #define NGX_HTTP_FASTCGI_END_REQUEST 3
88 #define NGX_HTTP_FASTCGI_PARAMS 4
89 #define NGX_HTTP_FASTCGI_STDIN 5
90 #define NGX_HTTP_FASTCGI_STDOUT 6
91 #define NGX_HTTP_FASTCGI_STDERR 7
92 #define NGX_HTTP_FASTCGI_DATA 8
100 u_char content_length_hi
;
101 u_char content_length_lo
;
102 u_char padding_length
;
104 } ngx_http_fastcgi_header_t
;
112 } ngx_http_fastcgi_begin_request_t
;
118 u_char request_id_hi
;
119 u_char request_id_lo
;
120 } ngx_http_fastcgi_header_small_t
;
124 ngx_http_fastcgi_header_t h0
;
125 ngx_http_fastcgi_begin_request_t br
;
126 ngx_http_fastcgi_header_small_t h1
;
127 } ngx_http_fastcgi_request_start_t
;
130 static ngx_int_t
ngx_http_fastcgi_eval(ngx_http_request_t
*r
,
131 ngx_http_fastcgi_loc_conf_t
*flcf
);
133 static ngx_int_t
ngx_http_fastcgi_create_key(ngx_http_request_t
*r
);
135 static ngx_int_t
ngx_http_fastcgi_create_request(ngx_http_request_t
*r
);
136 static ngx_int_t
ngx_http_fastcgi_reinit_request(ngx_http_request_t
*r
);
137 static ngx_int_t
ngx_http_fastcgi_process_header(ngx_http_request_t
*r
);
138 static ngx_int_t
ngx_http_fastcgi_input_filter_init(void *data
);
139 static ngx_int_t
ngx_http_fastcgi_input_filter(ngx_event_pipe_t
*p
,
141 static ngx_int_t
ngx_http_fastcgi_process_record(ngx_http_request_t
*r
,
142 ngx_http_fastcgi_ctx_t
*f
);
143 static void ngx_http_fastcgi_abort_request(ngx_http_request_t
*r
);
144 static void ngx_http_fastcgi_finalize_request(ngx_http_request_t
*r
,
147 static ngx_int_t
ngx_http_fastcgi_add_variables(ngx_conf_t
*cf
);
148 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t
*cf
);
149 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t
*cf
,
150 void *parent
, void *child
);
151 static ngx_int_t
ngx_http_fastcgi_merge_params(ngx_conf_t
*cf
,
152 ngx_http_fastcgi_loc_conf_t
*conf
, ngx_http_fastcgi_loc_conf_t
*prev
);
154 static ngx_int_t
ngx_http_fastcgi_script_name_variable(ngx_http_request_t
*r
,
155 ngx_http_variable_value_t
*v
, uintptr_t data
);
156 static ngx_int_t
ngx_http_fastcgi_path_info_variable(ngx_http_request_t
*r
,
157 ngx_http_variable_value_t
*v
, uintptr_t data
);
158 static ngx_http_fastcgi_ctx_t
*ngx_http_fastcgi_split(ngx_http_request_t
*r
,
159 ngx_http_fastcgi_loc_conf_t
*flcf
);
161 static char *ngx_http_fastcgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
163 static char *ngx_http_fastcgi_split_path_info(ngx_conf_t
*cf
,
164 ngx_command_t
*cmd
, void *conf
);
165 static char *ngx_http_fastcgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
168 static char *ngx_http_fastcgi_cache(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
170 static char *ngx_http_fastcgi_cache_key(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
174 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t
*cf
, void *post
,
178 static ngx_conf_post_t ngx_http_fastcgi_lowat_post
=
179 { ngx_http_fastcgi_lowat_check
};
182 static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks
[] = {
183 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR
},
184 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT
},
185 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
},
186 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500
},
187 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503
},
188 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404
},
189 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING
},
190 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF
},
191 { ngx_null_string
, 0 }
195 ngx_module_t ngx_http_fastcgi_module
;
198 static ngx_command_t ngx_http_fastcgi_commands
[] = {
200 { ngx_string("fastcgi_pass"),
201 NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1
,
202 ngx_http_fastcgi_pass
,
203 NGX_HTTP_LOC_CONF_OFFSET
,
207 { ngx_string("fastcgi_index"),
208 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
209 ngx_conf_set_str_slot
,
210 NGX_HTTP_LOC_CONF_OFFSET
,
211 offsetof(ngx_http_fastcgi_loc_conf_t
, index
),
214 { ngx_string("fastcgi_split_path_info"),
215 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
216 ngx_http_fastcgi_split_path_info
,
217 NGX_HTTP_LOC_CONF_OFFSET
,
221 { ngx_string("fastcgi_store"),
222 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
223 ngx_http_fastcgi_store
,
224 NGX_HTTP_LOC_CONF_OFFSET
,
228 { ngx_string("fastcgi_store_access"),
229 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE123
,
230 ngx_conf_set_access_slot
,
231 NGX_HTTP_LOC_CONF_OFFSET
,
232 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.store_access
),
235 { ngx_string("fastcgi_ignore_client_abort"),
236 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
237 ngx_conf_set_flag_slot
,
238 NGX_HTTP_LOC_CONF_OFFSET
,
239 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.ignore_client_abort
),
242 { ngx_string("fastcgi_bind"),
243 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
244 ngx_http_upstream_bind_set_slot
,
245 NGX_HTTP_LOC_CONF_OFFSET
,
246 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.local
),
249 { ngx_string("fastcgi_connect_timeout"),
250 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
251 ngx_conf_set_msec_slot
,
252 NGX_HTTP_LOC_CONF_OFFSET
,
253 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.connect_timeout
),
256 { ngx_string("fastcgi_send_timeout"),
257 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
258 ngx_conf_set_msec_slot
,
259 NGX_HTTP_LOC_CONF_OFFSET
,
260 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.send_timeout
),
263 { ngx_string("fastcgi_send_lowat"),
264 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
265 ngx_conf_set_size_slot
,
266 NGX_HTTP_LOC_CONF_OFFSET
,
267 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.send_lowat
),
268 &ngx_http_fastcgi_lowat_post
},
270 { ngx_string("fastcgi_buffer_size"),
271 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
272 ngx_conf_set_size_slot
,
273 NGX_HTTP_LOC_CONF_OFFSET
,
274 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.buffer_size
),
277 { ngx_string("fastcgi_pass_request_headers"),
278 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
279 ngx_conf_set_flag_slot
,
280 NGX_HTTP_LOC_CONF_OFFSET
,
281 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_request_headers
),
284 { ngx_string("fastcgi_pass_request_body"),
285 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
286 ngx_conf_set_flag_slot
,
287 NGX_HTTP_LOC_CONF_OFFSET
,
288 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_request_body
),
291 { ngx_string("fastcgi_intercept_errors"),
292 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
293 ngx_conf_set_flag_slot
,
294 NGX_HTTP_LOC_CONF_OFFSET
,
295 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.intercept_errors
),
298 { ngx_string("fastcgi_read_timeout"),
299 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
300 ngx_conf_set_msec_slot
,
301 NGX_HTTP_LOC_CONF_OFFSET
,
302 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.read_timeout
),
305 { ngx_string("fastcgi_buffers"),
306 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
307 ngx_conf_set_bufs_slot
,
308 NGX_HTTP_LOC_CONF_OFFSET
,
309 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.bufs
),
312 { ngx_string("fastcgi_busy_buffers_size"),
313 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
314 ngx_conf_set_size_slot
,
315 NGX_HTTP_LOC_CONF_OFFSET
,
316 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.busy_buffers_size_conf
),
321 { ngx_string("fastcgi_cache"),
322 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
323 ngx_http_fastcgi_cache
,
324 NGX_HTTP_LOC_CONF_OFFSET
,
328 { ngx_string("fastcgi_cache_key"),
329 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
330 ngx_http_fastcgi_cache_key
,
331 NGX_HTTP_LOC_CONF_OFFSET
,
335 { ngx_string("fastcgi_cache_path"),
336 NGX_HTTP_MAIN_CONF
|NGX_CONF_2MORE
,
337 ngx_http_file_cache_set_slot
,
340 &ngx_http_fastcgi_module
},
342 { ngx_string("fastcgi_cache_bypass"),
343 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
344 ngx_http_set_predicate_slot
,
345 NGX_HTTP_LOC_CONF_OFFSET
,
346 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_bypass
),
349 { ngx_string("fastcgi_no_cache"),
350 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
351 ngx_http_set_predicate_slot
,
352 NGX_HTTP_LOC_CONF_OFFSET
,
353 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.no_cache
),
356 { ngx_string("fastcgi_cache_valid"),
357 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
358 ngx_http_file_cache_valid_set_slot
,
359 NGX_HTTP_LOC_CONF_OFFSET
,
360 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_valid
),
363 { ngx_string("fastcgi_cache_min_uses"),
364 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
365 ngx_conf_set_num_slot
,
366 NGX_HTTP_LOC_CONF_OFFSET
,
367 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_min_uses
),
370 { ngx_string("fastcgi_cache_use_stale"),
371 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
372 ngx_conf_set_bitmask_slot
,
373 NGX_HTTP_LOC_CONF_OFFSET
,
374 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_use_stale
),
375 &ngx_http_fastcgi_next_upstream_masks
},
377 { ngx_string("fastcgi_cache_methods"),
378 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
379 ngx_conf_set_bitmask_slot
,
380 NGX_HTTP_LOC_CONF_OFFSET
,
381 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_methods
),
382 &ngx_http_upstream_cache_method_mask
},
384 { ngx_string("fastcgi_cache_lock"),
385 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
386 ngx_conf_set_flag_slot
,
387 NGX_HTTP_LOC_CONF_OFFSET
,
388 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_lock
),
391 { ngx_string("fastcgi_cache_lock_timeout"),
392 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
393 ngx_conf_set_msec_slot
,
394 NGX_HTTP_LOC_CONF_OFFSET
,
395 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.cache_lock_timeout
),
400 { ngx_string("fastcgi_temp_path"),
401 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1234
,
402 ngx_conf_set_path_slot
,
403 NGX_HTTP_LOC_CONF_OFFSET
,
404 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.temp_path
),
407 { ngx_string("fastcgi_max_temp_file_size"),
408 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
409 ngx_conf_set_size_slot
,
410 NGX_HTTP_LOC_CONF_OFFSET
,
411 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.max_temp_file_size_conf
),
414 { ngx_string("fastcgi_temp_file_write_size"),
415 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
416 ngx_conf_set_size_slot
,
417 NGX_HTTP_LOC_CONF_OFFSET
,
418 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.temp_file_write_size_conf
),
421 { ngx_string("fastcgi_next_upstream"),
422 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
423 ngx_conf_set_bitmask_slot
,
424 NGX_HTTP_LOC_CONF_OFFSET
,
425 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.next_upstream
),
426 &ngx_http_fastcgi_next_upstream_masks
},
428 { ngx_string("fastcgi_param"),
429 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE23
,
430 ngx_http_upstream_param_set_slot
,
431 NGX_HTTP_LOC_CONF_OFFSET
,
432 offsetof(ngx_http_fastcgi_loc_conf_t
, params_source
),
435 { ngx_string("fastcgi_pass_header"),
436 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
437 ngx_conf_set_str_array_slot
,
438 NGX_HTTP_LOC_CONF_OFFSET
,
439 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_headers
),
442 { ngx_string("fastcgi_hide_header"),
443 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
444 ngx_conf_set_str_array_slot
,
445 NGX_HTTP_LOC_CONF_OFFSET
,
446 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.hide_headers
),
449 { ngx_string("fastcgi_ignore_headers"),
450 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
451 ngx_conf_set_bitmask_slot
,
452 NGX_HTTP_LOC_CONF_OFFSET
,
453 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.ignore_headers
),
454 &ngx_http_upstream_ignore_headers_masks
},
456 { ngx_string("fastcgi_catch_stderr"),
457 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
458 ngx_conf_set_str_array_slot
,
459 NGX_HTTP_LOC_CONF_OFFSET
,
460 offsetof(ngx_http_fastcgi_loc_conf_t
, catch_stderr
),
463 { ngx_string("fastcgi_keep_conn"),
464 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
465 ngx_conf_set_flag_slot
,
466 NGX_HTTP_LOC_CONF_OFFSET
,
467 offsetof(ngx_http_fastcgi_loc_conf_t
, keep_conn
),
474 static ngx_http_module_t ngx_http_fastcgi_module_ctx
= {
475 ngx_http_fastcgi_add_variables
, /* preconfiguration */
476 NULL
, /* postconfiguration */
478 NULL
, /* create main configuration */
479 NULL
, /* init main configuration */
481 NULL
, /* create server configuration */
482 NULL
, /* merge server configuration */
484 ngx_http_fastcgi_create_loc_conf
, /* create location configuration */
485 ngx_http_fastcgi_merge_loc_conf
/* merge location configuration */
489 ngx_module_t ngx_http_fastcgi_module
= {
491 &ngx_http_fastcgi_module_ctx
, /* module context */
492 ngx_http_fastcgi_commands
, /* module directives */
493 NGX_HTTP_MODULE
, /* module type */
494 NULL
, /* init master */
495 NULL
, /* init module */
496 NULL
, /* init process */
497 NULL
, /* init thread */
498 NULL
, /* exit thread */
499 NULL
, /* exit process */
500 NULL
, /* exit master */
501 NGX_MODULE_V1_PADDING
505 static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start
= {
507 NGX_HTTP_FASTCGI_BEGIN_REQUEST
, /* type */
508 0, /* request_id_hi */
509 1, /* request_id_lo */
510 0, /* content_length_hi */
511 sizeof(ngx_http_fastcgi_begin_request_t
), /* content_length_lo */
512 0, /* padding_length */
516 NGX_HTTP_FASTCGI_RESPONDER
, /* role_lo */
517 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */
518 { 0, 0, 0, 0, 0 } }, /* reserved[5] */
521 NGX_HTTP_FASTCGI_PARAMS
, /* type */
522 0, /* request_id_hi */
523 1 }, /* request_id_lo */
528 static ngx_http_variable_t ngx_http_fastcgi_vars
[] = {
530 { ngx_string("fastcgi_script_name"), NULL
,
531 ngx_http_fastcgi_script_name_variable
, 0,
532 NGX_HTTP_VAR_NOCACHEABLE
|NGX_HTTP_VAR_NOHASH
, 0 },
534 { ngx_string("fastcgi_path_info"), NULL
,
535 ngx_http_fastcgi_path_info_variable
, 0,
536 NGX_HTTP_VAR_NOCACHEABLE
|NGX_HTTP_VAR_NOHASH
, 0 },
538 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
542 static ngx_str_t ngx_http_fastcgi_hide_headers
[] = {
543 ngx_string("Status"),
544 ngx_string("X-Accel-Expires"),
545 ngx_string("X-Accel-Redirect"),
546 ngx_string("X-Accel-Limit-Rate"),
547 ngx_string("X-Accel-Buffering"),
548 ngx_string("X-Accel-Charset"),
555 static ngx_keyval_t ngx_http_fastcgi_cache_headers
[] = {
556 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
557 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
558 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
559 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
560 { ngx_string("HTTP_RANGE"), ngx_string("") },
561 { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
562 { ngx_null_string
, ngx_null_string
}
568 static ngx_path_init_t ngx_http_fastcgi_temp_path
= {
569 ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH
), { 1, 2, 0 }
574 ngx_http_fastcgi_handler(ngx_http_request_t
*r
)
577 ngx_http_upstream_t
*u
;
578 ngx_http_fastcgi_ctx_t
*f
;
579 ngx_http_fastcgi_loc_conf_t
*flcf
;
581 if (r
->subrequest_in_memory
) {
582 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
583 "ngx_http_fastcgi_module does not support "
584 "subrequest in memory");
585 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
588 if (ngx_http_upstream_create(r
) != NGX_OK
) {
589 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
592 f
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_fastcgi_ctx_t
));
594 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
597 ngx_http_set_ctx(r
, f
, ngx_http_fastcgi_module
);
599 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
601 if (flcf
->fastcgi_lengths
) {
602 if (ngx_http_fastcgi_eval(r
, flcf
) != NGX_OK
) {
603 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
609 ngx_str_set(&u
->schema
, "fastcgi://");
610 u
->output
.tag
= (ngx_buf_tag_t
) &ngx_http_fastcgi_module
;
612 u
->conf
= &flcf
->upstream
;
615 u
->create_key
= ngx_http_fastcgi_create_key
;
617 u
->create_request
= ngx_http_fastcgi_create_request
;
618 u
->reinit_request
= ngx_http_fastcgi_reinit_request
;
619 u
->process_header
= ngx_http_fastcgi_process_header
;
620 u
->abort_request
= ngx_http_fastcgi_abort_request
;
621 u
->finalize_request
= ngx_http_fastcgi_finalize_request
;
626 u
->pipe
= ngx_pcalloc(r
->pool
, sizeof(ngx_event_pipe_t
));
627 if (u
->pipe
== NULL
) {
628 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
631 u
->pipe
->input_filter
= ngx_http_fastcgi_input_filter
;
632 u
->pipe
->input_ctx
= r
;
634 u
->input_filter_init
= ngx_http_fastcgi_input_filter_init
;
636 rc
= ngx_http_read_client_request_body(r
, ngx_http_upstream_init
);
638 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
) {
647 ngx_http_fastcgi_eval(ngx_http_request_t
*r
, ngx_http_fastcgi_loc_conf_t
*flcf
)
650 ngx_http_upstream_t
*u
;
652 ngx_memzero(&url
, sizeof(ngx_url_t
));
654 if (ngx_http_script_run(r
, &url
.url
, flcf
->fastcgi_lengths
->elts
, 0,
655 flcf
->fastcgi_values
->elts
)
663 if (ngx_parse_url(r
->pool
, &url
) != NGX_OK
) {
665 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
666 "%s in upstream \"%V\"", url
.err
, &url
.url
);
674 u
->resolved
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_upstream_resolved_t
));
675 if (u
->resolved
== NULL
) {
679 if (url
.addrs
&& url
.addrs
[0].sockaddr
) {
680 u
->resolved
->sockaddr
= url
.addrs
[0].sockaddr
;
681 u
->resolved
->socklen
= url
.addrs
[0].socklen
;
682 u
->resolved
->naddrs
= 1;
683 u
->resolved
->host
= url
.addrs
[0].name
;
686 u
->resolved
->host
= url
.host
;
687 u
->resolved
->port
= url
.port
;
688 u
->resolved
->no_port
= url
.no_port
;
698 ngx_http_fastcgi_create_key(ngx_http_request_t
*r
)
701 ngx_http_fastcgi_loc_conf_t
*flcf
;
703 key
= ngx_array_push(&r
->cache
->keys
);
708 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
710 if (ngx_http_complex_value(r
, &flcf
->cache_key
, key
) != NGX_OK
) {
721 ngx_http_fastcgi_create_request(ngx_http_request_t
*r
)
724 u_char ch
, *pos
, *lowcase_key
;
725 size_t size
, len
, key_len
, val_len
, padding
,
727 ngx_uint_t i
, n
, next
, hash
, skip_empty
, header_params
;
729 ngx_chain_t
*cl
, *body
;
730 ngx_list_part_t
*part
;
731 ngx_table_elt_t
*header
, **ignored
;
732 ngx_http_script_code_pt code
;
733 ngx_http_script_engine_t e
, le
;
734 ngx_http_fastcgi_header_t
*h
;
735 ngx_http_fastcgi_loc_conf_t
*flcf
;
736 ngx_http_script_len_code_pt lcode
;
742 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
744 if (flcf
->params_len
) {
745 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
747 ngx_http_script_flush_no_cacheable_variables(r
, flcf
->flushes
);
750 le
.ip
= flcf
->params_len
->elts
;
753 while (*(uintptr_t *) le
.ip
) {
755 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
756 key_len
= lcode(&le
);
758 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
759 skip_empty
= lcode(&le
);
761 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode(&le
)) {
762 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
764 le
.ip
+= sizeof(uintptr_t);
766 if (skip_empty
&& val_len
== 0) {
770 len
+= 1 + key_len
+ ((val_len
> 127) ? 4 : 1) + val_len
;
774 if (flcf
->upstream
.pass_request_headers
) {
779 if (flcf
->header_params
) {
781 part
= &r
->headers_in
.headers
.part
;
788 ignored
= ngx_palloc(r
->pool
, n
* sizeof(void *));
789 if (ignored
== NULL
) {
794 part
= &r
->headers_in
.headers
.part
;
797 for (i
= 0; /* void */; i
++) {
799 if (i
>= part
->nelts
) {
800 if (part
->next
== NULL
) {
809 if (flcf
->header_params
) {
810 if (allocated
< header
[i
].key
.len
) {
811 allocated
= header
[i
].key
.len
+ 16;
812 lowcase_key
= ngx_pnalloc(r
->pool
, allocated
);
813 if (lowcase_key
== NULL
) {
820 for (n
= 0; n
< header
[i
].key
.len
; n
++) {
821 ch
= header
[i
].key
.data
[n
];
823 if (ch
>= 'A' && ch
<= 'Z') {
826 } else if (ch
== '-') {
830 hash
= ngx_hash(hash
, ch
);
834 if (ngx_hash_find(&flcf
->headers_hash
, hash
, lowcase_key
, n
)) {
835 ignored
[header_params
++] = &header
[i
];
839 n
+= sizeof("HTTP_") - 1;
842 n
= sizeof("HTTP_") - 1 + header
[i
].key
.len
;
845 len
+= ((n
> 127) ? 4 : 1) + ((header
[i
].value
.len
> 127) ? 4 : 1)
846 + n
+ header
[i
].value
.len
;
852 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
853 "fastcgi request record is too big: %uz", len
);
858 padding
= 8 - len
% 8;
859 padding
= (padding
== 8) ? 0 : padding
;
862 size
= sizeof(ngx_http_fastcgi_header_t
)
863 + sizeof(ngx_http_fastcgi_begin_request_t
)
865 + sizeof(ngx_http_fastcgi_header_t
) /* NGX_HTTP_FASTCGI_PARAMS */
867 + sizeof(ngx_http_fastcgi_header_t
) /* NGX_HTTP_FASTCGI_PARAMS */
869 + sizeof(ngx_http_fastcgi_header_t
); /* NGX_HTTP_FASTCGI_STDIN */
872 b
= ngx_create_temp_buf(r
->pool
, size
);
877 cl
= ngx_alloc_chain_link(r
->pool
);
884 ngx_http_fastcgi_request_start
.br
.flags
=
885 flcf
->keep_conn
? NGX_HTTP_FASTCGI_KEEP_CONN
: 0;
887 ngx_memcpy(b
->pos
, &ngx_http_fastcgi_request_start
,
888 sizeof(ngx_http_fastcgi_request_start_t
));
890 h
= (ngx_http_fastcgi_header_t
*)
891 (b
->pos
+ sizeof(ngx_http_fastcgi_header_t
)
892 + sizeof(ngx_http_fastcgi_begin_request_t
));
894 h
->content_length_hi
= (u_char
) ((len
>> 8) & 0xff);
895 h
->content_length_lo
= (u_char
) (len
& 0xff);
896 h
->padding_length
= (u_char
) padding
;
899 b
->last
= b
->pos
+ sizeof(ngx_http_fastcgi_header_t
)
900 + sizeof(ngx_http_fastcgi_begin_request_t
)
901 + sizeof(ngx_http_fastcgi_header_t
);
904 if (flcf
->params_len
) {
905 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
907 e
.ip
= flcf
->params
->elts
;
912 le
.ip
= flcf
->params_len
->elts
;
914 while (*(uintptr_t *) le
.ip
) {
916 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
917 key_len
= (u_char
) lcode(&le
);
919 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
920 skip_empty
= lcode(&le
);
922 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode(&le
)) {
923 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
925 le
.ip
+= sizeof(uintptr_t);
927 if (skip_empty
&& val_len
== 0) {
930 while (*(uintptr_t *) e
.ip
) {
931 code
= *(ngx_http_script_code_pt
*) e
.ip
;
932 code((ngx_http_script_engine_t
*) &e
);
934 e
.ip
+= sizeof(uintptr_t);
941 *e
.pos
++ = (u_char
) key_len
;
944 *e
.pos
++ = (u_char
) (((val_len
>> 24) & 0x7f) | 0x80);
945 *e
.pos
++ = (u_char
) ((val_len
>> 16) & 0xff);
946 *e
.pos
++ = (u_char
) ((val_len
>> 8) & 0xff);
947 *e
.pos
++ = (u_char
) (val_len
& 0xff);
950 *e
.pos
++ = (u_char
) val_len
;
953 while (*(uintptr_t *) e
.ip
) {
954 code
= *(ngx_http_script_code_pt
*) e
.ip
;
955 code((ngx_http_script_engine_t
*) &e
);
957 e
.ip
+= sizeof(uintptr_t);
959 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
960 "fastcgi param: \"%*s: %*s\"",
961 key_len
, e
.pos
- (key_len
+ val_len
),
962 val_len
, e
.pos
- val_len
);
969 if (flcf
->upstream
.pass_request_headers
) {
971 part
= &r
->headers_in
.headers
.part
;
974 for (i
= 0; /* void */; i
++) {
976 if (i
>= part
->nelts
) {
977 if (part
->next
== NULL
) {
986 for (n
= 0; n
< header_params
; n
++) {
987 if (&header
[i
] == ignored
[n
]) {
992 key_len
= sizeof("HTTP_") - 1 + header
[i
].key
.len
;
994 *b
->last
++ = (u_char
) (((key_len
>> 24) & 0x7f) | 0x80);
995 *b
->last
++ = (u_char
) ((key_len
>> 16) & 0xff);
996 *b
->last
++ = (u_char
) ((key_len
>> 8) & 0xff);
997 *b
->last
++ = (u_char
) (key_len
& 0xff);
1000 *b
->last
++ = (u_char
) key_len
;
1003 val_len
= header
[i
].value
.len
;
1004 if (val_len
> 127) {
1005 *b
->last
++ = (u_char
) (((val_len
>> 24) & 0x7f) | 0x80);
1006 *b
->last
++ = (u_char
) ((val_len
>> 16) & 0xff);
1007 *b
->last
++ = (u_char
) ((val_len
>> 8) & 0xff);
1008 *b
->last
++ = (u_char
) (val_len
& 0xff);
1011 *b
->last
++ = (u_char
) val_len
;
1014 b
->last
= ngx_cpymem(b
->last
, "HTTP_", sizeof("HTTP_") - 1);
1016 for (n
= 0; n
< header
[i
].key
.len
; n
++) {
1017 ch
= header
[i
].key
.data
[n
];
1019 if (ch
>= 'a' && ch
<= 'z') {
1022 } else if (ch
== '-') {
1029 b
->last
= ngx_copy(b
->last
, header
[i
].value
.data
, val_len
);
1031 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1032 "fastcgi param: \"%*s: %*s\"",
1033 key_len
, b
->last
- (key_len
+ val_len
),
1034 val_len
, b
->last
- val_len
);
1043 ngx_memzero(b
->last
, padding
);
1048 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
1049 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
1052 h
->type
= NGX_HTTP_FASTCGI_PARAMS
;
1053 h
->request_id_hi
= 0;
1054 h
->request_id_lo
= 1;
1055 h
->content_length_hi
= 0;
1056 h
->content_length_lo
= 0;
1057 h
->padding_length
= 0;
1060 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
1061 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
1063 if (flcf
->upstream
.pass_request_body
) {
1064 body
= r
->upstream
->request_bufs
;
1065 r
->upstream
->request_bufs
= cl
;
1067 #if (NGX_SUPPRESS_WARN)
1074 if (body
->buf
->in_file
) {
1075 file_pos
= body
->buf
->file_pos
;
1078 pos
= body
->buf
->pos
;
1084 b
= ngx_alloc_buf(r
->pool
);
1089 ngx_memcpy(b
, body
->buf
, sizeof(ngx_buf_t
));
1091 if (body
->buf
->in_file
) {
1092 b
->file_pos
= file_pos
;
1093 file_pos
+= 32 * 1024;
1095 if (file_pos
>= body
->buf
->file_last
) {
1096 file_pos
= body
->buf
->file_last
;
1100 b
->file_last
= file_pos
;
1101 len
= (ngx_uint_t
) (file_pos
- b
->file_pos
);
1107 if (pos
>= body
->buf
->last
) {
1108 pos
= body
->buf
->last
;
1113 len
= (ngx_uint_t
) (pos
- b
->pos
);
1116 padding
= 8 - len
% 8;
1117 padding
= (padding
== 8) ? 0 : padding
;
1120 h
->type
= NGX_HTTP_FASTCGI_STDIN
;
1121 h
->request_id_hi
= 0;
1122 h
->request_id_lo
= 1;
1123 h
->content_length_hi
= (u_char
) ((len
>> 8) & 0xff);
1124 h
->content_length_lo
= (u_char
) (len
& 0xff);
1125 h
->padding_length
= (u_char
) padding
;
1128 cl
->next
= ngx_alloc_chain_link(r
->pool
);
1129 if (cl
->next
== NULL
) {
1136 b
= ngx_create_temp_buf(r
->pool
,
1137 sizeof(ngx_http_fastcgi_header_t
)
1144 ngx_memzero(b
->last
, padding
);
1148 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
1149 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
1151 cl
->next
= ngx_alloc_chain_link(r
->pool
);
1152 if (cl
->next
== NULL
) {
1165 r
->upstream
->request_bufs
= cl
;
1169 h
->type
= NGX_HTTP_FASTCGI_STDIN
;
1170 h
->request_id_hi
= 0;
1171 h
->request_id_lo
= 1;
1172 h
->content_length_hi
= 0;
1173 h
->content_length_lo
= 0;
1174 h
->padding_length
= 0;
1184 ngx_http_fastcgi_reinit_request(ngx_http_request_t
*r
)
1186 ngx_http_fastcgi_ctx_t
*f
;
1188 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
1194 f
->state
= ngx_http_fastcgi_st_version
;
1195 f
->fastcgi_stdout
= 0;
1196 f
->large_stderr
= 0;
1205 ngx_http_fastcgi_process_header(ngx_http_request_t
*r
)
1207 u_char
*p
, *msg
, *start
, *last
,
1208 *part_start
, *part_end
;
1210 ngx_str_t
*status_line
, *pattern
;
1211 ngx_int_t rc
, status
;
1215 ngx_http_upstream_t
*u
;
1216 ngx_http_fastcgi_ctx_t
*f
;
1217 ngx_http_upstream_header_t
*hh
;
1218 ngx_http_fastcgi_loc_conf_t
*flcf
;
1219 ngx_http_fastcgi_split_part_t
*part
;
1220 ngx_http_upstream_main_conf_t
*umcf
;
1222 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
1224 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
1230 if (f
->state
< ngx_http_fastcgi_st_data
) {
1232 f
->pos
= u
->buffer
.pos
;
1233 f
->last
= u
->buffer
.last
;
1235 rc
= ngx_http_fastcgi_process_record(r
, f
);
1237 u
->buffer
.pos
= f
->pos
;
1238 u
->buffer
.last
= f
->last
;
1240 if (rc
== NGX_AGAIN
) {
1244 if (rc
== NGX_ERROR
) {
1245 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1248 if (f
->type
!= NGX_HTTP_FASTCGI_STDOUT
1249 && f
->type
!= NGX_HTTP_FASTCGI_STDERR
)
1251 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1252 "upstream sent unexpected FastCGI record: %d",
1255 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1258 if (f
->type
== NGX_HTTP_FASTCGI_STDOUT
&& f
->length
== 0) {
1259 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1260 "upstream prematurely closed FastCGI stdout");
1262 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1266 if (f
->state
== ngx_http_fastcgi_st_padding
) {
1268 if (u
->buffer
.pos
+ f
->padding
< u
->buffer
.last
) {
1269 f
->state
= ngx_http_fastcgi_st_version
;
1270 u
->buffer
.pos
+= f
->padding
;
1275 if (u
->buffer
.pos
+ f
->padding
== u
->buffer
.last
) {
1276 f
->state
= ngx_http_fastcgi_st_version
;
1277 u
->buffer
.pos
= u
->buffer
.last
;
1282 f
->padding
-= u
->buffer
.last
- u
->buffer
.pos
;
1283 u
->buffer
.pos
= u
->buffer
.last
;
1289 /* f->state == ngx_http_fastcgi_st_data */
1291 if (f
->type
== NGX_HTTP_FASTCGI_STDERR
) {
1294 msg
= u
->buffer
.pos
;
1296 if (u
->buffer
.pos
+ f
->length
<= u
->buffer
.last
) {
1297 u
->buffer
.pos
+= f
->length
;
1299 f
->state
= ngx_http_fastcgi_st_padding
;
1302 f
->length
-= u
->buffer
.last
- u
->buffer
.pos
;
1303 u
->buffer
.pos
= u
->buffer
.last
;
1306 for (p
= u
->buffer
.pos
- 1; msg
< p
; p
--) {
1307 if (*p
!= LF
&& *p
!= CR
&& *p
!= '.' && *p
!= ' ') {
1314 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1315 "FastCGI sent in stderr: \"%*s\"", p
- msg
, msg
);
1317 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
1319 if (flcf
->catch_stderr
) {
1320 pattern
= flcf
->catch_stderr
->elts
;
1322 for (i
= 0; i
< flcf
->catch_stderr
->nelts
; i
++) {
1323 if (ngx_strnstr(msg
, (char *) pattern
[i
].data
,
1327 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1332 if (u
->buffer
.pos
== u
->buffer
.last
) {
1334 if (!f
->fastcgi_stdout
) {
1337 * the special handling the large number
1338 * of the PHP warnings to not allocate memory
1341 #if (NGX_HTTP_CACHE)
1343 u
->buffer
.pos
= u
->buffer
.start
1344 + r
->cache
->header_start
;
1346 u
->buffer
.pos
= u
->buffer
.start
;
1349 u
->buffer
.pos
= u
->buffer
.start
;
1351 u
->buffer
.last
= u
->buffer
.pos
;
1352 f
->large_stderr
= 1;
1359 f
->state
= ngx_http_fastcgi_st_padding
;
1366 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1368 #if (NGX_HTTP_CACHE)
1370 if (f
->large_stderr
&& r
->cache
) {
1373 ngx_http_fastcgi_header_t
*fh
;
1375 start
= u
->buffer
.start
+ r
->cache
->header_start
;
1377 len
= u
->buffer
.pos
- start
- 2 * sizeof(ngx_http_fastcgi_header_t
);
1380 * A tail of large stderr output before HTTP header is placed
1381 * in a cache file without a FastCGI record header.
1382 * To workaround it we put a dummy FastCGI record header at the
1383 * start of the stderr output or update r->cache_header_start,
1384 * if there is no enough place for the record header.
1388 fh
= (ngx_http_fastcgi_header_t
*) start
;
1390 fh
->type
= NGX_HTTP_FASTCGI_STDERR
;
1391 fh
->request_id_hi
= 0;
1392 fh
->request_id_lo
= 1;
1393 fh
->content_length_hi
= (u_char
) ((len
>> 8) & 0xff);
1394 fh
->content_length_lo
= (u_char
) (len
& 0xff);
1395 fh
->padding_length
= 0;
1399 r
->cache
->header_start
+= u
->buffer
.pos
- start
1400 - sizeof(ngx_http_fastcgi_header_t
);
1403 f
->large_stderr
= 0;
1408 f
->fastcgi_stdout
= 1;
1410 start
= u
->buffer
.pos
;
1412 if (u
->buffer
.pos
+ f
->length
< u
->buffer
.last
) {
1415 * set u->buffer.last to the end of the FastCGI record data
1416 * for ngx_http_parse_header_line()
1419 last
= u
->buffer
.last
;
1420 u
->buffer
.last
= u
->buffer
.pos
+ f
->length
;
1428 part_start
= u
->buffer
.pos
;
1429 part_end
= u
->buffer
.last
;
1431 rc
= ngx_http_parse_header_line(r
, &u
->buffer
, 1);
1433 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1434 "http fastcgi parser: %d", rc
);
1436 if (rc
== NGX_AGAIN
) {
1442 /* a header line has been parsed successfully */
1444 h
= ngx_list_push(&u
->headers_in
.headers
);
1449 if (f
->split_parts
&& f
->split_parts
->nelts
) {
1451 part
= f
->split_parts
->elts
;
1452 size
= u
->buffer
.pos
- part_start
;
1454 for (i
= 0; i
< f
->split_parts
->nelts
; i
++) {
1455 size
+= part
[i
].end
- part
[i
].start
;
1458 p
= ngx_pnalloc(r
->pool
, size
);
1465 for (i
= 0; i
< f
->split_parts
->nelts
; i
++) {
1466 p
= ngx_cpymem(p
, part
[i
].start
,
1467 part
[i
].end
- part
[i
].start
);
1470 p
= ngx_cpymem(p
, part_start
, u
->buffer
.pos
- part_start
);
1474 f
->split_parts
->nelts
= 0;
1476 rc
= ngx_http_parse_header_line(r
, &buf
, 1);
1478 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
1479 h
->key
.data
= r
->header_name_start
;
1480 h
->key
.data
[h
->key
.len
] = '\0';
1482 h
->value
.len
= r
->header_end
- r
->header_start
;
1483 h
->value
.data
= r
->header_start
;
1484 h
->value
.data
[h
->value
.len
] = '\0';
1486 h
->lowcase_key
= ngx_pnalloc(r
->pool
, h
->key
.len
);
1487 if (h
->lowcase_key
== NULL
) {
1493 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
1494 h
->value
.len
= r
->header_end
- r
->header_start
;
1496 h
->key
.data
= ngx_pnalloc(r
->pool
,
1497 h
->key
.len
+ 1 + h
->value
.len
+ 1
1499 if (h
->key
.data
== NULL
) {
1503 h
->value
.data
= h
->key
.data
+ h
->key
.len
+ 1;
1504 h
->lowcase_key
= h
->key
.data
+ h
->key
.len
+ 1
1507 ngx_memcpy(h
->key
.data
, r
->header_name_start
, h
->key
.len
);
1508 h
->key
.data
[h
->key
.len
] = '\0';
1509 ngx_memcpy(h
->value
.data
, r
->header_start
, h
->value
.len
);
1510 h
->value
.data
[h
->value
.len
] = '\0';
1513 h
->hash
= r
->header_hash
;
1515 if (h
->key
.len
== r
->lowcase_index
) {
1516 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
1519 ngx_strlow(h
->lowcase_key
, h
->key
.data
, h
->key
.len
);
1522 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
->hash
,
1523 h
->lowcase_key
, h
->key
.len
);
1525 if (hh
&& hh
->handler(r
, h
, hh
->offset
) != NGX_OK
) {
1529 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1530 "http fastcgi header: \"%V: %V\"",
1531 &h
->key
, &h
->value
);
1533 if (u
->buffer
.pos
< u
->buffer
.last
) {
1537 /* the end of the FastCGI record */
1542 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1544 /* a whole header has been parsed successfully */
1546 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1547 "http fastcgi header done");
1549 if (u
->headers_in
.status
) {
1550 status_line
= &u
->headers_in
.status
->value
;
1552 status
= ngx_atoi(status_line
->data
, 3);
1554 if (status
== NGX_ERROR
) {
1555 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1556 "upstream sent invalid status \"%V\"",
1558 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1561 u
->headers_in
.status_n
= status
;
1562 u
->headers_in
.status_line
= *status_line
;
1564 } else if (u
->headers_in
.location
) {
1565 u
->headers_in
.status_n
= 302;
1566 ngx_str_set(&u
->headers_in
.status_line
,
1567 "302 Moved Temporarily");
1570 u
->headers_in
.status_n
= 200;
1571 ngx_str_set(&u
->headers_in
.status_line
, "200 OK");
1575 u
->state
->status
= u
->headers_in
.status_n
;
1581 /* there was error while a header line parsing */
1583 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1584 "upstream sent invalid header");
1586 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1590 u
->buffer
.last
= last
;
1593 f
->length
-= u
->buffer
.pos
- start
;
1595 if (f
->length
== 0) {
1596 f
->state
= ngx_http_fastcgi_st_padding
;
1599 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1607 /* rc == NGX_AGAIN */
1609 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1610 "upstream split a header line in FastCGI records");
1612 if (f
->split_parts
== NULL
) {
1613 f
->split_parts
= ngx_array_create(r
->pool
, 1,
1614 sizeof(ngx_http_fastcgi_split_part_t
));
1615 if (f
->split_parts
== NULL
) {
1620 part
= ngx_array_push(f
->split_parts
);
1625 part
->start
= part_start
;
1626 part
->end
= part_end
;
1628 if (u
->buffer
.pos
< u
->buffer
.last
) {
1638 ngx_http_fastcgi_input_filter_init(void *data
)
1640 ngx_http_request_t
*r
= data
;
1641 ngx_http_fastcgi_loc_conf_t
*flcf
;
1643 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
1645 r
->upstream
->pipe
->length
= flcf
->keep_conn
?
1646 (off_t
) sizeof(ngx_http_fastcgi_header_t
) : -1;
1653 ngx_http_fastcgi_input_filter(ngx_event_pipe_t
*p
, ngx_buf_t
*buf
)
1657 ngx_buf_t
*b
, **prev
;
1659 ngx_http_request_t
*r
;
1660 ngx_http_fastcgi_ctx_t
*f
;
1661 ngx_http_fastcgi_loc_conf_t
*flcf
;
1663 if (buf
->pos
== buf
->last
) {
1668 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
1669 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
1672 prev
= &buf
->shadow
;
1675 f
->last
= buf
->last
;
1678 if (f
->state
< ngx_http_fastcgi_st_data
) {
1680 rc
= ngx_http_fastcgi_process_record(r
, f
);
1682 if (rc
== NGX_AGAIN
) {
1686 if (rc
== NGX_ERROR
) {
1690 if (f
->type
== NGX_HTTP_FASTCGI_STDOUT
&& f
->length
== 0) {
1691 f
->state
= ngx_http_fastcgi_st_padding
;
1693 if (!flcf
->keep_conn
) {
1694 p
->upstream_done
= 1;
1697 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, p
->log
, 0,
1698 "http fastcgi closed stdout");
1703 if (f
->type
== NGX_HTTP_FASTCGI_END_REQUEST
) {
1705 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, p
->log
, 0,
1706 "http fastcgi sent end request");
1708 if (!flcf
->keep_conn
) {
1709 p
->upstream_done
= 1;
1718 if (f
->state
== ngx_http_fastcgi_st_padding
) {
1720 if (f
->type
== NGX_HTTP_FASTCGI_END_REQUEST
) {
1722 if (f
->pos
+ f
->padding
< f
->last
) {
1723 p
->upstream_done
= 1;
1727 if (f
->pos
+ f
->padding
== f
->last
) {
1728 p
->upstream_done
= 1;
1729 r
->upstream
->keepalive
= 1;
1733 f
->padding
-= f
->last
- f
->pos
;
1738 if (f
->pos
+ f
->padding
< f
->last
) {
1739 f
->state
= ngx_http_fastcgi_st_version
;
1740 f
->pos
+= f
->padding
;
1745 if (f
->pos
+ f
->padding
== f
->last
) {
1746 f
->state
= ngx_http_fastcgi_st_version
;
1751 f
->padding
-= f
->last
- f
->pos
;
1757 /* f->state == ngx_http_fastcgi_st_data */
1759 if (f
->type
== NGX_HTTP_FASTCGI_STDERR
) {
1763 if (f
->pos
== f
->last
) {
1769 if (f
->pos
+ f
->length
<= f
->last
) {
1770 f
->pos
+= f
->length
;
1772 f
->state
= ngx_http_fastcgi_st_padding
;
1775 f
->length
-= f
->last
- f
->pos
;
1779 for (m
= f
->pos
- 1; msg
< m
; m
--) {
1780 if (*m
!= LF
&& *m
!= CR
&& *m
!= '.' && *m
!= ' ') {
1785 ngx_log_error(NGX_LOG_ERR
, p
->log
, 0,
1786 "FastCGI sent in stderr: \"%*s\"",
1790 f
->state
= ngx_http_fastcgi_st_padding
;
1796 if (f
->type
== NGX_HTTP_FASTCGI_END_REQUEST
) {
1798 if (f
->pos
+ f
->length
<= f
->last
) {
1799 f
->state
= ngx_http_fastcgi_st_padding
;
1800 f
->pos
+= f
->length
;
1805 f
->length
-= f
->last
- f
->pos
;
1811 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1813 if (f
->pos
== f
->last
) {
1821 ngx_free_chain(p
->pool
, cl
);
1824 b
= ngx_alloc_buf(p
->pool
);
1830 ngx_memzero(b
, sizeof(ngx_buf_t
));
1833 b
->start
= buf
->start
;
1842 cl
= ngx_alloc_chain_link(p
->pool
);
1855 p
->last_in
= &cl
->next
;
1858 /* STUB */ b
->num
= buf
->num
;
1860 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, p
->log
, 0,
1861 "input buf #%d %p", b
->num
, b
->pos
);
1863 if (f
->pos
+ f
->length
<= f
->last
) {
1864 f
->state
= ngx_http_fastcgi_st_padding
;
1865 f
->pos
+= f
->length
;
1871 f
->length
-= f
->last
- f
->pos
;
1879 if (flcf
->keep_conn
) {
1881 /* set p->length, minimal amount of data we want to see */
1883 if (f
->state
< ngx_http_fastcgi_st_data
) {
1886 } else if (f
->state
== ngx_http_fastcgi_st_padding
) {
1887 p
->length
= f
->padding
;
1890 /* ngx_http_fastcgi_st_data */
1892 p
->length
= f
->length
;
1900 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, p
->log
, 0,
1901 "input buf %p %z", b
->pos
, b
->last
- b
->pos
);
1906 /* there is no data record in the buf, add it to free chain */
1908 if (ngx_event_pipe_add_free_buf(p
, buf
) != NGX_OK
) {
1917 ngx_http_fastcgi_process_record(ngx_http_request_t
*r
,
1918 ngx_http_fastcgi_ctx_t
*f
)
1921 ngx_http_fastcgi_state_e state
;
1925 for (p
= f
->pos
; p
< f
->last
; p
++) {
1929 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1930 "http fastcgi record byte: %02Xd", ch
);
1934 case ngx_http_fastcgi_st_version
:
1936 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1937 "upstream sent unsupported FastCGI "
1938 "protocol version: %d", ch
);
1941 state
= ngx_http_fastcgi_st_type
;
1944 case ngx_http_fastcgi_st_type
:
1946 case NGX_HTTP_FASTCGI_STDOUT
:
1947 case NGX_HTTP_FASTCGI_STDERR
:
1948 case NGX_HTTP_FASTCGI_END_REQUEST
:
1949 f
->type
= (ngx_uint_t
) ch
;
1952 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1953 "upstream sent invalid FastCGI "
1954 "record type: %d", ch
);
1958 state
= ngx_http_fastcgi_st_request_id_hi
;
1961 /* we support the single request per connection */
1963 case ngx_http_fastcgi_st_request_id_hi
:
1965 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1966 "upstream sent unexpected FastCGI "
1967 "request id high byte: %d", ch
);
1970 state
= ngx_http_fastcgi_st_request_id_lo
;
1973 case ngx_http_fastcgi_st_request_id_lo
:
1975 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1976 "upstream sent unexpected FastCGI "
1977 "request id low byte: %d", ch
);
1980 state
= ngx_http_fastcgi_st_content_length_hi
;
1983 case ngx_http_fastcgi_st_content_length_hi
:
1984 f
->length
= ch
<< 8;
1985 state
= ngx_http_fastcgi_st_content_length_lo
;
1988 case ngx_http_fastcgi_st_content_length_lo
:
1989 f
->length
|= (size_t) ch
;
1990 state
= ngx_http_fastcgi_st_padding_length
;
1993 case ngx_http_fastcgi_st_padding_length
:
1994 f
->padding
= (size_t) ch
;
1995 state
= ngx_http_fastcgi_st_reserved
;
1998 case ngx_http_fastcgi_st_reserved
:
1999 state
= ngx_http_fastcgi_st_data
;
2001 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2002 "http fastcgi record length: %z", f
->length
);
2009 /* suppress warning */
2010 case ngx_http_fastcgi_st_data
:
2011 case ngx_http_fastcgi_st_padding
:
2023 ngx_http_fastcgi_abort_request(ngx_http_request_t
*r
)
2025 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2026 "abort http fastcgi request");
2033 ngx_http_fastcgi_finalize_request(ngx_http_request_t
*r
, ngx_int_t rc
)
2035 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2036 "finalize http fastcgi request");
2043 ngx_http_fastcgi_add_variables(ngx_conf_t
*cf
)
2045 ngx_http_variable_t
*var
, *v
;
2047 for (v
= ngx_http_fastcgi_vars
; v
->name
.len
; v
++) {
2048 var
= ngx_http_add_variable(cf
, &v
->name
, v
->flags
);
2053 var
->get_handler
= v
->get_handler
;
2054 var
->data
= v
->data
;
2062 ngx_http_fastcgi_create_loc_conf(ngx_conf_t
*cf
)
2064 ngx_http_fastcgi_loc_conf_t
*conf
;
2066 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_fastcgi_loc_conf_t
));
2072 * set by ngx_pcalloc():
2074 * conf->upstream.bufs.num = 0;
2075 * conf->upstream.ignore_headers = 0;
2076 * conf->upstream.next_upstream = 0;
2077 * conf->upstream.cache_use_stale = 0;
2078 * conf->upstream.cache_methods = 0;
2079 * conf->upstream.temp_path = NULL;
2080 * conf->upstream.hide_headers_hash = { NULL, 0 };
2081 * conf->upstream.uri = { 0, NULL };
2082 * conf->upstream.location = NULL;
2083 * conf->upstream.store_lengths = NULL;
2084 * conf->upstream.store_values = NULL;
2086 * conf->index.len = { 0, NULL };
2089 conf
->upstream
.store
= NGX_CONF_UNSET
;
2090 conf
->upstream
.store_access
= NGX_CONF_UNSET_UINT
;
2091 conf
->upstream
.buffering
= NGX_CONF_UNSET
;
2092 conf
->upstream
.ignore_client_abort
= NGX_CONF_UNSET
;
2094 conf
->upstream
.local
= NGX_CONF_UNSET_PTR
;
2096 conf
->upstream
.connect_timeout
= NGX_CONF_UNSET_MSEC
;
2097 conf
->upstream
.send_timeout
= NGX_CONF_UNSET_MSEC
;
2098 conf
->upstream
.read_timeout
= NGX_CONF_UNSET_MSEC
;
2100 conf
->upstream
.send_lowat
= NGX_CONF_UNSET_SIZE
;
2101 conf
->upstream
.buffer_size
= NGX_CONF_UNSET_SIZE
;
2103 conf
->upstream
.busy_buffers_size_conf
= NGX_CONF_UNSET_SIZE
;
2104 conf
->upstream
.max_temp_file_size_conf
= NGX_CONF_UNSET_SIZE
;
2105 conf
->upstream
.temp_file_write_size_conf
= NGX_CONF_UNSET_SIZE
;
2107 conf
->upstream
.pass_request_headers
= NGX_CONF_UNSET
;
2108 conf
->upstream
.pass_request_body
= NGX_CONF_UNSET
;
2110 #if (NGX_HTTP_CACHE)
2111 conf
->upstream
.cache
= NGX_CONF_UNSET_PTR
;
2112 conf
->upstream
.cache_min_uses
= NGX_CONF_UNSET_UINT
;
2113 conf
->upstream
.cache_bypass
= NGX_CONF_UNSET_PTR
;
2114 conf
->upstream
.no_cache
= NGX_CONF_UNSET_PTR
;
2115 conf
->upstream
.cache_valid
= NGX_CONF_UNSET_PTR
;
2116 conf
->upstream
.cache_lock
= NGX_CONF_UNSET
;
2117 conf
->upstream
.cache_lock_timeout
= NGX_CONF_UNSET_MSEC
;
2120 conf
->upstream
.hide_headers
= NGX_CONF_UNSET_PTR
;
2121 conf
->upstream
.pass_headers
= NGX_CONF_UNSET_PTR
;
2123 conf
->upstream
.intercept_errors
= NGX_CONF_UNSET
;
2125 /* "fastcgi_cyclic_temp_file" is disabled */
2126 conf
->upstream
.cyclic_temp_file
= 0;
2128 conf
->catch_stderr
= NGX_CONF_UNSET_PTR
;
2130 conf
->keep_conn
= NGX_CONF_UNSET
;
2132 ngx_str_set(&conf
->upstream
.module
, "fastcgi");
2139 ngx_http_fastcgi_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
2141 ngx_http_fastcgi_loc_conf_t
*prev
= parent
;
2142 ngx_http_fastcgi_loc_conf_t
*conf
= child
;
2145 ngx_hash_init_t hash
;
2146 ngx_http_core_loc_conf_t
*clcf
;
2148 if (conf
->upstream
.store
!= 0) {
2149 ngx_conf_merge_value(conf
->upstream
.store
,
2150 prev
->upstream
.store
, 0);
2152 if (conf
->upstream
.store_lengths
== NULL
) {
2153 conf
->upstream
.store_lengths
= prev
->upstream
.store_lengths
;
2154 conf
->upstream
.store_values
= prev
->upstream
.store_values
;
2158 ngx_conf_merge_uint_value(conf
->upstream
.store_access
,
2159 prev
->upstream
.store_access
, 0600);
2161 ngx_conf_merge_value(conf
->upstream
.buffering
,
2162 prev
->upstream
.buffering
, 1);
2164 ngx_conf_merge_value(conf
->upstream
.ignore_client_abort
,
2165 prev
->upstream
.ignore_client_abort
, 0);
2167 ngx_conf_merge_ptr_value(conf
->upstream
.local
,
2168 prev
->upstream
.local
, NULL
);
2170 ngx_conf_merge_msec_value(conf
->upstream
.connect_timeout
,
2171 prev
->upstream
.connect_timeout
, 60000);
2173 ngx_conf_merge_msec_value(conf
->upstream
.send_timeout
,
2174 prev
->upstream
.send_timeout
, 60000);
2176 ngx_conf_merge_msec_value(conf
->upstream
.read_timeout
,
2177 prev
->upstream
.read_timeout
, 60000);
2179 ngx_conf_merge_size_value(conf
->upstream
.send_lowat
,
2180 prev
->upstream
.send_lowat
, 0);
2182 ngx_conf_merge_size_value(conf
->upstream
.buffer_size
,
2183 prev
->upstream
.buffer_size
,
2184 (size_t) ngx_pagesize
);
2187 ngx_conf_merge_bufs_value(conf
->upstream
.bufs
, prev
->upstream
.bufs
,
2190 if (conf
->upstream
.bufs
.num
< 2) {
2191 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2192 "there must be at least 2 \"fastcgi_buffers\"");
2193 return NGX_CONF_ERROR
;
2197 size
= conf
->upstream
.buffer_size
;
2198 if (size
< conf
->upstream
.bufs
.size
) {
2199 size
= conf
->upstream
.bufs
.size
;
2203 ngx_conf_merge_size_value(conf
->upstream
.busy_buffers_size_conf
,
2204 prev
->upstream
.busy_buffers_size_conf
,
2205 NGX_CONF_UNSET_SIZE
);
2207 if (conf
->upstream
.busy_buffers_size_conf
== NGX_CONF_UNSET_SIZE
) {
2208 conf
->upstream
.busy_buffers_size
= 2 * size
;
2210 conf
->upstream
.busy_buffers_size
=
2211 conf
->upstream
.busy_buffers_size_conf
;
2214 if (conf
->upstream
.busy_buffers_size
< size
) {
2215 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2216 "\"fastcgi_busy_buffers_size\" must be equal to or greater than "
2217 "the maximum of the value of \"fastcgi_buffer_size\" and "
2218 "one of the \"fastcgi_buffers\"");
2220 return NGX_CONF_ERROR
;
2223 if (conf
->upstream
.busy_buffers_size
2224 > (conf
->upstream
.bufs
.num
- 1) * conf
->upstream
.bufs
.size
)
2226 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2227 "\"fastcgi_busy_buffers_size\" must be less than "
2228 "the size of all \"fastcgi_buffers\" minus one buffer");
2230 return NGX_CONF_ERROR
;
2234 ngx_conf_merge_size_value(conf
->upstream
.temp_file_write_size_conf
,
2235 prev
->upstream
.temp_file_write_size_conf
,
2236 NGX_CONF_UNSET_SIZE
);
2238 if (conf
->upstream
.temp_file_write_size_conf
== NGX_CONF_UNSET_SIZE
) {
2239 conf
->upstream
.temp_file_write_size
= 2 * size
;
2241 conf
->upstream
.temp_file_write_size
=
2242 conf
->upstream
.temp_file_write_size_conf
;
2245 if (conf
->upstream
.temp_file_write_size
< size
) {
2246 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2247 "\"fastcgi_temp_file_write_size\" must be equal to or greater "
2248 "than the maximum of the value of \"fastcgi_buffer_size\" and "
2249 "one of the \"fastcgi_buffers\"");
2251 return NGX_CONF_ERROR
;
2255 ngx_conf_merge_size_value(conf
->upstream
.max_temp_file_size_conf
,
2256 prev
->upstream
.max_temp_file_size_conf
,
2257 NGX_CONF_UNSET_SIZE
);
2259 if (conf
->upstream
.max_temp_file_size_conf
== NGX_CONF_UNSET_SIZE
) {
2260 conf
->upstream
.max_temp_file_size
= 1024 * 1024 * 1024;
2262 conf
->upstream
.max_temp_file_size
=
2263 conf
->upstream
.max_temp_file_size_conf
;
2266 if (conf
->upstream
.max_temp_file_size
!= 0
2267 && conf
->upstream
.max_temp_file_size
< size
)
2269 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2270 "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
2271 "temporary files usage or must be equal to or greater than "
2272 "the maximum of the value of \"fastcgi_buffer_size\" and "
2273 "one of the \"fastcgi_buffers\"");
2275 return NGX_CONF_ERROR
;
2279 ngx_conf_merge_bitmask_value(conf
->upstream
.ignore_headers
,
2280 prev
->upstream
.ignore_headers
,
2281 NGX_CONF_BITMASK_SET
);
2284 ngx_conf_merge_bitmask_value(conf
->upstream
.next_upstream
,
2285 prev
->upstream
.next_upstream
,
2286 (NGX_CONF_BITMASK_SET
2287 |NGX_HTTP_UPSTREAM_FT_ERROR
2288 |NGX_HTTP_UPSTREAM_FT_TIMEOUT
));
2290 if (conf
->upstream
.next_upstream
& NGX_HTTP_UPSTREAM_FT_OFF
) {
2291 conf
->upstream
.next_upstream
= NGX_CONF_BITMASK_SET
2292 |NGX_HTTP_UPSTREAM_FT_OFF
;
2295 if (ngx_conf_merge_path_value(cf
, &conf
->upstream
.temp_path
,
2296 prev
->upstream
.temp_path
,
2297 &ngx_http_fastcgi_temp_path
)
2300 return NGX_CONF_ERROR
;
2303 #if (NGX_HTTP_CACHE)
2305 ngx_conf_merge_ptr_value(conf
->upstream
.cache
,
2306 prev
->upstream
.cache
, NULL
);
2308 if (conf
->upstream
.cache
&& conf
->upstream
.cache
->data
== NULL
) {
2309 ngx_shm_zone_t
*shm_zone
;
2311 shm_zone
= conf
->upstream
.cache
;
2313 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2314 "\"fastcgi_cache\" zone \"%V\" is unknown",
2315 &shm_zone
->shm
.name
);
2317 return NGX_CONF_ERROR
;
2320 ngx_conf_merge_uint_value(conf
->upstream
.cache_min_uses
,
2321 prev
->upstream
.cache_min_uses
, 1);
2323 ngx_conf_merge_bitmask_value(conf
->upstream
.cache_use_stale
,
2324 prev
->upstream
.cache_use_stale
,
2325 (NGX_CONF_BITMASK_SET
2326 |NGX_HTTP_UPSTREAM_FT_OFF
));
2328 if (conf
->upstream
.cache_use_stale
& NGX_HTTP_UPSTREAM_FT_OFF
) {
2329 conf
->upstream
.cache_use_stale
= NGX_CONF_BITMASK_SET
2330 |NGX_HTTP_UPSTREAM_FT_OFF
;
2333 if (conf
->upstream
.cache_use_stale
& NGX_HTTP_UPSTREAM_FT_ERROR
) {
2334 conf
->upstream
.cache_use_stale
|= NGX_HTTP_UPSTREAM_FT_NOLIVE
;
2337 if (conf
->upstream
.cache_methods
== 0) {
2338 conf
->upstream
.cache_methods
= prev
->upstream
.cache_methods
;
2341 conf
->upstream
.cache_methods
|= NGX_HTTP_GET
|NGX_HTTP_HEAD
;
2343 ngx_conf_merge_ptr_value(conf
->upstream
.cache_bypass
,
2344 prev
->upstream
.cache_bypass
, NULL
);
2346 ngx_conf_merge_ptr_value(conf
->upstream
.no_cache
,
2347 prev
->upstream
.no_cache
, NULL
);
2349 if (conf
->upstream
.no_cache
&& conf
->upstream
.cache_bypass
== NULL
) {
2350 ngx_log_error(NGX_LOG_WARN
, cf
->log
, 0,
2351 "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, "
2352 "now it should be used together with \"fastcgi_cache_bypass\"");
2355 ngx_conf_merge_ptr_value(conf
->upstream
.cache_valid
,
2356 prev
->upstream
.cache_valid
, NULL
);
2358 if (conf
->cache_key
.value
.data
== NULL
) {
2359 conf
->cache_key
= prev
->cache_key
;
2362 ngx_conf_merge_value(conf
->upstream
.cache_lock
,
2363 prev
->upstream
.cache_lock
, 0);
2365 ngx_conf_merge_msec_value(conf
->upstream
.cache_lock_timeout
,
2366 prev
->upstream
.cache_lock_timeout
, 5000);
2370 ngx_conf_merge_value(conf
->upstream
.pass_request_headers
,
2371 prev
->upstream
.pass_request_headers
, 1);
2372 ngx_conf_merge_value(conf
->upstream
.pass_request_body
,
2373 prev
->upstream
.pass_request_body
, 1);
2375 ngx_conf_merge_value(conf
->upstream
.intercept_errors
,
2376 prev
->upstream
.intercept_errors
, 0);
2378 ngx_conf_merge_ptr_value(conf
->catch_stderr
, prev
->catch_stderr
, NULL
);
2380 ngx_conf_merge_value(conf
->keep_conn
, prev
->keep_conn
, 0);
2383 ngx_conf_merge_str_value(conf
->index
, prev
->index
, "");
2385 hash
.max_size
= 512;
2386 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
2387 hash
.name
= "fastcgi_hide_headers_hash";
2389 if (ngx_http_upstream_hide_headers_hash(cf
, &conf
->upstream
,
2390 &prev
->upstream
, ngx_http_fastcgi_hide_headers
, &hash
)
2393 return NGX_CONF_ERROR
;
2396 if (conf
->upstream
.upstream
== NULL
) {
2397 conf
->upstream
.upstream
= prev
->upstream
.upstream
;
2400 if (conf
->fastcgi_lengths
== NULL
) {
2401 conf
->fastcgi_lengths
= prev
->fastcgi_lengths
;
2402 conf
->fastcgi_values
= prev
->fastcgi_values
;
2405 if (conf
->upstream
.upstream
|| conf
->fastcgi_lengths
) {
2406 clcf
= ngx_http_conf_get_module_loc_conf(cf
, ngx_http_core_module
);
2407 if (clcf
->handler
== NULL
&& clcf
->lmt_excpt
) {
2408 clcf
->handler
= ngx_http_fastcgi_handler
;
2413 if (conf
->split_regex
== NULL
) {
2414 conf
->split_regex
= prev
->split_regex
;
2415 conf
->split_name
= prev
->split_name
;
2419 if (ngx_http_fastcgi_merge_params(cf
, conf
, prev
) != NGX_OK
) {
2420 return NGX_CONF_ERROR
;
2428 ngx_http_fastcgi_merge_params(ngx_conf_t
*cf
,
2429 ngx_http_fastcgi_loc_conf_t
*conf
, ngx_http_fastcgi_loc_conf_t
*prev
)
2435 ngx_array_t headers_names
;
2436 #if (NGX_HTTP_CACHE)
2437 ngx_array_t params_merged
;
2440 ngx_hash_init_t hash
;
2441 ngx_http_upstream_param_t
*src
;
2442 ngx_http_script_compile_t sc
;
2443 ngx_http_script_copy_code_t
*copy
;
2445 if (conf
->params_source
== NULL
) {
2446 conf
->params_source
= prev
->params_source
;
2448 if (prev
->headers_hash
.buckets
2449 #if (NGX_HTTP_CACHE)
2450 && ((conf
->upstream
.cache
== NULL
)
2451 == (prev
->upstream
.cache
== NULL
))
2455 conf
->flushes
= prev
->flushes
;
2456 conf
->params_len
= prev
->params_len
;
2457 conf
->params
= prev
->params
;
2458 conf
->headers_hash
= prev
->headers_hash
;
2459 conf
->header_params
= prev
->header_params
;
2465 if (conf
->params_source
== NULL
2466 #if (NGX_HTTP_CACHE)
2467 && (conf
->upstream
.cache
== NULL
)
2471 conf
->headers_hash
.buckets
= (void *) 1;
2475 conf
->params_len
= ngx_array_create(cf
->pool
, 64, 1);
2476 if (conf
->params_len
== NULL
) {
2480 conf
->params
= ngx_array_create(cf
->pool
, 512, 1);
2481 if (conf
->params
== NULL
) {
2485 if (ngx_array_init(&headers_names
, cf
->temp_pool
, 4, sizeof(ngx_hash_key_t
))
2491 if (conf
->params_source
) {
2492 src
= conf
->params_source
->elts
;
2493 nsrc
= conf
->params_source
->nelts
;
2500 #if (NGX_HTTP_CACHE)
2502 if (conf
->upstream
.cache
) {
2504 ngx_http_upstream_param_t
*s
;
2506 if (ngx_array_init(¶ms_merged
, cf
->temp_pool
, 4,
2507 sizeof(ngx_http_upstream_param_t
))
2513 for (i
= 0; i
< nsrc
; i
++) {
2515 s
= ngx_array_push(¶ms_merged
);
2523 h
= ngx_http_fastcgi_cache_headers
;
2525 while (h
->key
.len
) {
2527 src
= params_merged
.elts
;
2528 nsrc
= params_merged
.nelts
;
2530 for (i
= 0; i
< nsrc
; i
++) {
2531 if (ngx_strcasecmp(h
->key
.data
, src
[i
].key
.data
) == 0) {
2536 s
= ngx_array_push(¶ms_merged
);
2542 s
->value
= h
->value
;
2550 src
= params_merged
.elts
;
2551 nsrc
= params_merged
.nelts
;
2556 for (i
= 0; i
< nsrc
; i
++) {
2558 if (src
[i
].key
.len
> sizeof("HTTP_") - 1
2559 && ngx_strncmp(src
[i
].key
.data
, "HTTP_", sizeof("HTTP_") - 1) == 0)
2561 hk
= ngx_array_push(&headers_names
);
2566 hk
->key
.len
= src
[i
].key
.len
- 5;
2567 hk
->key
.data
= src
[i
].key
.data
+ 5;
2568 hk
->key_hash
= ngx_hash_key_lc(hk
->key
.data
, hk
->key
.len
);
2569 hk
->value
= (void *) 1;
2571 if (src
[i
].value
.len
== 0) {
2576 copy
= ngx_array_push_n(conf
->params_len
,
2577 sizeof(ngx_http_script_copy_code_t
));
2582 copy
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
2583 copy
->len
= src
[i
].key
.len
;
2585 copy
= ngx_array_push_n(conf
->params_len
,
2586 sizeof(ngx_http_script_copy_code_t
));
2591 copy
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
2592 copy
->len
= src
[i
].skip_empty
;
2595 size
= (sizeof(ngx_http_script_copy_code_t
)
2596 + src
[i
].key
.len
+ sizeof(uintptr_t) - 1)
2597 & ~(sizeof(uintptr_t) - 1);
2599 copy
= ngx_array_push_n(conf
->params
, size
);
2604 copy
->code
= ngx_http_script_copy_code
;
2605 copy
->len
= src
[i
].key
.len
;
2607 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
2608 ngx_memcpy(p
, src
[i
].key
.data
, src
[i
].key
.len
);
2611 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2614 sc
.source
= &src
[i
].value
;
2615 sc
.flushes
= &conf
->flushes
;
2616 sc
.lengths
= &conf
->params_len
;
2617 sc
.values
= &conf
->params
;
2619 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2623 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
2628 *code
= (uintptr_t) NULL
;
2631 code
= ngx_array_push_n(conf
->params
, sizeof(uintptr_t));
2636 *code
= (uintptr_t) NULL
;
2639 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
2644 *code
= (uintptr_t) NULL
;
2646 conf
->header_params
= headers_names
.nelts
;
2648 hash
.hash
= &conf
->headers_hash
;
2649 hash
.key
= ngx_hash_key_lc
;
2650 hash
.max_size
= 512;
2651 hash
.bucket_size
= 64;
2652 hash
.name
= "fastcgi_params_hash";
2653 hash
.pool
= cf
->pool
;
2654 hash
.temp_pool
= NULL
;
2656 return ngx_hash_init(&hash
, headers_names
.elts
, headers_names
.nelts
);
2661 ngx_http_fastcgi_script_name_variable(ngx_http_request_t
*r
,
2662 ngx_http_variable_value_t
*v
, uintptr_t data
)
2665 ngx_http_fastcgi_ctx_t
*f
;
2666 ngx_http_fastcgi_loc_conf_t
*flcf
;
2668 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
2670 f
= ngx_http_fastcgi_split(r
, flcf
);
2676 if (f
->script_name
.len
== 0
2677 || f
->script_name
.data
[f
->script_name
.len
- 1] != '/')
2679 v
->len
= f
->script_name
.len
;
2681 v
->no_cacheable
= 0;
2683 v
->data
= f
->script_name
.data
;
2688 v
->len
= f
->script_name
.len
+ flcf
->index
.len
;
2690 v
->data
= ngx_pnalloc(r
->pool
, v
->len
);
2691 if (v
->data
== NULL
) {
2695 p
= ngx_copy(v
->data
, f
->script_name
.data
, f
->script_name
.len
);
2696 ngx_memcpy(p
, flcf
->index
.data
, flcf
->index
.len
);
2703 ngx_http_fastcgi_path_info_variable(ngx_http_request_t
*r
,
2704 ngx_http_variable_value_t
*v
, uintptr_t data
)
2706 ngx_http_fastcgi_ctx_t
*f
;
2707 ngx_http_fastcgi_loc_conf_t
*flcf
;
2709 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
2711 f
= ngx_http_fastcgi_split(r
, flcf
);
2717 v
->len
= f
->path_info
.len
;
2719 v
->no_cacheable
= 0;
2721 v
->data
= f
->path_info
.data
;
2727 static ngx_http_fastcgi_ctx_t
*
2728 ngx_http_fastcgi_split(ngx_http_request_t
*r
, ngx_http_fastcgi_loc_conf_t
*flcf
)
2730 ngx_http_fastcgi_ctx_t
*f
;
2733 int captures
[(1 + 2) * 3];
2735 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
2738 f
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_fastcgi_ctx_t
));
2743 ngx_http_set_ctx(r
, f
, ngx_http_fastcgi_module
);
2746 if (f
->script_name
.len
) {
2750 if (flcf
->split_regex
== NULL
) {
2751 f
->script_name
= r
->uri
;
2755 n
= ngx_regex_exec(flcf
->split_regex
, &r
->uri
, captures
, (1 + 2) * 3);
2757 if (n
>= 0) { /* match */
2758 f
->script_name
.len
= captures
[3] - captures
[2];
2759 f
->script_name
.data
= r
->uri
.data
+ captures
[2];
2761 f
->path_info
.len
= captures
[5] - captures
[4];
2762 f
->path_info
.data
= r
->uri
.data
+ captures
[4];
2767 if (n
== NGX_REGEX_NO_MATCHED
) {
2768 f
->script_name
= r
->uri
;
2772 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
2773 ngx_regex_exec_n
" failed: %i on \"%V\" using \"%V\"",
2774 n
, &r
->uri
, &flcf
->split_name
);
2779 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
2782 f
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_fastcgi_ctx_t
));
2787 ngx_http_set_ctx(r
, f
, ngx_http_fastcgi_module
);
2790 f
->script_name
= r
->uri
;
2799 ngx_http_fastcgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2801 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
2804 ngx_str_t
*value
, *url
;
2806 ngx_http_core_loc_conf_t
*clcf
;
2807 ngx_http_script_compile_t sc
;
2809 if (flcf
->upstream
.upstream
|| flcf
->fastcgi_lengths
) {
2810 return "is duplicate";
2813 clcf
= ngx_http_conf_get_module_loc_conf(cf
, ngx_http_core_module
);
2815 clcf
->handler
= ngx_http_fastcgi_handler
;
2817 if (clcf
->name
.data
[clcf
->name
.len
- 1] == '/') {
2818 clcf
->auto_redirect
= 1;
2821 value
= cf
->args
->elts
;
2825 n
= ngx_http_script_variables_count(url
);
2829 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2833 sc
.lengths
= &flcf
->fastcgi_lengths
;
2834 sc
.values
= &flcf
->fastcgi_values
;
2836 sc
.complete_lengths
= 1;
2837 sc
.complete_values
= 1;
2839 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2840 return NGX_CONF_ERROR
;
2846 ngx_memzero(&u
, sizeof(ngx_url_t
));
2851 flcf
->upstream
.upstream
= ngx_http_upstream_add(cf
, &u
, 0);
2852 if (flcf
->upstream
.upstream
== NULL
) {
2853 return NGX_CONF_ERROR
;
2861 ngx_http_fastcgi_split_path_info(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2864 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
2867 ngx_regex_compile_t rc
;
2868 u_char errstr
[NGX_MAX_CONF_ERRSTR
];
2870 value
= cf
->args
->elts
;
2872 flcf
->split_name
= value
[1];
2874 ngx_memzero(&rc
, sizeof(ngx_regex_compile_t
));
2876 rc
.pattern
= value
[1];
2878 rc
.err
.len
= NGX_MAX_CONF_ERRSTR
;
2879 rc
.err
.data
= errstr
;
2881 if (ngx_regex_compile(&rc
) != NGX_OK
) {
2882 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0, "%V", &rc
.err
);
2883 return NGX_CONF_ERROR
;
2886 if (rc
.captures
!= 2) {
2887 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2888 "pattern \"%V\" must have 2 captures", &value
[1]);
2889 return NGX_CONF_ERROR
;
2892 flcf
->split_regex
= rc
.regex
;
2898 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2899 "\"%V\" requires PCRE library", &cmd
->name
);
2900 return NGX_CONF_ERROR
;
2907 ngx_http_fastcgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2909 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
2912 ngx_http_script_compile_t sc
;
2914 if (flcf
->upstream
.store
!= NGX_CONF_UNSET
2915 || flcf
->upstream
.store_lengths
)
2917 return "is duplicate";
2920 value
= cf
->args
->elts
;
2922 if (ngx_strcmp(value
[1].data
, "off") == 0) {
2923 flcf
->upstream
.store
= 0;
2927 #if (NGX_HTTP_CACHE)
2929 if (flcf
->upstream
.cache
!= NGX_CONF_UNSET_PTR
2930 && flcf
->upstream
.cache
!= NULL
)
2932 return "is incompatible with \"fastcgi_cache\"";
2937 if (ngx_strcmp(value
[1].data
, "on") == 0) {
2938 flcf
->upstream
.store
= 1;
2942 /* include the terminating '\0' into script */
2945 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2948 sc
.source
= &value
[1];
2949 sc
.lengths
= &flcf
->upstream
.store_lengths
;
2950 sc
.values
= &flcf
->upstream
.store_values
;
2951 sc
.variables
= ngx_http_script_variables_count(&value
[1]);
2952 sc
.complete_lengths
= 1;
2953 sc
.complete_values
= 1;
2955 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2956 return NGX_CONF_ERROR
;
2963 #if (NGX_HTTP_CACHE)
2966 ngx_http_fastcgi_cache(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2968 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
2972 value
= cf
->args
->elts
;
2974 if (flcf
->upstream
.cache
!= NGX_CONF_UNSET_PTR
) {
2975 return "is duplicate";
2978 if (ngx_strcmp(value
[1].data
, "off") == 0) {
2979 flcf
->upstream
.cache
= NULL
;
2983 if (flcf
->upstream
.store
> 0 || flcf
->upstream
.store_lengths
) {
2984 return "is incompatible with \"fastcgi_store\"";
2987 flcf
->upstream
.cache
= ngx_shared_memory_add(cf
, &value
[1], 0,
2988 &ngx_http_fastcgi_module
);
2989 if (flcf
->upstream
.cache
== NULL
) {
2990 return NGX_CONF_ERROR
;
2998 ngx_http_fastcgi_cache_key(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
3000 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
3003 ngx_http_compile_complex_value_t ccv
;
3005 value
= cf
->args
->elts
;
3007 if (flcf
->cache_key
.value
.data
) {
3008 return "is duplicate";
3011 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
3014 ccv
.value
= &value
[1];
3015 ccv
.complex_value
= &flcf
->cache_key
;
3017 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
3018 return NGX_CONF_ERROR
;
3028 ngx_http_fastcgi_lowat_check(ngx_conf_t
*cf
, void *post
, void *data
)
3033 if ((u_long
) *np
>= ngx_freebsd_net_inet_tcp_sendspace
) {
3034 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
3035 "\"fastcgi_send_lowat\" must be less than %d "
3036 "(sysctl net.inet.tcp.sendspace)",
3037 ngx_freebsd_net_inet_tcp_sendspace
);
3039 return NGX_CONF_ERROR
;
3042 #elif !(NGX_HAVE_SO_SNDLOWAT)
3045 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
3046 "\"fastcgi_send_lowat\" is not supported, ignored");