3 * Copyright (C) Igor Sysoev
7 #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
;
23 } ngx_http_fastcgi_loc_conf_t
;
27 ngx_http_fastcgi_st_version
= 0,
28 ngx_http_fastcgi_st_type
,
29 ngx_http_fastcgi_st_request_id_hi
,
30 ngx_http_fastcgi_st_request_id_lo
,
31 ngx_http_fastcgi_st_content_length_hi
,
32 ngx_http_fastcgi_st_content_length_lo
,
33 ngx_http_fastcgi_st_padding_length
,
34 ngx_http_fastcgi_st_reserved
,
35 ngx_http_fastcgi_st_data
,
36 ngx_http_fastcgi_st_padding
37 } ngx_http_fastcgi_state_e
;
43 } ngx_http_fastcgi_split_part_t
;
47 ngx_http_fastcgi_state_e state
;
54 ngx_uint_t fastcgi_stdout
; /* unsigned :1 */
56 ngx_array_t
*split_parts
;
57 } ngx_http_fastcgi_ctx_t
;
60 #define NGX_HTTP_FASTCGI_RESPONDER 1
62 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
63 #define NGX_HTTP_FASTCGI_ABORT_REQUEST 2
64 #define NGX_HTTP_FASTCGI_END_REQUEST 3
65 #define NGX_HTTP_FASTCGI_PARAMS 4
66 #define NGX_HTTP_FASTCGI_STDIN 5
67 #define NGX_HTTP_FASTCGI_STDOUT 6
68 #define NGX_HTTP_FASTCGI_STDERR 7
69 #define NGX_HTTP_FASTCGI_DATA 8
77 u_char content_length_hi
;
78 u_char content_length_lo
;
79 u_char padding_length
;
81 } ngx_http_fastcgi_header_t
;
89 } ngx_http_fastcgi_begin_request_t
;
97 } ngx_http_fastcgi_header_small_t
;
101 ngx_http_fastcgi_header_t h0
;
102 ngx_http_fastcgi_begin_request_t br
;
103 ngx_http_fastcgi_header_small_t h1
;
104 } ngx_http_fastcgi_request_start_t
;
107 static ngx_int_t
ngx_http_fastcgi_create_request(ngx_http_request_t
*r
);
108 static ngx_int_t
ngx_http_fastcgi_reinit_request(ngx_http_request_t
*r
);
109 static ngx_int_t
ngx_http_fastcgi_process_header(ngx_http_request_t
*r
);
110 static ngx_int_t
ngx_http_fastcgi_input_filter(ngx_event_pipe_t
*p
,
112 static ngx_int_t
ngx_http_fastcgi_process_record(ngx_http_request_t
*r
,
113 ngx_http_fastcgi_ctx_t
*f
);
114 static void ngx_http_fastcgi_abort_request(ngx_http_request_t
*r
);
115 static void ngx_http_fastcgi_finalize_request(ngx_http_request_t
*r
,
118 static ngx_int_t
ngx_http_fastcgi_add_variables(ngx_conf_t
*cf
);
119 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t
*cf
);
120 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t
*cf
,
121 void *parent
, void *child
);
122 static ngx_int_t
ngx_http_fastcgi_script_name_variable(ngx_http_request_t
*r
,
123 ngx_http_variable_value_t
*v
, uintptr_t data
);
125 static char *ngx_http_fastcgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
127 static char *ngx_http_fastcgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
129 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t
*cf
, void *post
,
132 static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t
*cf
,
133 ngx_command_t
*cmd
, void *conf
);
134 static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t
*cf
,
135 ngx_command_t
*cmd
, void *conf
);
138 static ngx_conf_post_t ngx_http_fastcgi_lowat_post
=
139 { ngx_http_fastcgi_lowat_check
};
142 static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks
[] = {
143 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR
},
144 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT
},
145 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER
},
146 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500
},
147 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503
},
148 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404
},
149 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF
},
150 { ngx_null_string
, 0 }
154 static ngx_command_t ngx_http_fastcgi_commands
[] = {
156 { ngx_string("fastcgi_pass"),
157 NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1
,
158 ngx_http_fastcgi_pass
,
159 NGX_HTTP_LOC_CONF_OFFSET
,
163 { ngx_string("fastcgi_index"),
164 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
165 ngx_conf_set_str_slot
,
166 NGX_HTTP_LOC_CONF_OFFSET
,
167 offsetof(ngx_http_fastcgi_loc_conf_t
, index
),
170 { ngx_string("fastcgi_store"),
171 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
172 ngx_http_fastcgi_store
,
173 NGX_HTTP_LOC_CONF_OFFSET
,
177 { ngx_string("fastcgi_store_access"),
178 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE123
,
179 ngx_conf_set_access_slot
,
180 NGX_HTTP_LOC_CONF_OFFSET
,
181 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.store_access
),
184 { ngx_string("fastcgi_ignore_client_abort"),
185 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
186 ngx_conf_set_flag_slot
,
187 NGX_HTTP_LOC_CONF_OFFSET
,
188 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.ignore_client_abort
),
191 { ngx_string("fastcgi_connect_timeout"),
192 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
193 ngx_conf_set_msec_slot
,
194 NGX_HTTP_LOC_CONF_OFFSET
,
195 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.connect_timeout
),
198 { ngx_string("fastcgi_send_timeout"),
199 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
200 ngx_conf_set_msec_slot
,
201 NGX_HTTP_LOC_CONF_OFFSET
,
202 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.send_timeout
),
205 { ngx_string("fastcgi_send_lowat"),
206 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
207 ngx_conf_set_size_slot
,
208 NGX_HTTP_LOC_CONF_OFFSET
,
209 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.send_lowat
),
210 &ngx_http_fastcgi_lowat_post
},
212 { ngx_string("fastcgi_buffer_size"),
213 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
214 ngx_conf_set_size_slot
,
215 NGX_HTTP_LOC_CONF_OFFSET
,
216 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.buffer_size
),
219 { ngx_string("fastcgi_pass_request_headers"),
220 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
221 ngx_conf_set_flag_slot
,
222 NGX_HTTP_LOC_CONF_OFFSET
,
223 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_request_headers
),
226 { ngx_string("fastcgi_pass_request_body"),
227 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
228 ngx_conf_set_flag_slot
,
229 NGX_HTTP_LOC_CONF_OFFSET
,
230 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_request_body
),
233 { ngx_string("fastcgi_intercept_errors"),
234 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
235 ngx_conf_set_flag_slot
,
236 NGX_HTTP_LOC_CONF_OFFSET
,
237 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.intercept_errors
),
240 { ngx_string("fastcgi_read_timeout"),
241 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
242 ngx_conf_set_msec_slot
,
243 NGX_HTTP_LOC_CONF_OFFSET
,
244 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.read_timeout
),
247 { ngx_string("fastcgi_buffers"),
248 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
249 ngx_conf_set_bufs_slot
,
250 NGX_HTTP_LOC_CONF_OFFSET
,
251 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.bufs
),
254 { ngx_string("fastcgi_busy_buffers_size"),
255 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
256 ngx_conf_set_size_slot
,
257 NGX_HTTP_LOC_CONF_OFFSET
,
258 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.busy_buffers_size_conf
),
261 { ngx_string("fastcgi_temp_path"),
262 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1234
,
263 ngx_conf_set_path_slot
,
264 NGX_HTTP_LOC_CONF_OFFSET
,
265 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.temp_path
),
266 (void *) ngx_garbage_collector_temp_handler
},
268 { ngx_string("fastcgi_max_temp_file_size"),
269 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
270 ngx_conf_set_size_slot
,
271 NGX_HTTP_LOC_CONF_OFFSET
,
272 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.max_temp_file_size_conf
),
275 { ngx_string("fastcgi_temp_file_write_size"),
276 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
277 ngx_conf_set_size_slot
,
278 NGX_HTTP_LOC_CONF_OFFSET
,
279 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.temp_file_write_size_conf
),
282 { ngx_string("fastcgi_next_upstream"),
283 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_1MORE
,
284 ngx_conf_set_bitmask_slot
,
285 NGX_HTTP_LOC_CONF_OFFSET
,
286 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.next_upstream
),
287 &ngx_http_fastcgi_next_upstream_masks
},
289 { ngx_string("fastcgi_upstream_max_fails"),
290 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
291 ngx_http_fastcgi_upstream_max_fails_unsupported
,
296 { ngx_string("fastcgi_upstream_fail_timeout"),
297 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE1
,
298 ngx_http_fastcgi_upstream_fail_timeout_unsupported
,
303 { ngx_string("fastcgi_param"),
304 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_TAKE2
,
305 ngx_conf_set_keyval_slot
,
306 NGX_HTTP_LOC_CONF_OFFSET
,
307 offsetof(ngx_http_fastcgi_loc_conf_t
, params_source
),
310 { ngx_string("fastcgi_pass_header"),
311 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
312 ngx_conf_set_str_array_slot
,
313 NGX_HTTP_LOC_CONF_OFFSET
,
314 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.pass_headers
),
317 { ngx_string("fastcgi_hide_header"),
318 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
319 ngx_conf_set_str_array_slot
,
320 NGX_HTTP_LOC_CONF_OFFSET
,
321 offsetof(ngx_http_fastcgi_loc_conf_t
, upstream
.hide_headers
),
324 { ngx_string("fastcgi_catch_stderr"),
325 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_FLAG
,
326 ngx_conf_set_str_array_slot
,
327 NGX_HTTP_LOC_CONF_OFFSET
,
328 offsetof(ngx_http_fastcgi_loc_conf_t
, catch_stderr
),
335 static ngx_http_module_t ngx_http_fastcgi_module_ctx
= {
336 ngx_http_fastcgi_add_variables
, /* preconfiguration */
337 NULL
, /* postconfiguration */
339 NULL
, /* create main configuration */
340 NULL
, /* init main configuration */
342 NULL
, /* create server configuration */
343 NULL
, /* merge server configuration */
345 ngx_http_fastcgi_create_loc_conf
, /* create location configuration */
346 ngx_http_fastcgi_merge_loc_conf
/* merge location configuration */
350 ngx_module_t ngx_http_fastcgi_module
= {
352 &ngx_http_fastcgi_module_ctx
, /* module context */
353 ngx_http_fastcgi_commands
, /* module directives */
354 NGX_HTTP_MODULE
, /* module type */
355 NULL
, /* init master */
356 NULL
, /* init module */
357 NULL
, /* init process */
358 NULL
, /* init thread */
359 NULL
, /* exit thread */
360 NULL
, /* exit process */
361 NULL
, /* exit master */
362 NGX_MODULE_V1_PADDING
366 static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start
= {
368 NGX_HTTP_FASTCGI_BEGIN_REQUEST
, /* type */
369 0, /* request_id_hi */
370 1, /* request_id_lo */
371 0, /* content_length_hi */
372 sizeof(ngx_http_fastcgi_begin_request_t
), /* content_length_lo */
373 0, /* padding_length */
377 NGX_HTTP_FASTCGI_RESPONDER
, /* role_lo */
378 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */
379 { 0, 0, 0, 0, 0 } }, /* reserved[5] */
382 NGX_HTTP_FASTCGI_PARAMS
, /* type */
383 0, /* request_id_hi */
384 1 }, /* request_id_lo */
389 static ngx_str_t ngx_http_fastcgi_script_name
=
390 ngx_string("fastcgi_script_name");
393 static ngx_str_t ngx_http_fastcgi_hide_headers
[] = {
394 ngx_string("Status"),
395 ngx_string("X-Accel-Expires"),
396 ngx_string("X-Accel-Redirect"),
397 ngx_string("X-Accel-Limit-Rate"),
398 ngx_string("X-Accel-Buffering"),
399 ngx_string("X-Accel-Charset"),
405 ngx_http_fastcgi_handler(ngx_http_request_t
*r
)
408 ngx_http_upstream_t
*u
;
409 ngx_http_fastcgi_loc_conf_t
*flcf
;
411 if (r
->subrequest_in_memory
) {
412 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
413 "ngx_http_fastcgi_module does not support "
414 "subrequest in memory");
415 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
418 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
420 u
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_upstream_t
));
422 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
425 u
->schema
= flcf
->upstream
.schema
;
427 u
->peer
.log
= r
->connection
->log
;
428 u
->peer
.log_error
= NGX_ERROR_ERR
;
430 u
->peer
.lock
= &r
->connection
->lock
;
433 u
->output
.tag
= (ngx_buf_tag_t
) &ngx_http_fastcgi_module
;
435 u
->conf
= &flcf
->upstream
;
437 u
->create_request
= ngx_http_fastcgi_create_request
;
438 u
->reinit_request
= ngx_http_fastcgi_reinit_request
;
439 u
->process_header
= ngx_http_fastcgi_process_header
;
440 u
->abort_request
= ngx_http_fastcgi_abort_request
;
441 u
->finalize_request
= ngx_http_fastcgi_finalize_request
;
445 u
->pipe
= ngx_pcalloc(r
->pool
, sizeof(ngx_event_pipe_t
));
446 if (u
->pipe
== NULL
) {
447 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
450 u
->pipe
->input_filter
= ngx_http_fastcgi_input_filter
;
451 u
->pipe
->input_ctx
= r
;
455 rc
= ngx_http_read_client_request_body(r
, ngx_http_upstream_init
);
457 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
) {
466 ngx_http_fastcgi_create_request(ngx_http_request_t
*r
)
470 size_t size
, len
, key_len
, val_len
, padding
;
471 ngx_uint_t i
, n
, next
;
473 ngx_chain_t
*cl
, *body
;
474 ngx_list_part_t
*part
;
475 ngx_table_elt_t
*header
;
476 ngx_http_script_code_pt code
;
477 ngx_http_script_engine_t e
, le
;
478 ngx_http_fastcgi_header_t
*h
;
479 ngx_http_fastcgi_loc_conf_t
*flcf
;
480 ngx_http_script_len_code_pt lcode
;
484 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
486 if (flcf
->params_len
) {
487 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
489 ngx_http_script_flush_no_cacheable_variables(r
, flcf
->flushes
);
492 le
.ip
= flcf
->params_len
->elts
;
495 while (*(uintptr_t *) le
.ip
) {
497 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
498 key_len
= lcode(&le
);
500 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode(&le
)) {
501 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
503 le
.ip
+= sizeof(uintptr_t);
505 len
+= 1 + key_len
+ ((val_len
> 127) ? 4 : 1) + val_len
;
509 if (flcf
->upstream
.pass_request_headers
) {
511 part
= &r
->headers_in
.headers
.part
;
514 for (i
= 0; /* void */; i
++) {
516 if (i
>= part
->nelts
) {
517 if (part
->next
== NULL
) {
526 len
+= ((sizeof("HTTP_") - 1 + header
[i
].key
.len
> 127) ? 4 : 1)
527 + ((header
[i
].value
.len
> 127) ? 4 : 1)
528 + sizeof("HTTP_") - 1 + header
[i
].key
.len
+ header
[i
].value
.len
;
534 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
535 "fastcgi request record is too big: %uz", len
);
540 padding
= 8 - len
% 8;
541 padding
= (padding
== 8) ? 0 : padding
;
544 size
= sizeof(ngx_http_fastcgi_header_t
)
545 + sizeof(ngx_http_fastcgi_begin_request_t
)
547 + sizeof(ngx_http_fastcgi_header_t
) /* NGX_HTTP_FASTCGI_PARAMS */
549 + sizeof(ngx_http_fastcgi_header_t
) /* NGX_HTTP_FASTCGI_PARAMS */
551 + sizeof(ngx_http_fastcgi_header_t
); /* NGX_HTTP_FASTCGI_STDIN */
554 b
= ngx_create_temp_buf(r
->pool
, size
);
559 cl
= ngx_alloc_chain_link(r
->pool
);
566 ngx_memcpy(b
->pos
, &ngx_http_fastcgi_request_start
,
567 sizeof(ngx_http_fastcgi_request_start_t
));
569 h
= (ngx_http_fastcgi_header_t
*)
570 (b
->pos
+ sizeof(ngx_http_fastcgi_header_t
)
571 + sizeof(ngx_http_fastcgi_begin_request_t
));
573 h
->content_length_hi
= (u_char
) ((len
>> 8) & 0xff);
574 h
->content_length_lo
= (u_char
) (len
& 0xff);
575 h
->padding_length
= (u_char
) padding
;
578 b
->last
= b
->pos
+ sizeof(ngx_http_fastcgi_header_t
)
579 + sizeof(ngx_http_fastcgi_begin_request_t
)
580 + sizeof(ngx_http_fastcgi_header_t
);
583 if (flcf
->params_len
) {
584 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
586 e
.ip
= flcf
->params
->elts
;
591 le
.ip
= flcf
->params_len
->elts
;
593 while (*(uintptr_t *) le
.ip
) {
595 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
596 key_len
= (u_char
) lcode(&le
);
598 for (val_len
= 0; *(uintptr_t *) le
.ip
; val_len
+= lcode(&le
)) {
599 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
601 le
.ip
+= sizeof(uintptr_t);
603 *e
.pos
++ = (u_char
) key_len
;
606 *e
.pos
++ = (u_char
) (((val_len
>> 24) & 0x7f) | 0x80);
607 *e
.pos
++ = (u_char
) ((val_len
>> 16) & 0xff);
608 *e
.pos
++ = (u_char
) ((val_len
>> 8) & 0xff);
609 *e
.pos
++ = (u_char
) (val_len
& 0xff);
612 *e
.pos
++ = (u_char
) val_len
;
615 while (*(uintptr_t *) e
.ip
) {
616 code
= *(ngx_http_script_code_pt
*) e
.ip
;
617 code((ngx_http_script_engine_t
*) &e
);
619 e
.ip
+= sizeof(uintptr_t);
621 ngx_log_debug4(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
622 "fastcgi param: \"%*s: %*s\"",
623 key_len
, e
.pos
- (key_len
+ val_len
),
624 val_len
, e
.pos
- val_len
);
631 if (flcf
->upstream
.pass_request_headers
) {
633 part
= &r
->headers_in
.headers
.part
;
636 for (i
= 0; /* void */; i
++) {
638 if (i
>= part
->nelts
) {
639 if (part
->next
== NULL
) {
648 len
= sizeof("HTTP_") - 1 + header
[i
].key
.len
;
650 *b
->last
++ = (u_char
) (((len
>> 24) & 0x7f) | 0x80);
651 *b
->last
++ = (u_char
) ((len
>> 16) & 0xff);
652 *b
->last
++ = (u_char
) ((len
>> 8) & 0xff);
653 *b
->last
++ = (u_char
) (len
& 0xff);
656 *b
->last
++ = (u_char
) len
;
659 len
= header
[i
].value
.len
;
661 *b
->last
++ = (u_char
) (((len
>> 24) & 0x7f) | 0x80);
662 *b
->last
++ = (u_char
) ((len
>> 16) & 0xff);
663 *b
->last
++ = (u_char
) ((len
>> 8) & 0xff);
664 *b
->last
++ = (u_char
) (len
& 0xff);
667 *b
->last
++ = (u_char
) len
;
670 b
->last
= ngx_cpymem(b
->last
, "HTTP_", sizeof("HTTP_") - 1);
672 for (n
= 0; n
< header
[i
].key
.len
; n
++) {
673 ch
= header
[i
].key
.data
[n
];
675 if (ch
>= 'a' && ch
<= 'z') {
678 } else if (ch
== '-') {
685 b
->last
= ngx_copy(b
->last
, header
[i
].value
.data
,
686 header
[i
].value
.len
);
692 ngx_memzero(b
->last
, padding
);
697 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
698 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
701 h
->type
= NGX_HTTP_FASTCGI_PARAMS
;
702 h
->request_id_hi
= 0;
703 h
->request_id_lo
= 1;
704 h
->content_length_hi
= 0;
705 h
->content_length_lo
= 0;
706 h
->padding_length
= 0;
709 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
710 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
712 if (flcf
->upstream
.pass_request_body
) {
713 body
= r
->upstream
->request_bufs
;
714 r
->upstream
->request_bufs
= cl
;
716 #if (NGX_SUPPRESS_WARN)
723 if (body
->buf
->in_file
) {
724 file_pos
= body
->buf
->file_pos
;
727 pos
= body
->buf
->pos
;
733 b
= ngx_alloc_buf(r
->pool
);
738 ngx_memcpy(b
, body
->buf
, sizeof(ngx_buf_t
));
740 if (body
->buf
->in_file
) {
741 b
->file_pos
= file_pos
;
742 file_pos
+= 32 * 1024;
744 if (file_pos
>= body
->buf
->file_last
) {
745 file_pos
= body
->buf
->file_last
;
749 b
->file_last
= file_pos
;
750 len
= (ngx_uint_t
) (file_pos
- b
->file_pos
);
756 if (pos
>= body
->buf
->last
) {
757 pos
= body
->buf
->last
;
762 len
= (ngx_uint_t
) (pos
- b
->pos
);
765 padding
= 8 - len
% 8;
766 padding
= (padding
== 8) ? 0 : padding
;
769 h
->type
= NGX_HTTP_FASTCGI_STDIN
;
770 h
->request_id_hi
= 0;
771 h
->request_id_lo
= 1;
772 h
->content_length_hi
= (u_char
) ((len
>> 8) & 0xff);
773 h
->content_length_lo
= (u_char
) (len
& 0xff);
774 h
->padding_length
= (u_char
) padding
;
777 cl
->next
= ngx_alloc_chain_link(r
->pool
);
778 if (cl
->next
== NULL
) {
785 b
= ngx_create_temp_buf(r
->pool
,
786 sizeof(ngx_http_fastcgi_header_t
)
793 ngx_memzero(b
->last
, padding
);
797 h
= (ngx_http_fastcgi_header_t
*) b
->last
;
798 b
->last
+= sizeof(ngx_http_fastcgi_header_t
);
800 cl
->next
= ngx_alloc_chain_link(r
->pool
);
801 if (cl
->next
== NULL
) {
814 r
->upstream
->request_bufs
= cl
;
818 h
->type
= NGX_HTTP_FASTCGI_STDIN
;
819 h
->request_id_hi
= 0;
820 h
->request_id_lo
= 1;
821 h
->content_length_hi
= 0;
822 h
->content_length_lo
= 0;
823 h
->padding_length
= 0;
833 ngx_http_fastcgi_reinit_request(ngx_http_request_t
*r
)
835 ngx_http_fastcgi_ctx_t
*f
;
837 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
843 f
->state
= ngx_http_fastcgi_st_version
;
844 f
->fastcgi_stdout
= 0;
851 ngx_http_fastcgi_process_header(ngx_http_request_t
*r
)
853 u_char
*p
, *start
, *last
, *part_start
;
855 ngx_str_t
*status_line
, line
, *pattern
;
856 ngx_int_t rc
, status
;
860 ngx_http_upstream_t
*u
;
861 ngx_http_fastcgi_ctx_t
*f
;
862 ngx_http_upstream_header_t
*hh
;
863 ngx_http_fastcgi_loc_conf_t
*flcf
;
864 ngx_http_fastcgi_split_part_t
*part
;
865 ngx_http_upstream_main_conf_t
*umcf
;
867 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
869 umcf
= ngx_http_get_module_main_conf(r
, ngx_http_upstream_module
);
872 f
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_fastcgi_ctx_t
));
877 ngx_http_set_ctx(r
, f
, ngx_http_fastcgi_module
);
884 if (f
->state
< ngx_http_fastcgi_st_data
) {
886 f
->pos
= u
->buffer
.pos
;
887 f
->last
= u
->buffer
.last
;
889 rc
= ngx_http_fastcgi_process_record(r
, f
);
891 u
->buffer
.pos
= f
->pos
;
892 u
->buffer
.last
= f
->last
;
894 if (rc
== NGX_AGAIN
) {
898 if (rc
== NGX_ERROR
) {
899 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
902 if (f
->type
!= NGX_HTTP_FASTCGI_STDOUT
903 && f
->type
!= NGX_HTTP_FASTCGI_STDERR
)
905 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
906 "upstream sent unexpected FastCGI record: %d",
909 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
912 if (f
->type
== NGX_HTTP_FASTCGI_STDOUT
&& f
->length
== 0) {
913 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
914 "upstream closed prematurely FastCGI stdout");
916 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
920 if (f
->state
== ngx_http_fastcgi_st_padding
) {
922 if (u
->buffer
.pos
+ f
->padding
< u
->buffer
.last
) {
923 f
->state
= ngx_http_fastcgi_st_version
;
924 u
->buffer
.pos
+= f
->padding
;
929 if (u
->buffer
.pos
+ f
->padding
== u
->buffer
.last
) {
930 f
->state
= ngx_http_fastcgi_st_version
;
931 u
->buffer
.pos
= u
->buffer
.last
;
936 f
->padding
-= u
->buffer
.last
- u
->buffer
.pos
;
937 u
->buffer
.pos
= u
->buffer
.last
;
943 /* f->state == ngx_http_fastcgi_st_data */
945 if (f
->type
== NGX_HTTP_FASTCGI_STDERR
) {
948 line
.data
= u
->buffer
.pos
;
950 if (u
->buffer
.pos
+ f
->length
<= u
->buffer
.last
) {
951 line
.len
= f
->length
;
952 u
->buffer
.pos
+= f
->length
;
954 f
->state
= ngx_http_fastcgi_st_padding
;
957 line
.len
= u
->buffer
.last
- u
->buffer
.pos
;
958 f
->length
-= u
->buffer
.last
- u
->buffer
.pos
;
959 u
->buffer
.pos
= u
->buffer
.last
;
962 while (line
.data
[line
.len
- 1] == LF
963 || line
.data
[line
.len
- 1] == CR
964 || line
.data
[line
.len
- 1] == '.'
965 || line
.data
[line
.len
- 1] == ' ')
970 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
971 "FastCGI sent in stderr: \"%V\"", &line
);
973 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
975 if (flcf
->catch_stderr
) {
976 pattern
= flcf
->catch_stderr
->elts
;
978 line
.data
[line
.len
- 1] = '\0';
980 for (i
= 0; i
< flcf
->catch_stderr
->nelts
; i
++) {
981 if (ngx_strstr(line
.data
, pattern
[i
].data
)) {
982 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
987 if (u
->buffer
.pos
== u
->buffer
.last
) {
989 if (!f
->fastcgi_stdout
) {
992 * the special handling the large number
993 * of the PHP warnings to not allocate memory
996 u
->buffer
.pos
= u
->buffer
.start
;
997 u
->buffer
.last
= u
->buffer
.start
;
1004 f
->state
= ngx_http_fastcgi_st_version
;
1011 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1013 f
->fastcgi_stdout
= 1;
1015 start
= u
->buffer
.pos
;
1017 if (u
->buffer
.pos
+ f
->length
< u
->buffer
.last
) {
1020 * set u->buffer.last to the end of the FastCGI record data
1021 * for ngx_http_parse_header_line()
1024 last
= u
->buffer
.last
;
1025 u
->buffer
.last
= u
->buffer
.pos
+ f
->length
;
1033 part_start
= u
->buffer
.pos
;
1035 rc
= ngx_http_parse_header_line(r
, &u
->buffer
);
1037 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1038 "http fastcgi parser: %d", rc
);
1040 if (rc
== NGX_AGAIN
) {
1046 /* a header line has been parsed successfully */
1048 h
= ngx_list_push(&u
->headers_in
.headers
);
1053 if (f
->split_parts
&& f
->split_parts
->nelts
) {
1055 part
= f
->split_parts
->elts
;
1056 size
= u
->buffer
.pos
- part_start
;
1058 for (i
= 0; i
< f
->split_parts
->nelts
; i
++) {
1059 size
+= part
[i
].end
- part
[i
].start
;
1062 p
= ngx_pnalloc(r
->pool
, size
);
1069 for (i
= 0; i
< f
->split_parts
->nelts
; i
++) {
1070 p
= ngx_cpymem(p
, part
[i
].start
,
1071 part
[i
].end
- part
[i
].start
);
1074 p
= ngx_cpymem(p
, part_start
, u
->buffer
.pos
- part_start
);
1078 f
->split_parts
->nelts
= 0;
1080 rc
= ngx_http_parse_header_line(r
, &buf
);
1082 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
1083 h
->key
.data
= r
->header_name_start
;
1084 h
->key
.data
[h
->key
.len
] = '\0';
1086 h
->value
.len
= r
->header_end
- r
->header_start
;
1087 h
->value
.data
= r
->header_start
;
1088 h
->value
.data
[h
->value
.len
] = '\0';
1090 h
->lowcase_key
= ngx_pnalloc(r
->pool
, h
->key
.len
);
1091 if (h
->lowcase_key
== NULL
) {
1097 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
1098 h
->value
.len
= r
->header_end
- r
->header_start
;
1100 h
->key
.data
= ngx_pnalloc(r
->pool
,
1101 h
->key
.len
+ 1 + h
->value
.len
+ 1
1103 if (h
->key
.data
== NULL
) {
1107 h
->value
.data
= h
->key
.data
+ h
->key
.len
+ 1;
1108 h
->lowcase_key
= h
->key
.data
+ h
->key
.len
+ 1
1111 ngx_cpystrn(h
->key
.data
, r
->header_name_start
,
1113 ngx_cpystrn(h
->value
.data
, r
->header_start
,
1117 h
->hash
= r
->header_hash
;
1119 if (h
->key
.len
== r
->lowcase_index
) {
1120 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
1123 ngx_strlow(h
->lowcase_key
, h
->key
.data
, h
->key
.len
);
1126 hh
= ngx_hash_find(&umcf
->headers_in_hash
, h
->hash
,
1127 h
->lowcase_key
, h
->key
.len
);
1129 if (hh
&& hh
->handler(r
, h
, hh
->offset
) != NGX_OK
) {
1133 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1134 "http fastcgi header: \"%V: %V\"",
1135 &h
->key
, &h
->value
);
1137 if (u
->buffer
.pos
< u
->buffer
.last
) {
1141 /* the end of the FastCGI record */
1146 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1148 /* a whole header has been parsed successfully */
1150 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1151 "http fastcgi header done");
1153 if (u
->headers_in
.status
) {
1154 status_line
= &u
->headers_in
.status
->value
;
1156 status
= ngx_atoi(status_line
->data
, 3);
1158 if (status
== NGX_ERROR
) {
1159 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1160 "upstream sent invalid status \"%V\"",
1162 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1165 u
->headers_in
.status_n
= status
;
1166 u
->headers_in
.status_line
= *status_line
;
1168 } else if (u
->headers_in
.location
) {
1169 u
->headers_in
.status_n
= 302;
1170 u
->headers_in
.status_line
.len
=
1171 sizeof("302 Moved Temporarily") - 1;
1172 u
->headers_in
.status_line
.data
=
1173 (u_char
*) "302 Moved Temporarily";
1176 u
->headers_in
.status_n
= 200;
1177 u
->headers_in
.status_line
.len
= sizeof("200 OK") - 1;
1178 u
->headers_in
.status_line
.data
= (u_char
*) "200 OK";
1181 u
->state
->status
= u
->headers_in
.status_n
;
1184 u
->cacheable
= ngx_http_upstream_is_cacheable(r
);
1191 /* there was error while a header line parsing */
1193 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1194 "upstream sent invalid header");
1196 return NGX_HTTP_UPSTREAM_INVALID_HEADER
;
1200 u
->buffer
.last
= last
;
1203 f
->length
-= u
->buffer
.pos
- start
;
1205 if (f
->length
== 0) {
1207 f
->state
= ngx_http_fastcgi_st_padding
;
1209 f
->state
= ngx_http_fastcgi_st_version
;
1213 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
1221 /* rc == NGX_AGAIN */
1223 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1224 "upstream split a header line in FastCGI records");
1226 if (f
->split_parts
== NULL
) {
1227 f
->split_parts
= ngx_array_create(r
->pool
, 1,
1228 sizeof(ngx_http_fastcgi_split_part_t
));
1229 if (f
->split_parts
== NULL
) {
1234 part
= ngx_array_push(f
->split_parts
);
1236 part
->start
= part_start
;
1237 part
->end
= u
->buffer
.last
;
1245 ngx_http_fastcgi_input_filter(ngx_event_pipe_t
*p
, ngx_buf_t
*buf
)
1248 ngx_buf_t
*b
, **prev
;
1251 ngx_http_request_t
*r
;
1252 ngx_http_fastcgi_ctx_t
*f
;
1254 if (buf
->pos
== buf
->last
) {
1259 f
= ngx_http_get_module_ctx(r
, ngx_http_fastcgi_module
);
1262 prev
= &buf
->shadow
;
1265 f
->last
= buf
->last
;
1268 if (f
->state
< ngx_http_fastcgi_st_data
) {
1270 rc
= ngx_http_fastcgi_process_record(r
, f
);
1272 if (rc
== NGX_AGAIN
) {
1276 if (rc
== NGX_ERROR
) {
1280 if (f
->type
== NGX_HTTP_FASTCGI_STDOUT
&& f
->length
== 0) {
1281 f
->state
= ngx_http_fastcgi_st_version
;
1282 p
->upstream_done
= 1;
1284 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, p
->log
, 0,
1285 "http fastcgi closed stdout");
1290 if (f
->type
== NGX_HTTP_FASTCGI_END_REQUEST
) {
1291 f
->state
= ngx_http_fastcgi_st_version
;
1292 p
->upstream_done
= 1;
1294 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, p
->log
, 0,
1295 "http fastcgi sent end request");
1302 if (f
->state
== ngx_http_fastcgi_st_padding
) {
1304 if (f
->pos
+ f
->padding
< f
->last
) {
1305 f
->state
= ngx_http_fastcgi_st_version
;
1306 f
->pos
+= f
->padding
;
1311 if (f
->pos
+ f
->padding
== f
->last
) {
1312 f
->state
= ngx_http_fastcgi_st_version
;
1317 f
->padding
-= f
->last
- f
->pos
;
1323 /* f->state == ngx_http_fastcgi_st_data */
1325 if (f
->type
== NGX_HTTP_FASTCGI_STDERR
) {
1329 if (f
->pos
== f
->last
) {
1335 if (f
->pos
+ f
->length
<= f
->last
) {
1336 line
.len
= f
->length
;
1337 f
->pos
+= f
->length
;
1339 f
->state
= ngx_http_fastcgi_st_padding
;
1342 line
.len
= f
->last
- f
->pos
;
1343 f
->length
-= f
->last
- f
->pos
;
1347 while (line
.data
[line
.len
- 1] == LF
1348 || line
.data
[line
.len
- 1] == CR
1349 || line
.data
[line
.len
- 1] == '.'
1350 || line
.data
[line
.len
- 1] == ' ')
1355 ngx_log_error(NGX_LOG_ERR
, p
->log
, 0,
1356 "FastCGI sent in stderr: \"%V\"", &line
);
1358 if (f
->pos
== f
->last
) {
1363 f
->state
= ngx_http_fastcgi_st_version
;
1370 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1372 if (f
->pos
== f
->last
) {
1378 p
->free
= p
->free
->next
;
1381 b
= ngx_alloc_buf(p
->pool
);
1387 ngx_memzero(b
, sizeof(ngx_buf_t
));
1390 b
->start
= buf
->start
;
1399 cl
= ngx_alloc_chain_link(p
->pool
);
1412 p
->last_in
= &cl
->next
;
1415 /* STUB */ b
->num
= buf
->num
;
1417 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, p
->log
, 0,
1418 "input buf #%d %p", b
->num
, b
->pos
);
1420 if (f
->pos
+ f
->length
< f
->last
) {
1423 f
->state
= ngx_http_fastcgi_st_padding
;
1425 f
->state
= ngx_http_fastcgi_st_version
;
1428 f
->pos
+= f
->length
;
1434 if (f
->pos
+ f
->length
== f
->last
) {
1437 f
->state
= ngx_http_fastcgi_st_padding
;
1439 f
->state
= ngx_http_fastcgi_st_version
;
1447 f
->length
-= f
->last
- f
->pos
;
1459 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, p
->log
, 0,
1460 "input buf %p %z", b
->pos
, b
->last
- b
->pos
);
1465 /* there is no data record in the buf, add it to free chain */
1467 if (ngx_event_pipe_add_free_buf(p
, buf
) != NGX_OK
) {
1476 ngx_http_fastcgi_process_record(ngx_http_request_t
*r
,
1477 ngx_http_fastcgi_ctx_t
*f
)
1480 ngx_http_fastcgi_state_e state
;
1484 for (p
= f
->pos
; p
< f
->last
; p
++) {
1488 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1489 "http fastcgi record byte: %02Xd", ch
);
1493 case ngx_http_fastcgi_st_version
:
1495 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1496 "upstream sent unsupported FastCGI "
1497 "protocol version: %d", ch
);
1500 state
= ngx_http_fastcgi_st_type
;
1503 case ngx_http_fastcgi_st_type
:
1505 case NGX_HTTP_FASTCGI_STDOUT
:
1506 case NGX_HTTP_FASTCGI_STDERR
:
1507 case NGX_HTTP_FASTCGI_END_REQUEST
:
1508 f
->type
= (ngx_uint_t
) ch
;
1511 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1512 "upstream sent invalid FastCGI "
1513 "record type: %d", ch
);
1517 state
= ngx_http_fastcgi_st_request_id_hi
;
1520 /* we support the single request per connection */
1522 case ngx_http_fastcgi_st_request_id_hi
:
1524 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1525 "upstream sent unexpected FastCGI "
1526 "request id high byte: %d", ch
);
1529 state
= ngx_http_fastcgi_st_request_id_lo
;
1532 case ngx_http_fastcgi_st_request_id_lo
:
1534 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1535 "upstream sent unexpected FastCGI "
1536 "request id low byte: %d", ch
);
1539 state
= ngx_http_fastcgi_st_content_length_hi
;
1542 case ngx_http_fastcgi_st_content_length_hi
:
1543 f
->length
= ch
<< 8;
1544 state
= ngx_http_fastcgi_st_content_length_lo
;
1547 case ngx_http_fastcgi_st_content_length_lo
:
1548 f
->length
|= (size_t) ch
;
1549 state
= ngx_http_fastcgi_st_padding_length
;
1552 case ngx_http_fastcgi_st_padding_length
:
1553 f
->padding
= (size_t) ch
;
1554 state
= ngx_http_fastcgi_st_reserved
;
1557 case ngx_http_fastcgi_st_reserved
:
1558 state
= ngx_http_fastcgi_st_data
;
1560 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1561 "http fastcgi record length: %z", f
->length
);
1568 /* suppress warning */
1569 case ngx_http_fastcgi_st_data
:
1570 case ngx_http_fastcgi_st_padding
:
1582 ngx_http_fastcgi_abort_request(ngx_http_request_t
*r
)
1584 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1585 "abort http fastcgi request");
1592 ngx_http_fastcgi_finalize_request(ngx_http_request_t
*r
, ngx_int_t rc
)
1594 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1595 "finalize http fastcgi request");
1602 ngx_http_fastcgi_add_variables(ngx_conf_t
*cf
)
1604 ngx_http_variable_t
*var
;
1606 var
= ngx_http_add_variable(cf
, &ngx_http_fastcgi_script_name
,
1607 NGX_HTTP_VAR_NOHASH
|NGX_HTTP_VAR_NOCACHEABLE
);
1612 var
->get_handler
= ngx_http_fastcgi_script_name_variable
;
1619 ngx_http_fastcgi_create_loc_conf(ngx_conf_t
*cf
)
1621 ngx_http_fastcgi_loc_conf_t
*conf
;
1623 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_fastcgi_loc_conf_t
));
1625 return NGX_CONF_ERROR
;
1629 * set by ngx_pcalloc():
1631 * conf->upstream.bufs.num = 0;
1632 * conf->upstream.next_upstream = 0;
1633 * conf->upstream.temp_path = NULL;
1634 * conf->upstream.hide_headers_hash = { NULL, 0 };
1635 * conf->upstream.schema = { 0, NULL };
1636 * conf->upstream.uri = { 0, NULL };
1637 * conf->upstream.location = NULL;
1638 * conf->upstream.store_lengths = NULL;
1639 * conf->upstream.store_values = NULL;
1641 * conf->index.len = 0;
1642 * conf->index.data = NULL;
1645 conf
->upstream
.store
= NGX_CONF_UNSET
;
1646 conf
->upstream
.store_access
= NGX_CONF_UNSET_UINT
;
1647 conf
->upstream
.buffering
= NGX_CONF_UNSET
;
1648 conf
->upstream
.ignore_client_abort
= NGX_CONF_UNSET
;
1650 conf
->upstream
.connect_timeout
= NGX_CONF_UNSET_MSEC
;
1651 conf
->upstream
.send_timeout
= NGX_CONF_UNSET_MSEC
;
1652 conf
->upstream
.read_timeout
= NGX_CONF_UNSET_MSEC
;
1654 conf
->upstream
.send_lowat
= NGX_CONF_UNSET_SIZE
;
1655 conf
->upstream
.buffer_size
= NGX_CONF_UNSET_SIZE
;
1657 conf
->upstream
.busy_buffers_size_conf
= NGX_CONF_UNSET_SIZE
;
1658 conf
->upstream
.max_temp_file_size_conf
= NGX_CONF_UNSET_SIZE
;
1659 conf
->upstream
.temp_file_write_size_conf
= NGX_CONF_UNSET_SIZE
;
1661 conf
->upstream
.pass_request_headers
= NGX_CONF_UNSET
;
1662 conf
->upstream
.pass_request_body
= NGX_CONF_UNSET
;
1664 conf
->upstream
.hide_headers
= NGX_CONF_UNSET_PTR
;
1665 conf
->upstream
.pass_headers
= NGX_CONF_UNSET_PTR
;
1667 conf
->upstream
.intercept_errors
= NGX_CONF_UNSET
;
1669 /* "fastcgi_cyclic_temp_file" is disabled */
1670 conf
->upstream
.cyclic_temp_file
= 0;
1672 conf
->catch_stderr
= NGX_CONF_UNSET_PTR
;
1679 ngx_http_fastcgi_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
1681 ngx_http_fastcgi_loc_conf_t
*prev
= parent
;
1682 ngx_http_fastcgi_loc_conf_t
*conf
= child
;
1689 ngx_hash_init_t hash
;
1690 ngx_http_script_compile_t sc
;
1691 ngx_http_script_copy_code_t
*copy
;
1693 if (conf
->upstream
.store
!= 0) {
1694 ngx_conf_merge_value(conf
->upstream
.store
,
1695 prev
->upstream
.store
, 0);
1697 if (conf
->upstream
.store_lengths
== NULL
) {
1698 conf
->upstream
.store_lengths
= prev
->upstream
.store_lengths
;
1699 conf
->upstream
.store_values
= prev
->upstream
.store_values
;
1703 ngx_conf_merge_uint_value(conf
->upstream
.store_access
,
1704 prev
->upstream
.store_access
, 0600);
1706 ngx_conf_merge_value(conf
->upstream
.buffering
,
1707 prev
->upstream
.buffering
, 1);
1709 ngx_conf_merge_value(conf
->upstream
.ignore_client_abort
,
1710 prev
->upstream
.ignore_client_abort
, 0);
1712 ngx_conf_merge_msec_value(conf
->upstream
.connect_timeout
,
1713 prev
->upstream
.connect_timeout
, 60000);
1715 ngx_conf_merge_msec_value(conf
->upstream
.send_timeout
,
1716 prev
->upstream
.send_timeout
, 60000);
1718 ngx_conf_merge_msec_value(conf
->upstream
.read_timeout
,
1719 prev
->upstream
.read_timeout
, 60000);
1721 ngx_conf_merge_size_value(conf
->upstream
.send_lowat
,
1722 prev
->upstream
.send_lowat
, 0);
1724 ngx_conf_merge_size_value(conf
->upstream
.buffer_size
,
1725 prev
->upstream
.buffer_size
,
1726 (size_t) ngx_pagesize
);
1729 ngx_conf_merge_bufs_value(conf
->upstream
.bufs
, prev
->upstream
.bufs
,
1732 if (conf
->upstream
.bufs
.num
< 2) {
1733 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1734 "there must be at least 2 \"fastcgi_buffers\"");
1735 return NGX_CONF_ERROR
;
1739 size
= conf
->upstream
.buffer_size
;
1740 if (size
< conf
->upstream
.bufs
.size
) {
1741 size
= conf
->upstream
.bufs
.size
;
1745 ngx_conf_merge_size_value(conf
->upstream
.busy_buffers_size_conf
,
1746 prev
->upstream
.busy_buffers_size_conf
,
1747 NGX_CONF_UNSET_SIZE
);
1749 if (conf
->upstream
.busy_buffers_size_conf
== NGX_CONF_UNSET_SIZE
) {
1750 conf
->upstream
.busy_buffers_size
= 2 * size
;
1752 conf
->upstream
.busy_buffers_size
=
1753 conf
->upstream
.busy_buffers_size_conf
;
1756 if (conf
->upstream
.busy_buffers_size
< size
) {
1757 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1758 "\"fastcgi_busy_buffers_size\" must be equal or bigger than "
1759 "maximum of the value of \"fastcgi_buffer_size\" and "
1760 "one of the \"fastcgi_buffers\"");
1762 return NGX_CONF_ERROR
;
1765 if (conf
->upstream
.busy_buffers_size
1766 > (conf
->upstream
.bufs
.num
- 1) * conf
->upstream
.bufs
.size
)
1768 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1769 "\"fastcgi_busy_buffers_size\" must be less than "
1770 "the size of all \"fastcgi_buffers\" minus one buffer");
1772 return NGX_CONF_ERROR
;
1776 ngx_conf_merge_size_value(conf
->upstream
.temp_file_write_size_conf
,
1777 prev
->upstream
.temp_file_write_size_conf
,
1778 NGX_CONF_UNSET_SIZE
);
1780 if (conf
->upstream
.temp_file_write_size_conf
== NGX_CONF_UNSET_SIZE
) {
1781 conf
->upstream
.temp_file_write_size
= 2 * size
;
1783 conf
->upstream
.temp_file_write_size
=
1784 conf
->upstream
.temp_file_write_size_conf
;
1787 if (conf
->upstream
.temp_file_write_size
< size
) {
1788 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1789 "\"fastcgi_temp_file_write_size\" must be equal or bigger than "
1790 "maximum of the value of \"fastcgi_buffer_size\" and "
1791 "one of the \"fastcgi_buffers\"");
1793 return NGX_CONF_ERROR
;
1797 ngx_conf_merge_size_value(conf
->upstream
.max_temp_file_size_conf
,
1798 prev
->upstream
.max_temp_file_size_conf
,
1799 NGX_CONF_UNSET_SIZE
);
1801 if (conf
->upstream
.max_temp_file_size_conf
== NGX_CONF_UNSET_SIZE
) {
1802 conf
->upstream
.max_temp_file_size
= 1024 * 1024 * 1024;
1804 conf
->upstream
.max_temp_file_size
=
1805 conf
->upstream
.max_temp_file_size_conf
;
1808 if (conf
->upstream
.max_temp_file_size
!= 0
1809 && conf
->upstream
.max_temp_file_size
< size
)
1811 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1812 "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
1813 "the temporary files usage or must be equal or bigger than "
1814 "maximum of the value of \"fastcgi_buffer_size\" and "
1815 "one of the \"fastcgi_buffers\"");
1817 return NGX_CONF_ERROR
;
1821 ngx_conf_merge_bitmask_value(conf
->upstream
.next_upstream
,
1822 prev
->upstream
.next_upstream
,
1823 (NGX_CONF_BITMASK_SET
1824 |NGX_HTTP_UPSTREAM_FT_ERROR
1825 |NGX_HTTP_UPSTREAM_FT_TIMEOUT
));
1827 if (conf
->upstream
.next_upstream
& NGX_HTTP_UPSTREAM_FT_OFF
) {
1828 conf
->upstream
.next_upstream
= NGX_CONF_BITMASK_SET
1829 |NGX_HTTP_UPSTREAM_FT_OFF
;
1832 ngx_conf_merge_path_value(conf
->upstream
.temp_path
,
1833 prev
->upstream
.temp_path
,
1834 NGX_HTTP_FASTCGI_TEMP_PATH
, 1, 2, 0,
1835 ngx_garbage_collector_temp_handler
, cf
);
1837 ngx_conf_merge_value(conf
->upstream
.pass_request_headers
,
1838 prev
->upstream
.pass_request_headers
, 1);
1839 ngx_conf_merge_value(conf
->upstream
.pass_request_body
,
1840 prev
->upstream
.pass_request_body
, 1);
1842 ngx_conf_merge_value(conf
->upstream
.intercept_errors
,
1843 prev
->upstream
.intercept_errors
, 0);
1845 ngx_conf_merge_ptr_value(conf
->catch_stderr
, prev
->catch_stderr
, NULL
);
1848 ngx_conf_merge_str_value(conf
->index
, prev
->index
, "");
1850 hash
.max_size
= 512;
1851 hash
.bucket_size
= ngx_align(64, ngx_cacheline_size
);
1852 hash
.name
= "fastcgi_hide_headers_hash";
1854 if (ngx_http_upstream_hide_headers_hash(cf
, &conf
->upstream
,
1856 ngx_http_fastcgi_hide_headers
,
1860 return NGX_CONF_ERROR
;
1863 if (conf
->upstream
.upstream
== NULL
) {
1864 conf
->upstream
.upstream
= prev
->upstream
.upstream
;
1865 conf
->upstream
.schema
= prev
->upstream
.schema
;
1868 if (conf
->params_source
== NULL
) {
1869 conf
->flushes
= prev
->flushes
;
1870 conf
->params_len
= prev
->params_len
;
1871 conf
->params
= prev
->params
;
1872 conf
->params_source
= prev
->params_source
;
1874 if (conf
->params_source
== NULL
) {
1879 conf
->params_len
= ngx_array_create(cf
->pool
, 64, 1);
1880 if (conf
->params_len
== NULL
) {
1881 return NGX_CONF_ERROR
;
1884 conf
->params
= ngx_array_create(cf
->pool
, 512, 1);
1885 if (conf
->params
== NULL
) {
1886 return NGX_CONF_ERROR
;
1889 src
= conf
->params_source
->elts
;
1890 for (i
= 0; i
< conf
->params_source
->nelts
; i
++) {
1892 if (ngx_http_script_variables_count(&src
[i
].value
) == 0) {
1893 copy
= ngx_array_push_n(conf
->params_len
,
1894 sizeof(ngx_http_script_copy_code_t
));
1896 return NGX_CONF_ERROR
;
1899 copy
->code
= (ngx_http_script_code_pt
)
1900 ngx_http_script_copy_len_code
;
1901 copy
->len
= src
[i
].key
.len
;
1904 copy
= ngx_array_push_n(conf
->params_len
,
1905 sizeof(ngx_http_script_copy_code_t
));
1907 return NGX_CONF_ERROR
;
1910 copy
->code
= (ngx_http_script_code_pt
)
1911 ngx_http_script_copy_len_code
;
1912 copy
->len
= src
[i
].value
.len
;
1915 size
= (sizeof(ngx_http_script_copy_code_t
)
1916 + src
[i
].key
.len
+ src
[i
].value
.len
1917 + sizeof(uintptr_t) - 1)
1918 & ~(sizeof(uintptr_t) - 1);
1920 copy
= ngx_array_push_n(conf
->params
, size
);
1922 return NGX_CONF_ERROR
;
1925 copy
->code
= ngx_http_script_copy_code
;
1926 copy
->len
= src
[i
].key
.len
+ src
[i
].value
.len
;
1928 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
1930 p
= ngx_cpymem(p
, src
[i
].key
.data
, src
[i
].key
.len
);
1931 ngx_memcpy(p
, src
[i
].value
.data
, src
[i
].value
.len
);
1934 copy
= ngx_array_push_n(conf
->params_len
,
1935 sizeof(ngx_http_script_copy_code_t
));
1937 return NGX_CONF_ERROR
;
1940 copy
->code
= (ngx_http_script_code_pt
)
1941 ngx_http_script_copy_len_code
;
1942 copy
->len
= src
[i
].key
.len
;
1945 size
= (sizeof(ngx_http_script_copy_code_t
)
1946 + src
[i
].key
.len
+ sizeof(uintptr_t) - 1)
1947 & ~(sizeof(uintptr_t) - 1);
1949 copy
= ngx_array_push_n(conf
->params
, size
);
1951 return NGX_CONF_ERROR
;
1954 copy
->code
= ngx_http_script_copy_code
;
1955 copy
->len
= src
[i
].key
.len
;
1957 p
= (u_char
*) copy
+ sizeof(ngx_http_script_copy_code_t
);
1958 ngx_memcpy(p
, src
[i
].key
.data
, src
[i
].key
.len
);
1961 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1964 sc
.source
= &src
[i
].value
;
1965 sc
.flushes
= &conf
->flushes
;
1966 sc
.lengths
= &conf
->params_len
;
1967 sc
.values
= &conf
->params
;
1969 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1970 return NGX_CONF_ERROR
;
1974 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
1976 return NGX_CONF_ERROR
;
1979 *code
= (uintptr_t) NULL
;
1982 code
= ngx_array_push_n(conf
->params
, sizeof(uintptr_t));
1984 return NGX_CONF_ERROR
;
1987 *code
= (uintptr_t) NULL
;
1990 code
= ngx_array_push_n(conf
->params_len
, sizeof(uintptr_t));
1992 return NGX_CONF_ERROR
;
1995 *code
= (uintptr_t) NULL
;
2002 ngx_http_fastcgi_script_name_variable(ngx_http_request_t
*r
,
2003 ngx_http_variable_value_t
*v
, uintptr_t data
)
2006 ngx_http_fastcgi_loc_conf_t
*flcf
;
2010 v
->no_cacheable
= 0;
2013 flcf
= ngx_http_get_module_loc_conf(r
, ngx_http_fastcgi_module
);
2015 if (r
->uri
.data
[r
->uri
.len
- 1] != '/') {
2016 v
->len
= r
->uri
.len
;
2017 v
->data
= r
->uri
.data
;
2021 v
->len
= r
->uri
.len
+ flcf
->index
.len
;
2023 v
->data
= ngx_pnalloc(r
->pool
, v
->len
);
2024 if (v
->data
== NULL
) {
2028 p
= ngx_copy(v
->data
, r
->uri
.data
, r
->uri
.len
);
2029 ngx_memcpy(p
, flcf
->index
.data
, flcf
->index
.len
);
2034 v
->no_cacheable
= 0;
2046 ngx_http_fastcgi_pass(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2048 ngx_http_fastcgi_loc_conf_t
*lcf
= conf
;
2052 ngx_http_core_loc_conf_t
*clcf
;
2054 if (lcf
->upstream
.schema
.len
) {
2055 return "is duplicate";
2058 value
= cf
->args
->elts
;
2060 ngx_memzero(&u
, sizeof(ngx_url_t
));
2065 lcf
->upstream
.upstream
= ngx_http_upstream_add(cf
, &u
, 0);
2066 if (lcf
->upstream
.upstream
== NULL
) {
2067 return NGX_CONF_ERROR
;
2070 lcf
->upstream
.schema
.len
= sizeof("fastcgi://") - 1;
2071 lcf
->upstream
.schema
.data
= (u_char
*) "fastcgi://";
2073 clcf
= ngx_http_conf_get_module_loc_conf(cf
, ngx_http_core_module
);
2075 clcf
->handler
= ngx_http_fastcgi_handler
;
2077 if (clcf
->name
.data
[clcf
->name
.len
- 1] == '/') {
2078 clcf
->auto_redirect
= 1;
2086 ngx_http_fastcgi_store(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
2088 ngx_http_fastcgi_loc_conf_t
*flcf
= conf
;
2091 ngx_http_script_compile_t sc
;
2093 if (flcf
->upstream
.store
!= NGX_CONF_UNSET
|| flcf
->upstream
.store_lengths
)
2095 return "is duplicate";
2098 value
= cf
->args
->elts
;
2100 if (ngx_strcmp(value
[1].data
, "on") == 0) {
2101 flcf
->upstream
.store
= 1;
2105 if (ngx_strcmp(value
[1].data
, "off") == 0) {
2106 flcf
->upstream
.store
= 0;
2110 /* include the terminating '\0' into script */
2113 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
2116 sc
.source
= &value
[1];
2117 sc
.lengths
= &flcf
->upstream
.store_lengths
;
2118 sc
.values
= &flcf
->upstream
.store_values
;
2119 sc
.variables
= ngx_http_script_variables_count(&value
[1]);
2120 sc
.complete_lengths
= 1;
2121 sc
.complete_values
= 1;
2123 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
2124 return NGX_CONF_ERROR
;
2132 ngx_http_fastcgi_lowat_check(ngx_conf_t
*cf
, void *post
, void *data
)
2137 if ((u_long
) *np
>= ngx_freebsd_net_inet_tcp_sendspace
) {
2138 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2139 "\"fastcgi_send_lowat\" must be less than %d "
2140 "(sysctl net.inet.tcp.sendspace)",
2141 ngx_freebsd_net_inet_tcp_sendspace
);
2143 return NGX_CONF_ERROR
;
2146 #elif !(NGX_HAVE_SO_SNDLOWAT)
2149 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
2150 "\"fastcgi_send_lowat\" is not supported, ignored");
2161 ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t
*cf
,
2162 ngx_command_t
*cmd
, void *conf
)
2164 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2165 "\"fastcgi_upstream_max_fails\" is not supported, "
2166 "use the \"max_fails\" parameter of the \"server\" directive ",
2167 "inside the \"upstream\" block");
2169 return NGX_CONF_ERROR
;
2174 ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t
*cf
,
2175 ngx_command_t
*cmd
, void *conf
)
2177 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2178 "\"fastcgi_upstream_fail_timeout\" is not supported, "
2179 "use the \"fail_timeout\" parameter of the \"server\" directive ",
2180 "inside the \"upstream\" block");
2182 return NGX_CONF_ERROR
;