~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_fastcgi_module.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_http.h>
 10 
 11 
 12 typedef struct {
 13     ngx_http_upstream_conf_t       upstream;
 14 
 15     ngx_str_t                      index;
 16 
 17     ngx_array_t                   *flushes;
 18     ngx_array_t                   *params_len;
 19     ngx_array_t                   *params;
 20     ngx_array_t                   *params_source;
 21     ngx_array_t                   *catch_stderr;
 22 
 23     ngx_array_t                   *fastcgi_lengths;
 24     ngx_array_t                   *fastcgi_values;
 25 
 26 #if (NGX_HTTP_CACHE)
 27     ngx_http_complex_value_t       cache_key;
 28 #endif
 29 
 30 #if (NGX_PCRE)
 31     ngx_regex_t                   *split_regex;
 32     ngx_str_t                      split_name;
 33 #endif
 34 } ngx_http_fastcgi_loc_conf_t;
 35 
 36 
 37 typedef enum {
 38     ngx_http_fastcgi_st_version = 0,
 39     ngx_http_fastcgi_st_type,
 40     ngx_http_fastcgi_st_request_id_hi,
 41     ngx_http_fastcgi_st_request_id_lo,
 42     ngx_http_fastcgi_st_content_length_hi,
 43     ngx_http_fastcgi_st_content_length_lo,
 44     ngx_http_fastcgi_st_padding_length,
 45     ngx_http_fastcgi_st_reserved,
 46     ngx_http_fastcgi_st_data,
 47     ngx_http_fastcgi_st_padding
 48 } ngx_http_fastcgi_state_e;
 49 
 50 
 51 typedef struct {
 52     u_char                        *start;
 53     u_char                        *end;
 54 } ngx_http_fastcgi_split_part_t;
 55 
 56 
 57 typedef struct {
 58     ngx_http_fastcgi_state_e       state;
 59     u_char                        *pos;
 60     u_char                        *last;
 61     ngx_uint_t                     type;
 62     size_t                         length;
 63     size_t                         padding;
 64 
 65     ngx_uint_t                     fastcgi_stdout; /* unsigned :1 */
 66 
 67     ngx_array_t                   *split_parts;
 68 
 69     ngx_str_t                      script_name;
 70     ngx_str_t                      path_info;
 71 } ngx_http_fastcgi_ctx_t;
 72 
 73 
 74 #define NGX_HTTP_FASTCGI_RESPONDER      1
 75 
 76 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST  1
 77 #define NGX_HTTP_FASTCGI_ABORT_REQUEST  2
 78 #define NGX_HTTP_FASTCGI_END_REQUEST    3
 79 #define NGX_HTTP_FASTCGI_PARAMS         4
 80 #define NGX_HTTP_FASTCGI_STDIN          5
 81 #define NGX_HTTP_FASTCGI_STDOUT         6
 82 #define NGX_HTTP_FASTCGI_STDERR         7
 83 #define NGX_HTTP_FASTCGI_DATA           8
 84 
 85 
 86 typedef struct {
 87     u_char  version;
 88     u_char  type;
 89     u_char  request_id_hi;
 90     u_char  request_id_lo;
 91     u_char  content_length_hi;
 92     u_char  content_length_lo;
 93     u_char  padding_length;
 94     u_char  reserved;
 95 } ngx_http_fastcgi_header_t;
 96 
 97 
 98 typedef struct {
 99     u_char  role_hi;
100     u_char  role_lo;
101     u_char  flags;
102     u_char  reserved[5];
103 } ngx_http_fastcgi_begin_request_t;
104 
105 
106 typedef struct {
107     u_char  version;
108     u_char  type;
109     u_char  request_id_hi;
110     u_char  request_id_lo;
111 } ngx_http_fastcgi_header_small_t;
112 
113 
114 typedef struct {
115     ngx_http_fastcgi_header_t         h0;
116     ngx_http_fastcgi_begin_request_t  br;
117     ngx_http_fastcgi_header_small_t   h1;
118 } ngx_http_fastcgi_request_start_t;
119 
120 
121 static ngx_int_t ngx_http_fastcgi_eval(ngx_http_request_t *r,
122     ngx_http_fastcgi_loc_conf_t *flcf);
123 #if (NGX_HTTP_CACHE)
124 static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r);
125 #endif
126 static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
127 static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
128 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
129 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
130     ngx_buf_t *buf);
131 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
132     ngx_http_fastcgi_ctx_t *f);
133 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
134 static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
135     ngx_int_t rc);
136 
137 static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf);
138 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
139 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
140     void *parent, void *child);
141 static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
142     ngx_http_variable_value_t *v, uintptr_t data);
143 static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r,
144     ngx_http_variable_value_t *v, uintptr_t data);
145 static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r,
146     ngx_http_fastcgi_loc_conf_t *flcf);
147 
148 static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
149     void *conf);
150 static char *ngx_http_fastcgi_split_path_info(ngx_conf_t *cf,
151     ngx_command_t *cmd, void *conf);
152 static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
153     void *conf);
154 #if (NGX_HTTP_CACHE)
155 static char *ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
156     void *conf);
157 static char *ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
158     void *conf);
159 #endif
160 
161 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
162     void *data);
163 
164 static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
165     ngx_command_t *cmd, void *conf);
166 static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
167     ngx_command_t *cmd, void *conf);
168 
169 
170 static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
171     { ngx_http_fastcgi_lowat_check };
172 
173 
174 static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
175     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
176     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
177     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
178     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
179     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
180     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
181     { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
182     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
183     { ngx_null_string, 0 }
184 };
185 
186 
187 static ngx_conf_bitmask_t  ngx_http_fastcgi_ignore_headers_masks[] = {
188     { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
189     { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
190     { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
191     { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
192     { ngx_null_string, 0 }
193 };
194 
195 
196 ngx_module_t  ngx_http_fastcgi_module;
197 
198 
199 static ngx_command_t  ngx_http_fastcgi_commands[] = {
200 
201     { ngx_string("fastcgi_pass"),
202       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
203       ngx_http_fastcgi_pass,
204       NGX_HTTP_LOC_CONF_OFFSET,
205       0,
206       NULL },
207 
208     { ngx_string("fastcgi_index"),
209       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
210       ngx_conf_set_str_slot,
211       NGX_HTTP_LOC_CONF_OFFSET,
212       offsetof(ngx_http_fastcgi_loc_conf_t, index),
213       NULL },
214 
215     { ngx_string("fastcgi_split_path_info"),
216       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
217       ngx_http_fastcgi_split_path_info,
218       NGX_HTTP_LOC_CONF_OFFSET,
219       0,
220       NULL },
221 
222     { ngx_string("fastcgi_store"),
223       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
224       ngx_http_fastcgi_store,
225       NGX_HTTP_LOC_CONF_OFFSET,
226       0,
227       NULL },
228 
229     { ngx_string("fastcgi_store_access"),
230       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
231       ngx_conf_set_access_slot,
232       NGX_HTTP_LOC_CONF_OFFSET,
233       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access),
234       NULL },
235 
236     { ngx_string("fastcgi_ignore_client_abort"),
237       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
238       ngx_conf_set_flag_slot,
239       NGX_HTTP_LOC_CONF_OFFSET,
240       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
241       NULL },
242 
243     { ngx_string("fastcgi_connect_timeout"),
244       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
245       ngx_conf_set_msec_slot,
246       NGX_HTTP_LOC_CONF_OFFSET,
247       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout),
248       NULL },
249 
250     { ngx_string("fastcgi_send_timeout"),
251       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
252       ngx_conf_set_msec_slot,
253       NGX_HTTP_LOC_CONF_OFFSET,
254       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_timeout),
255       NULL },
256 
257     { ngx_string("fastcgi_send_lowat"),
258       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
259       ngx_conf_set_size_slot,
260       NGX_HTTP_LOC_CONF_OFFSET,
261       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_lowat),
262       &ngx_http_fastcgi_lowat_post },
263 
264     { ngx_string("fastcgi_buffer_size"),
265       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
266       ngx_conf_set_size_slot,
267       NGX_HTTP_LOC_CONF_OFFSET,
268       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffer_size),
269       NULL },
270 
271     { ngx_string("fastcgi_pass_request_headers"),
272       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
273       ngx_conf_set_flag_slot,
274       NGX_HTTP_LOC_CONF_OFFSET,
275       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_request_headers),
276       NULL },
277 
278     { ngx_string("fastcgi_pass_request_body"),
279       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
280       ngx_conf_set_flag_slot,
281       NGX_HTTP_LOC_CONF_OFFSET,
282       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_request_body),
283       NULL },
284 
285     { ngx_string("fastcgi_intercept_errors"),
286       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
287       ngx_conf_set_flag_slot,
288       NGX_HTTP_LOC_CONF_OFFSET,
289       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.intercept_errors),
290       NULL },
291 
292     { ngx_string("fastcgi_read_timeout"),
293       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
294       ngx_conf_set_msec_slot,
295       NGX_HTTP_LOC_CONF_OFFSET,
296       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.read_timeout),
297       NULL },
298 
299     { ngx_string("fastcgi_buffers"),
300       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
301       ngx_conf_set_bufs_slot,
302       NGX_HTTP_LOC_CONF_OFFSET,
303       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.bufs),
304       NULL },
305 
306     { ngx_string("fastcgi_busy_buffers_size"),
307       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
308       ngx_conf_set_size_slot,
309       NGX_HTTP_LOC_CONF_OFFSET,
310       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.busy_buffers_size_conf),
311       NULL },
312 
313 #if (NGX_HTTP_CACHE)
314 
315     { ngx_string("fastcgi_cache"),
316       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
317       ngx_http_fastcgi_cache,
318       NGX_HTTP_LOC_CONF_OFFSET,
319       0,
320       NULL },
321 
322     { ngx_string("fastcgi_cache_key"),
323       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
324       ngx_http_fastcgi_cache_key,
325       NGX_HTTP_LOC_CONF_OFFSET,
326       0,
327       NULL },
328 
329     { ngx_string("fastcgi_cache_path"),
330       NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
331       ngx_http_file_cache_set_slot,
332       0,
333       0,
334       &ngx_http_fastcgi_module },
335 
336     { ngx_string("fastcgi_cache_valid"),
337       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
338       ngx_http_file_cache_valid_set_slot,
339       NGX_HTTP_LOC_CONF_OFFSET,
340       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid),
341       NULL },
342 
343     { ngx_string("fastcgi_cache_min_uses"),
344       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
345       ngx_conf_set_num_slot,
346       NGX_HTTP_LOC_CONF_OFFSET,
347       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_min_uses),
348       NULL },
349 
350     { ngx_string("fastcgi_cache_use_stale"),
351       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
352       ngx_conf_set_bitmask_slot,
353       NGX_HTTP_LOC_CONF_OFFSET,
354       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_use_stale),
355       &ngx_http_fastcgi_next_upstream_masks },
356 
357     { ngx_string("fastcgi_cache_methods"),
358       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
359       ngx_conf_set_bitmask_slot,
360       NGX_HTTP_LOC_CONF_OFFSET,
361       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_methods),
362       &ngx_http_upstream_cache_method_mask },
363 
364 #endif
365 
366     { ngx_string("fastcgi_temp_path"),
367       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
368       ngx_conf_set_path_slot,
369       NGX_HTTP_LOC_CONF_OFFSET,
370       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_path),
371       NULL },
372 
373     { ngx_string("fastcgi_max_temp_file_size"),
374       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
375       ngx_conf_set_size_slot,
376       NGX_HTTP_LOC_CONF_OFFSET,
377       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_temp_file_size_conf),
378       NULL },
379 
380     { ngx_string("fastcgi_temp_file_write_size"),
381       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
382       ngx_conf_set_size_slot,
383       NGX_HTTP_LOC_CONF_OFFSET,
384       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_file_write_size_conf),
385       NULL },
386 
387     { ngx_string("fastcgi_next_upstream"),
388       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
389       ngx_conf_set_bitmask_slot,
390       NGX_HTTP_LOC_CONF_OFFSET,
391       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
392       &ngx_http_fastcgi_next_upstream_masks },
393 
394     { ngx_string("fastcgi_upstream_max_fails"),
395       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
396       ngx_http_fastcgi_upstream_max_fails_unsupported,
397       0,
398       0,
399       NULL },
400 
401     { ngx_string("fastcgi_upstream_fail_timeout"),
402       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
403       ngx_http_fastcgi_upstream_fail_timeout_unsupported,
404       0,
405       0,
406       NULL },
407 
408     { ngx_string("fastcgi_param"),
409       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
410       ngx_conf_set_keyval_slot,
411       NGX_HTTP_LOC_CONF_OFFSET,
412       offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
413       NULL },
414 
415     { ngx_string("fastcgi_pass_header"),
416       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
417       ngx_conf_set_str_array_slot,
418       NGX_HTTP_LOC_CONF_OFFSET,
419       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
420       NULL },
421 
422     { ngx_string("fastcgi_hide_header"),
423       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
424       ngx_conf_set_str_array_slot,
425       NGX_HTTP_LOC_CONF_OFFSET,
426       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
427       NULL },
428 
429     { ngx_string("fastcgi_ignore_headers"),
430       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
431       ngx_conf_set_bitmask_slot,
432       NGX_HTTP_LOC_CONF_OFFSET,
433       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
434       &ngx_http_fastcgi_ignore_headers_masks },
435 
436     { ngx_string("fastcgi_catch_stderr"),
437       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
438       ngx_conf_set_str_array_slot,
439       NGX_HTTP_LOC_CONF_OFFSET,
440       offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr),
441       NULL },
442 
443       ngx_null_command
444 };
445 
446 
447 static ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
448     ngx_http_fastcgi_add_variables,        /* preconfiguration */
449     NULL,                                  /* postconfiguration */
450 
451     NULL,                                  /* create main configuration */
452     NULL,                                  /* init main configuration */
453 
454     NULL,                                  /* create server configuration */
455     NULL,                                  /* merge server configuration */
456 
457     ngx_http_fastcgi_create_loc_conf,      /* create location configuration */
458     ngx_http_fastcgi_merge_loc_conf        /* merge location configuration */
459 };
460 
461 
462 ngx_module_t  ngx_http_fastcgi_module = {
463     NGX_MODULE_V1,
464     &ngx_http_fastcgi_module_ctx,          /* module context */
465     ngx_http_fastcgi_commands,             /* module directives */
466     NGX_HTTP_MODULE,                       /* module type */
467     NULL,                                  /* init master */
468     NULL,                                  /* init module */
469     NULL,                                  /* init process */
470     NULL,                                  /* init thread */
471     NULL,                                  /* exit thread */
472     NULL,                                  /* exit process */
473     NULL,                                  /* exit master */
474     NGX_MODULE_V1_PADDING
475 };
476 
477 
478 static ngx_http_fastcgi_request_start_t  ngx_http_fastcgi_request_start = {
479     { 1,                                               /* version */
480       NGX_HTTP_FASTCGI_BEGIN_REQUEST,                  /* type */
481       0,                                               /* request_id_hi */
482       1,                                               /* request_id_lo */
483       0,                                               /* content_length_hi */
484       sizeof(ngx_http_fastcgi_begin_request_t),        /* content_length_lo */
485       0,                                               /* padding_length */
486       0 },                                             /* reserved */
487 
488     { 0,                                               /* role_hi */
489       NGX_HTTP_FASTCGI_RESPONDER,                      /* role_lo */
490       0, /* NGX_HTTP_FASTCGI_KEEP_CONN */              /* flags */
491       { 0, 0, 0, 0, 0 } },                             /* reserved[5] */
492 
493     { 1,                                               /* version */
494       NGX_HTTP_FASTCGI_PARAMS,                         /* type */
495       0,                                               /* request_id_hi */
496       1 },                                             /* request_id_lo */
497 
498 };
499 
500 
501 static ngx_http_variable_t  ngx_http_fastcgi_vars[] = {
502 
503     { ngx_string("fastcgi_script_name"), NULL,
504       ngx_http_fastcgi_script_name_variable, 0,
505       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
506 
507     { ngx_string("fastcgi_path_info"), NULL,
508       ngx_http_fastcgi_path_info_variable, 0,
509       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
510 
511     { ngx_null_string, NULL, NULL, 0, 0, 0 }
512 };
513 
514 
515 static ngx_str_t  ngx_http_fastcgi_hide_headers[] = {
516     ngx_string("Status"),
517     ngx_string("X-Accel-Expires"),
518     ngx_string("X-Accel-Redirect"),
519     ngx_string("X-Accel-Limit-Rate"),
520     ngx_string("X-Accel-Buffering"),
521     ngx_string("X-Accel-Charset"),
522     ngx_null_string
523 };
524 
525 
526 #if (NGX_HTTP_CACHE)
527 
528 static ngx_str_t  ngx_http_fastcgi_hide_cache_headers[] = {
529     ngx_string("Status"),
530     ngx_string("X-Accel-Expires"),
531     ngx_string("X-Accel-Redirect"),
532     ngx_string("X-Accel-Limit-Rate"),
533     ngx_string("X-Accel-Buffering"),
534     ngx_string("X-Accel-Charset"),
535     ngx_string("Set-Cookie"),
536     ngx_string("P3P"),
537     ngx_null_string
538 };
539 
540 #endif
541 
542 
543 static ngx_path_init_t  ngx_http_fastcgi_temp_path = {
544     ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
545 };
546 
547 
548 static ngx_int_t
549 ngx_http_fastcgi_handler(ngx_http_request_t *r)
550 {
551     ngx_int_t                     rc;
552     ngx_http_upstream_t          *u;
553     ngx_http_fastcgi_ctx_t       *f;
554     ngx_http_fastcgi_loc_conf_t  *flcf;
555 
556     if (r->subrequest_in_memory) {
557         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
558                       "ngx_http_fastcgi_module does not support "
559                       "subrequest in memory");
560         return NGX_HTTP_INTERNAL_SERVER_ERROR;
561     }
562 
563     if (ngx_http_upstream_create(r) != NGX_OK) {
564         return NGX_HTTP_INTERNAL_SERVER_ERROR;
565     }
566 
567     f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
568     if (f == NULL) {
569         return NGX_HTTP_INTERNAL_SERVER_ERROR;
570     }
571 
572     ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
573 
574     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
575 
576     if (flcf->fastcgi_lengths) {
577         if (ngx_http_fastcgi_eval(r, flcf) != NGX_OK) {
578             return NGX_HTTP_INTERNAL_SERVER_ERROR;
579         }
580     }
581 
582     u = r->upstream;
583 
584     u->schema.len = sizeof("fastcgi://") - 1;
585     u->schema.data = (u_char *) "fastcgi://";
586 
587     u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
588 
589     u->conf = &flcf->upstream;
590 
591 #if (NGX_HTTP_CACHE)
592     u->create_key = ngx_http_fastcgi_create_key;
593 #endif
594     u->create_request = ngx_http_fastcgi_create_request;
595     u->reinit_request = ngx_http_fastcgi_reinit_request;
596     u->process_header = ngx_http_fastcgi_process_header;
597     u->abort_request = ngx_http_fastcgi_abort_request;
598     u->finalize_request = ngx_http_fastcgi_finalize_request;
599 
600     u->buffering = 1;
601 
602     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
603     if (u->pipe == NULL) {
604         return NGX_HTTP_INTERNAL_SERVER_ERROR;
605     }
606 
607     u->pipe->input_filter = ngx_http_fastcgi_input_filter;
608     u->pipe->input_ctx = r;
609 
610     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
611 
612     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
613         return rc;
614     }
615 
616     return NGX_DONE;
617 }
618 
619 
620 static ngx_int_t
621 ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
622 {
623     ngx_url_t  u;
624 
625     ngx_memzero(&u, sizeof(ngx_url_t));
626 
627     if (ngx_http_script_run(r, &u.url, flcf->fastcgi_lengths->elts, 0,
628                             flcf->fastcgi_values->elts)
629         == NULL)
630     {
631         return NGX_ERROR;
632     }
633 
634     u.no_resolve = 1;
635 
636     if (ngx_parse_url(r->pool, &u) != NGX_OK) {
637          if (u.err) {
638             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
639                           "%s in upstream \"%V\"", u.err, &u.url);
640         }
641 
642         return NGX_ERROR;
643     }
644 
645     if (u.no_port) {
646         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
647                       "no port in upstream \"%V\"", &u.url);
648         return NGX_ERROR;
649     }
650 
651     r->upstream->resolved = ngx_pcalloc(r->pool,
652                                         sizeof(ngx_http_upstream_resolved_t));
653     if (r->upstream->resolved == NULL) {
654         return NGX_ERROR;
655     }
656 
657     if (u.addrs && u.addrs[0].sockaddr) {
658         r->upstream->resolved->sockaddr = u.addrs[0].sockaddr;
659         r->upstream->resolved->socklen = u.addrs[0].socklen;
660         r->upstream->resolved->naddrs = 1;
661         r->upstream->resolved->host = u.addrs[0].name;
662 
663     } else {
664         r->upstream->resolved->host = u.host;
665         r->upstream->resolved->port = u.port;
666     }
667 
668     return NGX_OK;
669 }
670 
671 
672 #if (NGX_HTTP_CACHE)
673 
674 static ngx_int_t
675 ngx_http_fastcgi_create_key(ngx_http_request_t *r)
676 {
677     ngx_str_t                    *key;
678     ngx_http_fastcgi_loc_conf_t  *flcf;
679 
680     key = ngx_array_push(&r->cache->keys);
681     if (key == NULL) {
682         return NGX_ERROR;
683     }
684 
685     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
686 
687     if (ngx_http_complex_value(r, &flcf->cache_key, key) != NGX_OK) {
688         return NGX_ERROR;
689     }
690 
691     return NGX_OK;
692 }
693 
694 #endif
695 
696 
697 static ngx_int_t
698 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
699 {
700     off_t                         file_pos;
701     u_char                        ch, *pos;
702     size_t                        size, len, key_len, val_len, padding;
703     ngx_uint_t                    i, n, next;
704     ngx_buf_t                    *b;
705     ngx_chain_t                  *cl, *body;
706     ngx_list_part_t              *part;
707     ngx_table_elt_t              *header;
708     ngx_http_script_code_pt       code;
709     ngx_http_script_engine_t      e, le;
710     ngx_http_fastcgi_header_t    *h;
711     ngx_http_fastcgi_loc_conf_t  *flcf;
712     ngx_http_script_len_code_pt   lcode;
713 
714     len = 0;
715 
716     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
717 
718     if (flcf->params_len) {
719         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
720 
721         ngx_http_script_flush_no_cacheable_variables(r, flcf->flushes);
722         le.flushed = 1;
723 
724         le.ip = flcf->params_len->elts;
725         le.request = r;
726 
727         while (*(uintptr_t *) le.ip) {
728 
729             lcode = *(ngx_http_script_len_code_pt *) le.ip;
730             key_len = lcode(&le);
731 
732             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
733                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
734             }
735             le.ip += sizeof(uintptr_t);
736 
737             len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
738         }
739     }
740 
741     if (flcf->upstream.pass_request_headers) {
742 
743         part = &r->headers_in.headers.part;
744         header = part->elts;
745 
746         for (i = 0; /* void */; i++) {
747 
748             if (i >= part->nelts) {
749                 if (part->next == NULL) {
750                     break;
751                 }
752 
753                 part = part->next;
754                 header = part->elts;
755                 i = 0;
756             }
757 
758             len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1)
759                 + ((header[i].value.len > 127) ? 4 : 1)
760                 + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len;
761         }
762     }
763 
764 
765     if (len > 65535) {
766         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
767                       "fastcgi request record is too big: %uz", len);
768         return NGX_ERROR;
769     }
770 
771 
772     padding = 8 - len % 8;
773     padding = (padding == 8) ? 0 : padding;
774 
775 
776     size = sizeof(ngx_http_fastcgi_header_t)
777            + sizeof(ngx_http_fastcgi_begin_request_t)
778 
779            + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
780            + len + padding
781            + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
782 
783            + sizeof(ngx_http_fastcgi_header_t); /* NGX_HTTP_FASTCGI_STDIN */
784 
785 
786     b = ngx_create_temp_buf(r->pool, size);
787     if (b == NULL) {
788         return NGX_ERROR;
789     }
790 
791     cl = ngx_alloc_chain_link(r->pool);
792     if (cl == NULL) {
793         return NGX_ERROR;
794     }
795 
796     cl->buf = b;
797 
798     ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start,
799                sizeof(ngx_http_fastcgi_request_start_t));
800 
801     h = (ngx_http_fastcgi_header_t *)
802              (b->pos + sizeof(ngx_http_fastcgi_header_t)
803                      + sizeof(ngx_http_fastcgi_begin_request_t));
804 
805     h->content_length_hi = (u_char) ((len >> 8) & 0xff);
806     h->content_length_lo = (u_char) (len & 0xff);
807     h->padding_length = (u_char) padding;
808     h->reserved = 0;
809 
810     b->last = b->pos + sizeof(ngx_http_fastcgi_header_t)
811                      + sizeof(ngx_http_fastcgi_begin_request_t)
812                      + sizeof(ngx_http_fastcgi_header_t);
813 
814 
815     if (flcf->params_len) {
816         ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
817 
818         e.ip = flcf->params->elts;
819         e.pos = b->last;
820         e.request = r;
821         e.flushed = 1;
822 
823         le.ip = flcf->params_len->elts;
824 
825         while (*(uintptr_t *) le.ip) {
826 
827             lcode = *(ngx_http_script_len_code_pt *) le.ip;
828             key_len = (u_char) lcode(&le);
829 
830             for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
831                 lcode = *(ngx_http_script_len_code_pt *) le.ip;
832             }
833             le.ip += sizeof(uintptr_t);
834 
835             *e.pos++ = (u_char) key_len;
836 
837             if (val_len > 127) {
838                 *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
839                 *e.pos++ = (u_char) ((val_len >> 16) & 0xff);
840                 *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
841                 *e.pos++ = (u_char) (val_len & 0xff);
842 
843             } else {
844                 *e.pos++ = (u_char) val_len;
845             }
846 
847             while (*(uintptr_t *) e.ip) {
848                 code = *(ngx_http_script_code_pt *) e.ip;
849                 code((ngx_http_script_engine_t *) &e);
850             }
851             e.ip += sizeof(uintptr_t);
852 
853             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
854                            "fastcgi param: \"%*s: %*s\"",
855                            key_len, e.pos - (key_len + val_len),
856                            val_len, e.pos - val_len);
857         }
858 
859         b->last = e.pos;
860     }
861 
862 
863     if (flcf->upstream.pass_request_headers) {
864 
865         part = &r->headers_in.headers.part;
866         header = part->elts;
867 
868         for (i = 0; /* void */; i++) {
869 
870             if (i >= part->nelts) {
871                 if (part->next == NULL) {
872                     break;
873                 }
874 
875                 part = part->next;
876                 header = part->elts;
877                 i = 0;
878             }
879 
880             len = sizeof("HTTP_") - 1 + header[i].key.len;
881             if (len > 127) {
882                 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
883                 *b->last++ = (u_char) ((len >> 16) & 0xff);
884                 *b->last++ = (u_char) ((len >> 8) & 0xff);
885                 *b->last++ = (u_char) (len & 0xff);
886 
887             } else {
888                 *b->last++ = (u_char) len;
889             }
890 
891             len = header[i].value.len;
892             if (len > 127) {
893                 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
894                 *b->last++ = (u_char) ((len >> 16) & 0xff);
895                 *b->last++ = (u_char) ((len >> 8) & 0xff);
896                 *b->last++ = (u_char) (len & 0xff);
897 
898             } else {
899                 *b->last++ = (u_char) len;
900             }
901 
902             b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
903 
904             for (n = 0; n < header[i].key.len; n++) {
905                 ch = header[i].key.data[n];
906 
907                 if (ch >= 'a' && ch <= 'z') {
908                     ch &= ~0x20;
909 
910                 } else if (ch == '-') {
911                     ch = '_';
912                 }
913 
914                 *b->last++ = ch;
915             }
916 
917             b->last = ngx_copy(b->last, header[i].value.data,
918                                header[i].value.len);
919         }
920     }
921 
922 
923     if (padding) {
924         ngx_memzero(b->last, padding);
925         b->last += padding;
926     }
927 
928 
929     h = (ngx_http_fastcgi_header_t *) b->last;
930     b->last += sizeof(ngx_http_fastcgi_header_t);
931 
932     h->version = 1;
933     h->type = NGX_HTTP_FASTCGI_PARAMS;
934     h->request_id_hi = 0;
935     h->request_id_lo = 1;
936     h->content_length_hi = 0;
937     h->content_length_lo = 0;
938     h->padding_length = 0;
939     h->reserved = 0;
940 
941     h = (ngx_http_fastcgi_header_t *) b->last;
942     b->last += sizeof(ngx_http_fastcgi_header_t);
943 
944     if (flcf->upstream.pass_request_body) {
945         body = r->upstream->request_bufs;
946         r->upstream->request_bufs = cl;
947 
948 #if (NGX_SUPPRESS_WARN)
949         file_pos = 0;
950         pos = NULL;
951 #endif
952 
953         while (body) {
954 
955             if (body->buf->in_file) {
956                 file_pos = body->buf->file_pos;
957 
958             } else {
959                 pos = body->buf->pos;
960             }
961 
962             next = 0;
963 
964             do {
965                 b = ngx_alloc_buf(r->pool);
966                 if (b == NULL) {
967                     return NGX_ERROR;
968                 }
969 
970                 ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
971 
972                 if (body->buf->in_file) {
973                     b->file_pos = file_pos;
974                     file_pos += 32 * 1024;
975 
976                     if (file_pos >= body->buf->file_last) {
977                         file_pos = body->buf->file_last;
978                         next = 1;
979                     }
980 
981                     b->file_last = file_pos;
982                     len = (ngx_uint_t) (file_pos - b->file_pos);
983 
984                 } else {
985                     b->pos = pos;
986                     pos += 32 * 1024;
987 
988                     if (pos >= body->buf->last) {
989                         pos = body->buf->last;
990                         next = 1;
991                     }
992 
993                     b->last = pos;
994                     len = (ngx_uint_t) (pos - b->pos);
995                 }
996 
997                 padding = 8 - len % 8;
998                 padding = (padding == 8) ? 0 : padding;
999 
1000                 h->version = 1;
1001                 h->type = NGX_HTTP_FASTCGI_STDIN;
1002                 h->request_id_hi = 0;
1003                 h->request_id_lo = 1;
1004                 h->content_length_hi = (u_char) ((len >> 8) & 0xff);
1005                 h->content_length_lo = (u_char) (len & 0xff);
1006                 h->padding_length = (u_char) padding;
1007                 h->reserved = 0;
1008 
1009                 cl->next = ngx_alloc_chain_link(r->pool);
1010                 if (cl->next == NULL) {
1011                     return NGX_ERROR;
1012                 }
1013 
1014                 cl = cl->next;
1015                 cl->buf = b;
1016 
1017                 b = ngx_create_temp_buf(r->pool,
1018                                         sizeof(ngx_http_fastcgi_header_t)
1019                                         + padding);
1020                 if (b == NULL) {
1021                     return NGX_ERROR;
1022                 }
1023 
1024                 if (padding) {
1025                     ngx_memzero(b->last, padding);
1026                     b->last += padding;
1027                 }
1028 
1029                 h = (ngx_http_fastcgi_header_t *) b->last;
1030                 b->last += sizeof(ngx_http_fastcgi_header_t);
1031 
1032                 cl->next = ngx_alloc_chain_link(r->pool);
1033                 if (cl->next == NULL) {
1034                     return NGX_ERROR;
1035                 }
1036 
1037                 cl = cl->next;
1038                 cl->buf = b;
1039 
1040             } while (!next);
1041 
1042             body = body->next;
1043         }
1044 
1045     } else {
1046         r->upstream->request_bufs = cl;
1047     }
1048 
1049     h->version = 1;
1050     h->type = NGX_HTTP_FASTCGI_STDIN;
1051     h->request_id_hi = 0;
1052     h->request_id_lo = 1;
1053     h->content_length_hi = 0;
1054     h->content_length_lo = 0;
1055     h->padding_length = 0;
1056     h->reserved = 0;
1057 
1058     cl->next = NULL;
1059 
1060     return NGX_OK;
1061 }
1062 
1063 
1064 static ngx_int_t
1065 ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
1066 {
1067     ngx_http_fastcgi_ctx_t  *f;
1068 
1069     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1070 
1071     if (f == NULL) {
1072         return NGX_OK;
1073     }
1074 
1075     f->state = ngx_http_fastcgi_st_version;
1076     f->fastcgi_stdout = 0;
1077 
1078     return NGX_OK;
1079 }
1080 
1081 
1082 static ngx_int_t
1083 ngx_http_fastcgi_process_header(ngx_http_request_t *r)
1084 {
1085     u_char                         *p, *msg, *start, *last,
1086                                    *part_start, *part_end;
1087     size_t                          size;
1088     ngx_str_t                      *status_line, *pattern;
1089     ngx_int_t                       rc, status;
1090     ngx_buf_t                       buf;
1091     ngx_uint_t                      i;
1092     ngx_table_elt_t                *h;
1093     ngx_http_upstream_t            *u;
1094     ngx_http_fastcgi_ctx_t         *f;
1095     ngx_http_upstream_header_t     *hh;
1096     ngx_http_fastcgi_loc_conf_t    *flcf;
1097     ngx_http_fastcgi_split_part_t  *part;
1098     ngx_http_upstream_main_conf_t  *umcf;
1099 
1100     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1101 
1102     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1103 
1104     u = r->upstream;
1105 
1106     for ( ;; ) {
1107 
1108         if (f->state < ngx_http_fastcgi_st_data) {
1109 
1110             f->pos = u->buffer.pos;
1111             f->last = u->buffer.last;
1112 
1113             rc = ngx_http_fastcgi_process_record(r, f);
1114 
1115             u->buffer.pos = f->pos;
1116             u->buffer.last = f->last;
1117 
1118             if (rc == NGX_AGAIN) {
1119                 return NGX_AGAIN;
1120             }
1121 
1122             if (rc == NGX_ERROR) {
1123                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1124             }
1125 
1126             if (f->type != NGX_HTTP_FASTCGI_STDOUT
1127                 && f->type != NGX_HTTP_FASTCGI_STDERR)
1128             {
1129                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1130                               "upstream sent unexpected FastCGI record: %d",
1131                               f->type);
1132 
1133                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1134             }
1135 
1136             if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1137                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1138                               "upstream closed prematurely FastCGI stdout");
1139 
1140                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1141             }
1142         }
1143 
1144         if (f->state == ngx_http_fastcgi_st_padding) {
1145 
1146             if (u->buffer.pos + f->padding < u->buffer.last) {
1147                 f->state = ngx_http_fastcgi_st_version;
1148                 u->buffer.pos += f->padding;
1149 
1150                 continue;
1151             }
1152 
1153             if (u->buffer.pos + f->padding == u->buffer.last) {
1154                 f->state = ngx_http_fastcgi_st_version;
1155                 u->buffer.pos = u->buffer.last;
1156 
1157                 return NGX_AGAIN;
1158             }
1159 
1160             f->padding -= u->buffer.last - u->buffer.pos;
1161             u->buffer.pos = u->buffer.last;
1162 
1163             return NGX_AGAIN;
1164         }
1165 
1166 
1167         /* f->state == ngx_http_fastcgi_st_data */
1168 
1169         if (f->type == NGX_HTTP_FASTCGI_STDERR) {
1170 
1171             if (f->length) {
1172                 msg = u->buffer.pos;
1173 
1174                 if (u->buffer.pos + f->length <= u->buffer.last) {
1175                     u->buffer.pos += f->length;
1176                     f->length = 0;
1177                     f->state = ngx_http_fastcgi_st_padding;
1178 
1179                 } else {
1180                     f->length -= u->buffer.last - u->buffer.pos;
1181                     u->buffer.pos = u->buffer.last;
1182                 }
1183 
1184                 for (p = u->buffer.pos - 1; msg < p; p--) {
1185                     if (*p != LF && *p != CR && *p != '.' && *p != ' ') {
1186                         break;
1187                     }
1188                 }
1189 
1190                 p++;
1191 
1192                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1193                               "FastCGI sent in stderr: \"%*s\"", p - msg, msg);
1194 
1195                 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
1196 
1197                 if (flcf->catch_stderr) {
1198                     pattern = flcf->catch_stderr->elts;
1199 
1200                     for (i = 0; i < flcf->catch_stderr->nelts; i++) {
1201                         if (ngx_strnstr(msg, (char *) pattern[i].data,
1202                                         p - msg)
1203                             != NULL)
1204                         {
1205                             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1206                         }
1207                     }
1208                 }
1209 
1210                 if (u->buffer.pos == u->buffer.last) {
1211 
1212                     if (!f->fastcgi_stdout) {
1213 
1214                         /*
1215                          * the special handling the large number
1216                          * of the PHP warnings to not allocate memory
1217                          */
1218 
1219                         u->buffer.pos = u->buffer.start;
1220                         u->buffer.last = u->buffer.start;
1221                     }
1222 
1223                     return NGX_AGAIN;
1224                 }
1225 
1226             } else {
1227                 f->state = ngx_http_fastcgi_st_version;
1228             }
1229 
1230             continue;
1231         }
1232 
1233 
1234         /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1235 
1236         f->fastcgi_stdout = 1;
1237 
1238         start = u->buffer.pos;
1239 
1240         if (u->buffer.pos + f->length < u->buffer.last) {
1241 
1242             /*
1243              * set u->buffer.last to the end of the FastCGI record data
1244              * for ngx_http_parse_header_line()
1245              */
1246 
1247             last = u->buffer.last;
1248             u->buffer.last = u->buffer.pos + f->length;
1249 
1250         } else {
1251             last = NULL;
1252         }
1253 
1254         for ( ;; ) {
1255 
1256             part_start = u->buffer.pos;
1257             part_end = u->buffer.last;
1258 
1259             rc = ngx_http_parse_header_line(r, &u->buffer, 1);
1260 
1261             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1262                            "http fastcgi parser: %d", rc);
1263 
1264             if (rc == NGX_AGAIN) {
1265                 break;
1266             }
1267 
1268             if (rc == NGX_OK) {
1269 
1270                 /* a header line has been parsed successfully */
1271 
1272                 h = ngx_list_push(&u->headers_in.headers);
1273                 if (h == NULL) {
1274                     return NGX_ERROR;
1275                 }
1276 
1277                 if (f->split_parts && f->split_parts->nelts) {
1278 
1279                     part = f->split_parts->elts;
1280                     size = u->buffer.pos - part_start;
1281 
1282                     for (i = 0; i < f->split_parts->nelts; i++) {
1283                         size += part[i].end - part[i].start;
1284                     }
1285 
1286                     p = ngx_pnalloc(r->pool, size);
1287                     if (p == NULL) {
1288                         return NGX_ERROR;
1289                     }
1290 
1291                     buf.pos = p;
1292 
1293                     for (i = 0; i < f->split_parts->nelts; i++) {
1294                         p = ngx_cpymem(p, part[i].start,
1295                                        part[i].end - part[i].start);
1296                     }
1297 
1298                     p = ngx_cpymem(p, part_start, u->buffer.pos - part_start);
1299 
1300                     buf.last = p;
1301 
1302                     f->split_parts->nelts = 0;
1303 
1304                     rc = ngx_http_parse_header_line(r, &buf, 1);
1305 
1306                     h->key.len = r->header_name_end - r->header_name_start;
1307                     h->key.data = r->header_name_start;
1308                     h->key.data[h->key.len] = '\0';
1309 
1310                     h->value.len = r->header_end - r->header_start;
1311                     h->value.data = r->header_start;
1312                     h->value.data[h->value.len] = '\0';
1313 
1314                     h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1315                     if (h->lowcase_key == NULL) {
1316                         return NGX_ERROR;
1317                     }
1318 
1319                 } else {
1320 
1321                     h->key.len = r->header_name_end - r->header_name_start;
1322                     h->value.len = r->header_end - r->header_start;
1323 
1324                     h->key.data = ngx_pnalloc(r->pool,
1325                                               h->key.len + 1 + h->value.len + 1
1326                                               + h->key.len);
1327                     if (h->key.data == NULL) {
1328                         return NGX_ERROR;
1329                     }
1330 
1331                     h->value.data = h->key.data + h->key.len + 1;
1332                     h->lowcase_key = h->key.data + h->key.len + 1
1333                                      + h->value.len + 1;
1334 
1335                     ngx_cpystrn(h->key.data, r->header_name_start,
1336                                 h->key.len + 1);
1337                     ngx_cpystrn(h->value.data, r->header_start,
1338                                 h->value.len + 1);
1339                 }
1340 
1341                 h->hash = r->header_hash;
1342 
1343                 if (h->key.len == r->lowcase_index) {
1344                     ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1345 
1346                 } else {
1347                     ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1348                 }
1349 
1350                 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
1351                                    h->lowcase_key, h->key.len);
1352 
1353                 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1354                     return NGX_ERROR;
1355                 }
1356 
1357                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1358                                "http fastcgi header: \"%V: %V\"",
1359                                &h->key, &h->value);
1360 
1361                 if (u->buffer.pos < u->buffer.last) {
1362                     continue;
1363                 }
1364 
1365                 /* the end of the FastCGI record */
1366 
1367                 break;
1368             }
1369 
1370             if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1371 
1372                 /* a whole header has been parsed successfully */
1373 
1374                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1375                                "http fastcgi header done");
1376 
1377                 if (u->headers_in.status) {
1378                     status_line = &u->headers_in.status->value;
1379 
1380                     status = ngx_atoi(status_line->data, 3);
1381 
1382                     if (status == NGX_ERROR) {
1383                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1384                                       "upstream sent invalid status \"%V\"",
1385                                       status_line);
1386                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1387                     }
1388 
1389                     u->headers_in.status_n = status;
1390                     u->headers_in.status_line = *status_line;
1391 
1392                 } else if (u->headers_in.location) {
1393                     u->headers_in.status_n = 302;
1394                     u->headers_in.status_line.len =
1395                                            sizeof("302 Moved Temporarily") - 1;
1396                     u->headers_in.status_line.data =
1397                                            (u_char *) "302 Moved Temporarily";
1398 
1399                 } else {
1400                     u->headers_in.status_n = 200;
1401                     u->headers_in.status_line.len = sizeof("200 OK") - 1;
1402                     u->headers_in.status_line.data = (u_char *) "200 OK";
1403                 }
1404 
1405                 if (u->state) {
1406                     u->state->status = u->headers_in.status_n;
1407                 }
1408 
1409                 break;
1410             }
1411 
1412             /* there was error while a header line parsing */
1413 
1414             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1415                           "upstream sent invalid header");
1416 
1417             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1418         }
1419 
1420         if (last) {
1421             u->buffer.last = last;
1422         }
1423 
1424         f->length -= u->buffer.pos - start;
1425 
1426         if (f->length == 0) {
1427             if (f->padding) {
1428                 f->state = ngx_http_fastcgi_st_padding;
1429             } else {
1430                 f->state = ngx_http_fastcgi_st_version;
1431             }
1432         }
1433 
1434         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1435             return NGX_OK;
1436         }
1437 
1438         if (rc == NGX_OK) {
1439             continue;
1440         }
1441 
1442         /* rc == NGX_AGAIN */
1443 
1444         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1445                        "upstream split a header line in FastCGI records");
1446 
1447         if (f->split_parts == NULL) {
1448             f->split_parts = ngx_array_create(r->pool, 1,
1449                                         sizeof(ngx_http_fastcgi_split_part_t));
1450             if (f->split_parts == NULL) {
1451                 return NGX_ERROR;
1452             }
1453         }
1454 
1455         part = ngx_array_push(f->split_parts);
1456 
1457         part->start = part_start;
1458         part->end = part_end;
1459 
1460         if (u->buffer.pos < u->buffer.last) {
1461             continue;
1462         }
1463 
1464         return NGX_AGAIN;
1465     }
1466 }
1467 
1468 
1469 static ngx_int_t
1470 ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1471 {
1472     u_char                  *m, *msg;
1473     ngx_int_t                rc;
1474     ngx_buf_t               *b, **prev;
1475     ngx_chain_t             *cl;
1476     ngx_http_request_t      *r;
1477     ngx_http_fastcgi_ctx_t  *f;
1478 
1479     if (buf->pos == buf->last) {
1480         return NGX_OK;
1481     }
1482 
1483     r = p->input_ctx;
1484     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1485 
1486     b = NULL;
1487     prev = &buf->shadow;
1488 
1489     f->pos = buf->pos;
1490     f->last = buf->last;
1491 
1492     for ( ;; ) {
1493         if (f->state < ngx_http_fastcgi_st_data) {
1494 
1495             rc = ngx_http_fastcgi_process_record(r, f);
1496 
1497             if (rc == NGX_AGAIN) {
1498                 break;
1499             }
1500 
1501             if (rc == NGX_ERROR) {
1502                 return NGX_ERROR;
1503             }
1504 
1505             if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1506                 f->state = ngx_http_fastcgi_st_version;
1507                 p->upstream_done = 1;
1508 
1509                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1510                                "http fastcgi closed stdout");
1511 
1512                 continue;
1513             }
1514 
1515             if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1516                 f->state = ngx_http_fastcgi_st_version;
1517                 p->upstream_done = 1;
1518 
1519                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1520                                "http fastcgi sent end request");
1521 
1522                 break;
1523             }
1524         }
1525 
1526 
1527         if (f->state == ngx_http_fastcgi_st_padding) {
1528 
1529             if (f->pos + f->padding < f->last) {
1530                 f->state = ngx_http_fastcgi_st_version;
1531                 f->pos += f->padding;
1532 
1533                 continue;
1534             }
1535 
1536             if (f->pos + f->padding == f->last) {
1537                 f->state = ngx_http_fastcgi_st_version;
1538 
1539                 break;
1540             }
1541 
1542             f->padding -= f->last - f->pos;
1543 
1544             break;
1545         }
1546 
1547 
1548         /* f->state == ngx_http_fastcgi_st_data */
1549 
1550         if (f->type == NGX_HTTP_FASTCGI_STDERR) {
1551 
1552             if (f->length) {
1553 
1554                 if (f->pos == f->last) {
1555                     break;
1556                 }
1557 
1558                 msg = f->pos;
1559 
1560                 if (f->pos + f->length <= f->last) {
1561                     f->pos += f->length;
1562                     f->length = 0;
1563                     f->state = ngx_http_fastcgi_st_padding;
1564 
1565                 } else {
1566                     f->length -= f->last - f->pos;
1567                     f->pos = f->last;
1568                 }
1569 
1570                 for (m = f->pos - 1; msg < m; m--) {
1571                     if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
1572                         break;
1573                     }
1574                 }
1575 
1576                 ngx_log_error(NGX_LOG_ERR, p->log, 0,
1577                               "FastCGI sent in stderr: \"%*s\"",
1578                               m + 1 - msg, msg);
1579 
1580                 if (f->pos == f->last) {
1581                     break;
1582                 }
1583 
1584             } else {
1585                 f->state = ngx_http_fastcgi_st_version;
1586             }
1587 
1588             continue;
1589         }
1590 
1591 
1592         /* f->type == NGX_HTTP_FASTCGI_STDOUT */
1593 
1594         if (f->pos == f->last) {
1595             break;
1596         }
1597 
1598         if (p->free) {
1599             b = p->free->buf;
1600             p->free = p->free->next;
1601 
1602         } else {
1603             b = ngx_alloc_buf(p->pool);
1604             if (b == NULL) {
1605                 return NGX_ERROR;
1606             }
1607         }
1608 
1609         ngx_memzero(b, sizeof(ngx_buf_t));
1610 
1611         b->pos = f->pos;
1612         b->start = buf->start;
1613         b->end = buf->end;
1614         b->tag = p->tag;
1615         b->temporary = 1;
1616         b->recycled = 1;
1617 
1618         *prev = b;
1619         prev = &b->shadow;
1620 
1621         cl = ngx_alloc_chain_link(p->pool);
1622         if (cl == NULL) {
1623             return NGX_ERROR;
1624         }
1625 
1626         cl->buf = b;
1627         cl->next = NULL;
1628 
1629         if (p->in) {
1630             *p->last_in = cl;
1631         } else {
1632             p->in = cl;
1633         }
1634         p->last_in = &cl->next;
1635 
1636 
1637         /* STUB */ b->num = buf->num;
1638 
1639         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1640                        "input buf #%d %p", b->num, b->pos);
1641 
1642         if (f->pos + f->length < f->last) {
1643 
1644             if (f->padding) {
1645                 f->state = ngx_http_fastcgi_st_padding;
1646             } else {
1647                 f->state = ngx_http_fastcgi_st_version;
1648             }
1649 
1650             f->pos += f->length;
1651             b->last = f->pos;
1652 
1653             continue;
1654         }
1655 
1656         if (f->pos + f->length == f->last) {
1657 
1658             if (f->padding) {
1659                 f->state = ngx_http_fastcgi_st_padding;
1660             } else {
1661                 f->state = ngx_http_fastcgi_st_version;
1662             }
1663 
1664             b->last = f->last;
1665 
1666             break;
1667         }
1668 
1669         f->length -= f->last - f->pos;
1670 
1671         b->last = f->last;
1672 
1673         break;
1674 
1675     }
1676 
1677     if (b) {
1678         b->shadow = buf;
1679         b->last_shadow = 1;
1680 
1681         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1682                        "input buf %p %z", b->pos, b->last - b->pos);
1683 
1684         return NGX_OK;
1685     }
1686 
1687     /* there is no data record in the buf, add it to free chain */
1688 
1689     if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
1690         return NGX_ERROR;
1691     }
1692 
1693     return NGX_OK;
1694 }
1695 
1696 
1697 static ngx_int_t
1698 ngx_http_fastcgi_process_record(ngx_http_request_t *r,
1699     ngx_http_fastcgi_ctx_t *f)
1700 {
1701     u_char                     ch, *p;
1702     ngx_http_fastcgi_state_e   state;
1703 
1704     state = f->state;
1705 
1706     for (p = f->pos; p < f->last; p++) {
1707 
1708         ch = *p;
1709 
1710         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1711                        "http fastcgi record byte: %02Xd", ch);
1712 
1713         switch (state) {
1714 
1715         case ngx_http_fastcgi_st_version:
1716             if (ch != 1) {
1717                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1718                               "upstream sent unsupported FastCGI "
1719                               "protocol version: %d", ch);
1720                 return NGX_ERROR;
1721             }
1722             state = ngx_http_fastcgi_st_type;
1723             break;
1724 
1725         case ngx_http_fastcgi_st_type:
1726             switch (ch) {
1727             case NGX_HTTP_FASTCGI_STDOUT:
1728             case NGX_HTTP_FASTCGI_STDERR:
1729             case NGX_HTTP_FASTCGI_END_REQUEST:
1730                  f->type = (ngx_uint_t) ch;
1731                  break;
1732             default:
1733                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1734                               "upstream sent invalid FastCGI "
1735                               "record type: %d", ch);
1736                 return NGX_ERROR;
1737 
1738             }
1739             state = ngx_http_fastcgi_st_request_id_hi;
1740             break;
1741 
1742         /* we support the single request per connection */
1743 
1744         case ngx_http_fastcgi_st_request_id_hi:
1745             if (ch != 0) {
1746                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1747                               "upstream sent unexpected FastCGI "
1748                               "request id high byte: %d", ch);
1749                 return NGX_ERROR;
1750             }
1751             state = ngx_http_fastcgi_st_request_id_lo;
1752             break;
1753 
1754         case ngx_http_fastcgi_st_request_id_lo:
1755             if (ch != 1) {
1756                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1757                               "upstream sent unexpected FastCGI "
1758                               "request id low byte: %d", ch);
1759                 return NGX_ERROR;
1760             }
1761             state = ngx_http_fastcgi_st_content_length_hi;
1762             break;
1763 
1764         case ngx_http_fastcgi_st_content_length_hi:
1765             f->length = ch << 8;
1766             state = ngx_http_fastcgi_st_content_length_lo;
1767             break;
1768 
1769         case ngx_http_fastcgi_st_content_length_lo:
1770             f->length |= (size_t) ch;
1771             state = ngx_http_fastcgi_st_padding_length;
1772             break;
1773 
1774         case ngx_http_fastcgi_st_padding_length:
1775             f->padding = (size_t) ch;
1776             state = ngx_http_fastcgi_st_reserved;
1777             break;
1778 
1779         case ngx_http_fastcgi_st_reserved:
1780             state = ngx_http_fastcgi_st_data;
1781 
1782             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1783                            "http fastcgi record length: %z", f->length);
1784 
1785             f->pos = p + 1;
1786             f->state = state;
1787 
1788             return NGX_OK;
1789 
1790         /* suppress warning */
1791         case ngx_http_fastcgi_st_data:
1792         case ngx_http_fastcgi_st_padding:
1793             break;
1794         }
1795     }
1796 
1797     f->state = state;
1798 
1799     return NGX_AGAIN;
1800 }
1801 
1802 
1803 static void
1804 ngx_http_fastcgi_abort_request(ngx_http_request_t *r)
1805 {
1806     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1807                    "abort http fastcgi request");
1808 
1809     return;
1810 }
1811 
1812 
1813 static void
1814 ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1815 {
1816     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1817                    "finalize http fastcgi request");
1818 
1819     return;
1820 }
1821 
1822 
1823 static ngx_int_t
1824 ngx_http_fastcgi_add_variables(ngx_conf_t *cf)
1825 {
1826    ngx_http_variable_t  *var, *v;
1827 
1828     for (v = ngx_http_fastcgi_vars; v->name.len; v++) {
1829         var = ngx_http_add_variable(cf, &v->name, v->flags);
1830         if (var == NULL) {
1831             return NGX_ERROR;
1832         }
1833 
1834         var->get_handler = v->get_handler;
1835         var->data = v->data;
1836     }
1837 
1838     return NGX_OK;
1839 }
1840 
1841 
1842 static void *
1843 ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
1844 {
1845     ngx_http_fastcgi_loc_conf_t  *conf;
1846 
1847     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_loc_conf_t));
1848     if (conf == NULL) {
1849         return NULL;
1850     }
1851 
1852     /*
1853      * set by ngx_pcalloc():
1854      *
1855      *     conf->upstream.bufs.num = 0;
1856      *     conf->upstream.ignore_headers = 0;
1857      *     conf->upstream.next_upstream = 0;
1858      *     conf->upstream.cache_use_stale = 0;
1859      *     conf->upstream.cache_methods = 0;
1860      *     conf->upstream.temp_path = NULL;
1861      *     conf->upstream.hide_headers_hash = { NULL, 0 };
1862      *     conf->upstream.uri = { 0, NULL };
1863      *     conf->upstream.location = NULL;
1864      *     conf->upstream.store_lengths = NULL;
1865      *     conf->upstream.store_values = NULL;
1866      *
1867      *     conf->index.len = 0;
1868      *     conf->index.data = NULL;
1869      */
1870 
1871     conf->upstream.store = NGX_CONF_UNSET;
1872     conf->upstream.store_access = NGX_CONF_UNSET_UINT;
1873     conf->upstream.buffering = NGX_CONF_UNSET;
1874     conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
1875 
1876     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
1877     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
1878     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
1879 
1880     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
1881     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
1882 
1883     conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
1884     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
1885     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
1886 
1887     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
1888     conf->upstream.pass_request_body = NGX_CONF_UNSET;
1889 
1890 #if (NGX_HTTP_CACHE)
1891     conf->upstream.cache = NGX_CONF_UNSET_PTR;
1892     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
1893     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
1894 #endif
1895 
1896     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
1897     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
1898 
1899     conf->upstream.intercept_errors = NGX_CONF_UNSET;
1900 
1901     /* "fastcgi_cyclic_temp_file" is disabled */
1902     conf->upstream.cyclic_temp_file = 0;
1903 
1904     conf->catch_stderr = NGX_CONF_UNSET_PTR;
1905 
1906     return conf;
1907 }
1908 
1909 
1910 static char *
1911 ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1912 {
1913     ngx_http_fastcgi_loc_conf_t *prev = parent;
1914     ngx_http_fastcgi_loc_conf_t *conf = child;
1915 
1916     u_char                       *p;
1917     size_t                        size;
1918     uintptr_t                    *code;
1919     ngx_str_t                    *h;
1920     ngx_uint_t                    i;
1921     ngx_keyval_t                 *src;
1922     ngx_hash_init_t               hash;
1923     ngx_http_script_compile_t     sc;
1924     ngx_http_script_copy_code_t  *copy;
1925 
1926     if (conf->upstream.store != 0) {
1927         ngx_conf_merge_value(conf->upstream.store,
1928                               prev->upstream.store, 0);
1929 
1930         if (conf->upstream.store_lengths == NULL) {
1931             conf->upstream.store_lengths = prev->upstream.store_lengths;
1932             conf->upstream.store_values = prev->upstream.store_values;
1933         }
1934     }
1935 
1936     ngx_conf_merge_uint_value(conf->upstream.store_access,
1937                               prev->upstream.store_access, 0600);
1938 
1939     ngx_conf_merge_value(conf->upstream.buffering,
1940                               prev->upstream.buffering, 1);
1941 
1942     ngx_conf_merge_value(conf->upstream.ignore_client_abort,
1943                               prev->upstream.ignore_client_abort, 0);
1944 
1945     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
1946                               prev->upstream.connect_timeout, 60000);
1947 
1948     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
1949                               prev->upstream.send_timeout, 60000);
1950 
1951     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
1952                               prev->upstream.read_timeout, 60000);
1953 
1954     ngx_conf_merge_size_value(conf->upstream.send_lowat,
1955                               prev->upstream.send_lowat, 0);
1956 
1957     ngx_conf_merge_size_value(conf->upstream.buffer_size,
1958                               prev->upstream.buffer_size,
1959                               (size_t) ngx_pagesize);
1960 
1961 
1962     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
1963                               8, ngx_pagesize);
1964 
1965     if (conf->upstream.bufs.num < 2) {
1966         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1967                            "there must be at least 2 \"fastcgi_buffers\"");
1968         return NGX_CONF_ERROR;
1969     }
1970 
1971 
1972     size = conf->upstream.buffer_size;
1973     if (size < conf->upstream.bufs.size) {
1974         size = conf->upstream.bufs.size;
1975     }
1976 
1977 
1978     ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
1979                               prev->upstream.busy_buffers_size_conf,
1980                               NGX_CONF_UNSET_SIZE);
1981 
1982     if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
1983         conf->upstream.busy_buffers_size = 2 * size;
1984     } else {
1985         conf->upstream.busy_buffers_size =
1986                                          conf->upstream.busy_buffers_size_conf;
1987     }
1988 
1989     if (conf->upstream.busy_buffers_size < size) {
1990         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1991              "\"fastcgi_busy_buffers_size\" must be equal or bigger than "
1992              "maximum of the value of \"fastcgi_buffer_size\" and "
1993              "one of the \"fastcgi_buffers\"");
1994 
1995         return NGX_CONF_ERROR;
1996     }
1997 
1998     if (conf->upstream.busy_buffers_size
1999         > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
2000     {
2001         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2002              "\"fastcgi_busy_buffers_size\" must be less than "
2003              "the size of all \"fastcgi_buffers\" minus one buffer");
2004 
2005         return NGX_CONF_ERROR;
2006     }
2007 
2008 
2009     ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
2010                               prev->upstream.temp_file_write_size_conf,
2011                               NGX_CONF_UNSET_SIZE);
2012 
2013     if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
2014         conf->upstream.temp_file_write_size = 2 * size;
2015     } else {
2016         conf->upstream.temp_file_write_size =
2017                                       conf->upstream.temp_file_write_size_conf;
2018     }
2019 
2020     if (conf->upstream.temp_file_write_size < size) {
2021         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2022              "\"fastcgi_temp_file_write_size\" must be equal or bigger than "
2023              "maximum of the value of \"fastcgi_buffer_size\" and "
2024              "one of the \"fastcgi_buffers\"");
2025 
2026         return NGX_CONF_ERROR;
2027     }
2028 
2029 
2030     ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
2031                               prev->upstream.max_temp_file_size_conf,
2032                               NGX_CONF_UNSET_SIZE);
2033 
2034     if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
2035         conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
2036     } else {
2037         conf->upstream.max_temp_file_size =
2038                                         conf->upstream.max_temp_file_size_conf;
2039     }
2040 
2041     if (conf->upstream.max_temp_file_size != 0
2042         && conf->upstream.max_temp_file_size < size)
2043     {
2044         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2045              "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
2046              "the temporary files usage or must be equal or bigger than "
2047              "maximum of the value of \"fastcgi_buffer_size\" and "
2048              "one of the \"fastcgi_buffers\"");
2049 
2050         return NGX_CONF_ERROR;
2051     }
2052 
2053 
2054     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
2055                               prev->upstream.ignore_headers,
2056                               NGX_CONF_BITMASK_SET);
2057 
2058 
2059     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
2060                               prev->upstream.next_upstream,
2061                               (NGX_CONF_BITMASK_SET
2062                                |NGX_HTTP_UPSTREAM_FT_ERROR
2063                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
2064 
2065     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
2066         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
2067                                        |NGX_HTTP_UPSTREAM_FT_OFF;
2068     }
2069 
2070     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
2071                               prev->upstream.temp_path,
2072                               &ngx_http_fastcgi_temp_path)
2073         != NGX_OK)
2074     {
2075         return NGX_CONF_ERROR;
2076     }
2077 
2078 #if (NGX_HTTP_CACHE)
2079 
2080     ngx_conf_merge_ptr_value(conf->upstream.cache,
2081                               prev->upstream.cache, NULL);
2082 
2083     if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
2084         ngx_shm_zone_t  *shm_zone;
2085 
2086         shm_zone = conf->upstream.cache;
2087 
2088         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2089                            "\"fastcgi_cache\" zone \"%V\" is unknown",
2090                            &shm_zone->shm.name);
2091 
2092         return NGX_CONF_ERROR;
2093     }
2094 
2095     ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
2096                               prev->upstream.cache_min_uses, 1);
2097 
2098     ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
2099                               prev->upstream.cache_use_stale,
2100                               (NGX_CONF_BITMASK_SET
2101                                |NGX_HTTP_UPSTREAM_FT_OFF));
2102 
2103     if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
2104         conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
2105                                          |NGX_HTTP_UPSTREAM_FT_OFF;
2106     }
2107 
2108     if (conf->upstream.cache_methods == 0) {
2109         conf->upstream.cache_methods = prev->upstream.cache_methods;
2110     }
2111 
2112     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
2113 
2114     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
2115                              prev->upstream.cache_valid, NULL);
2116 
2117     if (conf->cache_key.value.data == NULL) {
2118         conf->cache_key = prev->cache_key;
2119     }
2120 
2121 #endif
2122 
2123     ngx_conf_merge_value(conf->upstream.pass_request_headers,
2124                               prev->upstream.pass_request_headers, 1);
2125     ngx_conf_merge_value(conf->upstream.pass_request_body,
2126                               prev->upstream.pass_request_body, 1);
2127 
2128     ngx_conf_merge_value(conf->upstream.intercept_errors,
2129                               prev->upstream.intercept_errors, 0);
2130 
2131     ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL);
2132 
2133 
2134     ngx_conf_merge_str_value(conf->index, prev->index, "");
2135 
2136     hash.max_size = 512;
2137     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
2138     hash.name = "fastcgi_hide_headers_hash";
2139 
2140 #if (NGX_HTTP_CACHE)
2141 
2142     h = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
2143                                ngx_http_fastcgi_hide_headers;
2144 #else
2145 
2146     h = ngx_http_fastcgi_hide_headers;
2147 
2148 #endif
2149 
2150     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
2151                                             &prev->upstream, h, &hash)
2152         != NGX_OK)
2153     {
2154         return NGX_CONF_ERROR;
2155     }
2156 
2157     if (conf->upstream.upstream == NULL) {
2158         conf->upstream.upstream = prev->upstream.upstream;
2159     }
2160 
2161     if (conf->fastcgi_lengths == NULL) {
2162         conf->fastcgi_lengths = prev->fastcgi_lengths;
2163         conf->fastcgi_values = prev->fastcgi_values;
2164     }
2165 
2166 #if (NGX_PCRE)
2167     if (conf->split_regex == NULL) {
2168         conf->split_regex = prev->split_regex;
2169         conf->split_name = prev->split_name;
2170     }
2171 #endif
2172 
2173     if (conf->params_source == NULL) {
2174         conf->flushes = prev->flushes;
2175         conf->params_len = prev->params_len;
2176         conf->params = prev->params;
2177         conf->params_source = prev->params_source;
2178 
2179         if (conf->params_source == NULL) {
2180             return NGX_CONF_OK;
2181         }
2182     }
2183 
2184     conf->params_len = ngx_array_create(cf->pool, 64, 1);
2185     if (conf->params_len == NULL) {
2186         return NGX_CONF_ERROR;
2187     }
2188 
2189     conf->params = ngx_array_create(cf->pool, 512, 1);
2190     if (conf->params == NULL) {
2191         return NGX_CONF_ERROR;
2192     }
2193 
2194     src = conf->params_source->elts;
2195     for (i = 0; i < conf->params_source->nelts; i++) {
2196 
2197         if (ngx_http_script_variables_count(&src[i].value) == 0) {
2198             copy = ngx_array_push_n(conf->params_len,
2199                                     sizeof(ngx_http_script_copy_code_t));
2200             if (copy == NULL) {
2201                 return NGX_CONF_ERROR;
2202             }
2203 
2204             copy->code = (ngx_http_script_code_pt)
2205                                                   ngx_http_script_copy_len_code;
2206             copy->len = src[i].key.len;
2207 
2208 
2209             copy = ngx_array_push_n(conf->params_len,
2210                                     sizeof(ngx_http_script_copy_code_t));
2211             if (copy == NULL) {
2212                 return NGX_CONF_ERROR;
2213             }
2214 
2215             copy->code = (ngx_http_script_code_pt)
2216                                                  ngx_http_script_copy_len_code;
2217             copy->len = src[i].value.len;
2218 
2219 
2220             size = (sizeof(ngx_http_script_copy_code_t)
2221                        + src[i].key.len + src[i].value.len
2222                        + sizeof(uintptr_t) - 1)
2223                     & ~(sizeof(uintptr_t) - 1);
2224 
2225             copy = ngx_array_push_n(conf->params, size);
2226             if (copy == NULL) {
2227                 return NGX_CONF_ERROR;
2228             }
2229 
2230             copy->code = ngx_http_script_copy_code;
2231             copy->len = src[i].key.len + src[i].value.len;
2232 
2233             p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2234 
2235             p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
2236             ngx_memcpy(p, src[i].value.data, src[i].value.len);
2237 
2238         } else {
2239             copy = ngx_array_push_n(conf->params_len,
2240                                     sizeof(ngx_http_script_copy_code_t));
2241             if (copy == NULL) {
2242                 return NGX_CONF_ERROR;
2243             }
2244 
2245             copy->code = (ngx_http_script_code_pt)
2246                                                  ngx_http_script_copy_len_code;
2247             copy->len = src[i].key.len;
2248 
2249 
2250             size = (sizeof(ngx_http_script_copy_code_t)
2251                     + src[i].key.len + sizeof(uintptr_t) - 1)
2252                     & ~(sizeof(uintptr_t) - 1);
2253 
2254             copy = ngx_array_push_n(conf->params, size);
2255             if (copy == NULL) {
2256                 return NGX_CONF_ERROR;
2257             }
2258 
2259             copy->code = ngx_http_script_copy_code;
2260             copy->len = src[i].key.len;
2261 
2262             p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
2263             ngx_memcpy(p, src[i].key.data, src[i].key.len);
2264 
2265 
2266             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2267 
2268             sc.cf = cf;
2269             sc.source = &src[i].value;
2270             sc.flushes = &conf->flushes;
2271             sc.lengths = &conf->params_len;
2272             sc.values = &conf->params;
2273 
2274             if (ngx_http_script_compile(&sc) != NGX_OK) {
2275                 return NGX_CONF_ERROR;
2276             }
2277         }
2278 
2279         code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
2280         if (code == NULL) {
2281             return NGX_CONF_ERROR;
2282         }
2283 
2284         *code = (uintptr_t) NULL;
2285 
2286 
2287         code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
2288         if (code == NULL) {
2289             return NGX_CONF_ERROR;
2290         }
2291 
2292         *code = (uintptr_t) NULL;
2293     }
2294 
2295     code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
2296     if (code == NULL) {
2297         return NGX_CONF_ERROR;
2298     }
2299 
2300     *code = (uintptr_t) NULL;
2301 
2302     return NGX_CONF_OK;
2303 }
2304 
2305 
2306 static ngx_int_t
2307 ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
2308     ngx_http_variable_value_t *v, uintptr_t data)
2309 {
2310     u_char                       *p;
2311     ngx_http_fastcgi_ctx_t       *f;
2312     ngx_http_fastcgi_loc_conf_t  *flcf;
2313 
2314     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
2315 
2316     f = ngx_http_fastcgi_split(r, flcf);
2317 
2318     if (f == NULL) {
2319         return NGX_ERROR;
2320     }
2321 
2322     if (f->script_name.len == 0
2323         || f->script_name.data[f->script_name.len - 1] != '/')
2324     {
2325         v->len = f->script_name.len;
2326         v->valid = 1;
2327         v->no_cacheable = 0;
2328         v->not_found = 0;
2329         v->data = f->script_name.data;
2330 
2331         return NGX_OK;
2332     }
2333 
2334     v->len = f->script_name.len + flcf->index.len;
2335 
2336     v->data = ngx_pnalloc(r->pool, v->len);
2337     if (v->data == NULL) {
2338         return NGX_ERROR;
2339     }
2340 
2341     p = ngx_copy(v->data, f->script_name.data, f->script_name.len);
2342     ngx_memcpy(p, flcf->index.data, flcf->index.len);
2343 
2344     return NGX_OK;
2345 }
2346 
2347 
2348 static ngx_int_t
2349 ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r,
2350     ngx_http_variable_value_t *v, uintptr_t data)
2351 {
2352     ngx_http_fastcgi_ctx_t       *f;
2353     ngx_http_fastcgi_loc_conf_t  *flcf;
2354 
2355     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
2356 
2357     f = ngx_http_fastcgi_split(r, flcf);
2358 
2359     if (f == NULL) {
2360         return NGX_ERROR;
2361     }
2362 
2363     v->len = f->path_info.len;
2364     v->valid = 1;
2365     v->no_cacheable = 0;
2366     v->not_found = 0;
2367     v->data = f->path_info.data;
2368 
2369     return NGX_OK;
2370 }
2371 
2372 
2373 static ngx_http_fastcgi_ctx_t *
2374 ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
2375 {
2376     ngx_http_fastcgi_ctx_t       *f;
2377 #if (NGX_PCRE)
2378     ngx_int_t                     n;
2379     int                           captures[(1 + 2) * 3];
2380 
2381     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
2382 
2383     if (f == NULL) {
2384         f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
2385         if (f == NULL) {
2386             return NULL;
2387         }
2388 
2389         ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
2390     }
2391 
2392     if (f->script_name.len) {
2393         return f;
2394     }
2395 
2396     if (flcf->split_regex == NULL) {
2397         f->script_name = r->uri;
2398         return f;
2399     }
2400 
2401     n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
2402 
2403     if (n == NGX_REGEX_NO_MATCHED) {
2404         f->script_name = r->uri;
2405         return f;
2406     }
2407 
2408     if (n < 0) {
2409         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
2410                       ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
2411                       n, &r->uri, &flcf->split_name);
2412         return NULL;
2413     }
2414 
2415     /* match */
2416 
2417     f->script_name.len = captures[3] - captures[2];
2418     f->script_name.data = r->uri.data;
2419 
2420     f->path_info.len = captures[5] - captures[4];
2421     f->path_info.data = r->uri.data + f->script_name.len;
2422 
2423     return f;
2424 
2425 #else
2426 
2427     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
2428 
2429     if (f == NULL) {
2430         f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
2431         if (f == NULL) {
2432             return NULL;
2433         }
2434 
2435         ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
2436     }
2437 
2438     f->script_name = r->uri;
2439 
2440     return f;
2441 
2442 #endif
2443 }
2444 
2445 
2446 static char *
2447 ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2448 {
2449     ngx_http_fastcgi_loc_conf_t *flcf = conf;
2450 
2451     ngx_url_t                   u;
2452     ngx_str_t                  *value, *url;
2453     ngx_uint_t                  n;
2454     ngx_http_core_loc_conf_t   *clcf;
2455     ngx_http_script_compile_t   sc;
2456 
2457     if (flcf->upstream.upstream || flcf->fastcgi_lengths) {
2458         return "is duplicate";
2459     }
2460 
2461     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
2462 
2463     clcf->handler = ngx_http_fastcgi_handler;
2464 
2465     if (clcf->name.data[clcf->name.len - 1] == '/') {
2466         clcf->auto_redirect = 1;
2467     }
2468 
2469     value = cf->args->elts;
2470 
2471     url = &value[1];
2472 
2473     n = ngx_http_script_variables_count(url);
2474 
2475     if (n) {
2476 
2477         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2478 
2479         sc.cf = cf;
2480         sc.source = url;
2481         sc.lengths = &flcf->fastcgi_lengths;
2482         sc.values = &flcf->fastcgi_values;
2483         sc.variables = n;
2484         sc.complete_lengths = 1;
2485         sc.complete_values = 1;
2486 
2487         if (ngx_http_script_compile(&sc) != NGX_OK) {
2488             return NGX_CONF_ERROR;
2489         }
2490 
2491         return NGX_CONF_OK;
2492     }
2493 
2494     ngx_memzero(&u, sizeof(ngx_url_t));
2495 
2496     u.url = value[1];
2497     u.no_resolve = 1;
2498 
2499     flcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
2500     if (flcf->upstream.upstream == NULL) {
2501         return NGX_CONF_ERROR;
2502     }
2503 
2504     return NGX_CONF_OK;
2505 }
2506 
2507 
2508 static char *
2509 ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2510 {
2511 #if (NGX_PCRE)
2512     ngx_http_fastcgi_loc_conf_t *flcf = conf;
2513 
2514     ngx_int_t   n;
2515     ngx_str_t  *value, err;
2516     u_char      errstr[NGX_MAX_CONF_ERRSTR];
2517 
2518     value = cf->args->elts;
2519 
2520     flcf->split_name = value[1];
2521 
2522     err.len = NGX_MAX_CONF_ERRSTR;
2523     err.data = errstr;
2524 
2525     flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
2526 
2527     if (flcf->split_regex == NULL) {
2528         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2529         return NGX_CONF_ERROR;
2530     }
2531 
2532     n = ngx_regex_capture_count(flcf->split_regex);
2533 
2534     if (n < 0) {
2535         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2536                            ngx_regex_capture_count_n " failed for "
2537                            "pattern \"%V\"", &value[1]);
2538         return NGX_CONF_ERROR;
2539     }
2540 
2541     if (n != 2) {
2542         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2543                            "pattern \"%V\" must have 2 captures", &value[1]);
2544         return NGX_CONF_ERROR;
2545     }
2546 
2547     return NGX_CONF_OK;
2548 
2549 #else
2550 
2551     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2552                        "\"%V\" requires PCRE library", &cmd->name);
2553     return NGX_CONF_ERROR;
2554 
2555 #endif
2556 }
2557 
2558 
2559 static char *
2560 ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2561 {
2562     ngx_http_fastcgi_loc_conf_t *flcf = conf;
2563 
2564     ngx_str_t                  *value;
2565     ngx_http_script_compile_t   sc;
2566 
2567     if (flcf->upstream.store != NGX_CONF_UNSET
2568         || flcf->upstream.store_lengths)
2569     {
2570         return "is duplicate";
2571     }
2572 
2573     value = cf->args->elts;
2574 
2575     if (ngx_strcmp(value[1].data, "off") == 0) {
2576         flcf->upstream.store = 0;
2577         return NGX_CONF_OK;
2578     }
2579 
2580 #if (NGX_HTTP_CACHE)
2581 
2582     if (flcf->upstream.cache != NGX_CONF_UNSET_PTR
2583         && flcf->upstream.cache != NULL)
2584     {
2585         return "is incompatible with \"fastcgi_cache\"";
2586     }
2587 
2588 #endif
2589 
2590     if (ngx_strcmp(value[1].data, "on") == 0) {
2591         flcf->upstream.store = 1;
2592         return NGX_CONF_OK;
2593     }
2594 
2595     /* include the terminating '\0' into script */
2596     value[1].len++;
2597 
2598     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
2599 
2600     sc.cf = cf;
2601     sc.source = &value[1];
2602     sc.lengths = &flcf->upstream.store_lengths;
2603     sc.values = &flcf->upstream.store_values;
2604     sc.variables = ngx_http_script_variables_count(&value[1]);
2605     sc.complete_lengths = 1;
2606     sc.complete_values = 1;
2607 
2608     if (ngx_http_script_compile(&sc) != NGX_OK) {
2609         return NGX_CONF_ERROR;
2610     }
2611 
2612     return NGX_CONF_OK;
2613 }
2614 
2615 
2616 #if (NGX_HTTP_CACHE)
2617 
2618 static char *
2619 ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2620 {
2621     ngx_http_fastcgi_loc_conf_t *flcf = conf;
2622 
2623     ngx_str_t  *value;
2624 
2625     value = cf->args->elts;
2626 
2627     if (flcf->upstream.cache != NGX_CONF_UNSET_PTR) {
2628         return "is duplicate";
2629     }
2630 
2631     if (ngx_strcmp(value[1].data, "off") == 0) {
2632         flcf->upstream.cache = NULL;
2633         return NGX_CONF_OK;
2634     }
2635 
2636     if (flcf->upstream.store > 0 || flcf->upstream.store_lengths) {
2637         return "is incompatible with \"fastcgi_store\"";
2638     }
2639 
2640     flcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
2641                                                  &ngx_http_fastcgi_module);
2642     if (flcf->upstream.cache == NULL) {
2643         return NGX_CONF_ERROR;
2644     }
2645 
2646     return NGX_CONF_OK;
2647 }
2648 
2649 
2650 static char *
2651 ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2652 {
2653     ngx_http_fastcgi_loc_conf_t *flcf = conf;
2654 
2655     ngx_str_t                         *value;
2656     ngx_http_compile_complex_value_t   ccv;
2657 
2658     value = cf->args->elts;
2659 
2660     if (flcf->cache_key.value.len) {
2661         return "is duplicate";
2662     }
2663 
2664     ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
2665 
2666     ccv.cf = cf;
2667     ccv.value = &value[1];
2668     ccv.complex_value = &flcf->cache_key;
2669 
2670     if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
2671         return NGX_CONF_ERROR;
2672     }
2673 
2674     return NGX_CONF_OK;
2675 }
2676 
2677 #endif
2678 
2679 
2680 static char *
2681 ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
2682 {
2683 #if (NGX_FREEBSD)
2684     ssize_t *np = data;
2685 
2686     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
2687         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2688                            "\"fastcgi_send_lowat\" must be less than %d "
2689                            "(sysctl net.inet.tcp.sendspace)",
2690                            ngx_freebsd_net_inet_tcp_sendspace);
2691 
2692         return NGX_CONF_ERROR;
2693     }
2694 
2695 #elif !(NGX_HAVE_SO_SNDLOWAT)
2696     ssize_t *np = data;
2697 
2698     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2699                        "\"fastcgi_send_lowat\" is not supported, ignored");
2700 
2701     *np = 0;
2702 
2703 #endif
2704 
2705     return NGX_CONF_OK;
2706 }
2707 
2708 
2709 static char *
2710 ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
2711     ngx_command_t *cmd, void *conf)
2712 {
2713     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2714          "\"fastcgi_upstream_max_fails\" is not supported, "
2715          "use the \"max_fails\" parameter of the \"server\" directive ",
2716          "inside the \"upstream\" block");
2717 
2718     return NGX_CONF_ERROR;
2719 }
2720 
2721 
2722 static char *
2723 ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
2724     ngx_command_t *cmd, void *conf)
2725 {
2726     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2727          "\"fastcgi_upstream_fail_timeout\" is not supported, "
2728          "use the \"fail_timeout\" parameter of the \"server\" directive ",
2729          "inside the \"upstream\" block");
2730 
2731     return NGX_CONF_ERROR;
2732 }
2733 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.