diff src/http/modules/ngx_http_fastcgi_module.c @ 578:f3a9e57d2e17

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Mar 2010 21:27:17 +0300
parents da3c99095432
children be4f34123024
line wrap: on
line diff
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -62,7 +62,8 @@ typedef struct {
     size_t                         length;
     size_t                         padding;
 
-    ngx_uint_t                     fastcgi_stdout; /* unsigned :1 */
+    unsigned                       fastcgi_stdout:1;
+    unsigned                       large_stderr:1;
 
     ngx_array_t                   *split_parts;
 
@@ -240,6 +241,13 @@ static ngx_command_t  ngx_http_fastcgi_c
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
       NULL },
 
+    { ngx_string("fastcgi_bind"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_upstream_bind_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
+      NULL },
+
     { ngx_string("fastcgi_connect_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -523,6 +531,23 @@ static ngx_str_t  ngx_http_fastcgi_hide_
 };
 
 
+#if (NGX_HTTP_CACHE)
+
+static ngx_str_t  ngx_http_fastcgi_hide_cache_headers[] = {
+    ngx_string("Status"),
+    ngx_string("X-Accel-Expires"),
+    ngx_string("X-Accel-Redirect"),
+    ngx_string("X-Accel-Limit-Rate"),
+    ngx_string("X-Accel-Buffering"),
+    ngx_string("X-Accel-Charset"),
+    ngx_string("Set-Cookie"),
+    ngx_string("P3P"),
+    ngx_null_string
+};
+
+#endif
+
+
 static ngx_path_init_t  ngx_http_fastcgi_temp_path = {
     ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
 };
@@ -1057,6 +1082,7 @@ ngx_http_fastcgi_reinit_request(ngx_http
 
     f->state = ngx_http_fastcgi_st_version;
     f->fastcgi_stdout = 0;
+    f->large_stderr = 0;
 
     return NGX_OK;
 }
@@ -1075,6 +1101,7 @@ ngx_http_fastcgi_process_header(ngx_http
     ngx_table_elt_t                *h;
     ngx_http_upstream_t            *u;
     ngx_http_fastcgi_ctx_t         *f;
+    ngx_http_fastcgi_header_t      *fh;
     ngx_http_upstream_header_t     *hh;
     ngx_http_fastcgi_loc_conf_t    *flcf;
     ngx_http_fastcgi_split_part_t  *part;
@@ -1199,8 +1226,17 @@ ngx_http_fastcgi_process_header(ngx_http
                          * of the PHP warnings to not allocate memory
                          */
 
-                        u->buffer.pos = u->buffer.start;
-                        u->buffer.last = u->buffer.start;
+#if (NGX_HTTP_CACHE)
+                        if (r->cache) {
+                            u->buffer.pos = u->buffer.start
+                                                     + r->cache->header_start;
+                        } else {
+                            u->buffer.pos = u->buffer.start;
+                        }
+#endif
+
+                        u->buffer.last = u->buffer.pos;
+                        f->large_stderr = 1;
                     }
 
                     return NGX_AGAIN;
@@ -1216,6 +1252,45 @@ ngx_http_fastcgi_process_header(ngx_http
 
         /* f->type == NGX_HTTP_FASTCGI_STDOUT */
 
+#if (NGX_HTTP_CACHE)
+
+        if (f->large_stderr) {
+            u_char   *start;
+            ssize_t   len;
+
+            start = u->buffer.start + r->cache->header_start;
+
+            len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
+
+            /*
+             * A tail of large stderr output before HTTP header is placed
+             * in a cache file without a FastCGI record header.
+             * To workaround it we put a dummy FastCGI record header at the
+             * start of the stderr output or update r->cache_header_start,
+             * if there is no enough place for the record header.
+             */
+
+            if (len >= 0) {
+                fh = (ngx_http_fastcgi_header_t *) start;
+                fh->version = 1;
+                fh->type = NGX_HTTP_FASTCGI_STDERR;
+                fh->request_id_hi = 0;
+                fh->request_id_lo = 1;
+                fh->content_length_hi = (u_char) ((len >> 8) & 0xff);
+                fh->content_length_lo = (u_char) (len & 0xff);
+                fh->padding_length = 0;
+                fh->reserved = 0;
+
+            } else {
+                r->cache->header_start += u->buffer.pos - start
+                                           - sizeof(ngx_http_fastcgi_header_t);
+            }
+
+            f->large_stderr = 0;
+        }
+
+#endif
+
         f->fastcgi_stdout = 1;
 
         start = u->buffer.pos;
@@ -1899,6 +1974,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
+    ngx_str_t                    *h;
     ngx_uint_t                    i;
     ngx_keyval_t                 *src;
     ngx_hash_init_t               hash;
@@ -2119,10 +2195,18 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
     hash.name = "fastcgi_hide_headers_hash";
 
+#if (NGX_HTTP_CACHE)
+
+    h = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
+                               ngx_http_fastcgi_hide_headers;
+#else
+
+    h = ngx_http_fastcgi_hide_headers;
+
+#endif
+
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream,
-                                            ngx_http_fastcgi_hide_headers,
-                                            &hash)
+                                            &prev->upstream, h, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
@@ -2374,27 +2458,25 @@ ngx_http_fastcgi_split(ngx_http_request_
 
     n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
 
+    if (n >= 0) { /* match */
+        f->script_name.len = captures[3] - captures[2];
+        f->script_name.data = r->uri.data;
+
+        f->path_info.len = captures[5] - captures[4];
+        f->path_info.data = r->uri.data + f->script_name.len;
+
+        return f;
+    }
+
     if (n == NGX_REGEX_NO_MATCHED) {
         f->script_name = r->uri;
         return f;
     }
 
-    if (n < 0) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
-                      n, &r->uri, &flcf->split_name);
-        return NULL;
-    }
-
-    /* match */
-
-    f->script_name.len = captures[3] - captures[2];
-    f->script_name.data = r->uri.data;
-
-    f->path_info.len = captures[5] - captures[4];
-    f->path_info.data = r->uri.data + f->script_name.len;
-
-    return f;
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+                  n, &r->uri, &flcf->split_name);
+    return NULL;
 
 #else
 
@@ -2485,39 +2567,34 @@ ngx_http_fastcgi_split_path_info(ngx_con
 #if (NGX_PCRE)
     ngx_http_fastcgi_loc_conf_t *flcf = conf;
 
-    ngx_int_t   n;
-    ngx_str_t  *value, err;
-    u_char      errstr[NGX_MAX_CONF_ERRSTR];
+    ngx_str_t            *value;
+    ngx_regex_compile_t   rc;
+    u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
     value = cf->args->elts;
 
     flcf->split_name = value[1];
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
-
-    flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
-
-    if (flcf->split_regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pattern = value[1];
+    rc.pool = cf->pool;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
+
+    if (ngx_regex_compile(&rc) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
         return NGX_CONF_ERROR;
     }
 
-    n = ngx_regex_capture_count(flcf->split_regex);
-
-    if (n < 0) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           ngx_regex_capture_count_n " failed for "
-                           "pattern \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (n != 2) {
+    if (rc.captures != 2) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "pattern \"%V\" must have 2 captures", &value[1]);
         return NGX_CONF_ERROR;
     }
 
+    flcf->split_regex = rc.regex;
+
     return NGX_CONF_OK;
 
 #else