changeset 40:bc4fc02c96a3 NGINX_0_1_20

nginx 0.1.20 *) Feature: the new "script_filename" and "remote_port" parameters of the fastcgi_params directive. *) Bugfix: the FastCGI stderr stream was handled incorrectly.
author Igor Sysoev <http://sysoev.ru>
date Thu, 17 Feb 2005 00:00:00 +0300
parents 9a816ccfbf63
children 4d8e7a81b3a0
files CHANGES CHANGES.ru src/core/nginx.h src/event/ngx_event_openssl.c src/http/modules/ngx_http_fastcgi_handler.c
diffstat 5 files changed, 176 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+
+Changes with nginx 0.1.20                                        17 Feb 2005
+
+    *) Feature: the new "script_filename" and "remote_port" parameters 
+       ofthe fastcgi_params directive.
+
+    *) Bugfix: the FastCGI stderr stream was handled incorreсtly.
+
 
 Changes with nginx 0.1.19                                        16 Feb 2005
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,3 +1,12 @@
+
+Изменения в nginx 0.1.20                                          17.02.2005
+
+    *) Добавление: новые параметры script_filename и remote_port в 
+       директиве fastcgi_params.
+
+    *) Исправление: неправильно обрабатывался поток stderr от 
+       FastCGI-сервера.
+
 
 Изменения в nginx 0.1.19                                          16.02.2005
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.19"
+#define NGINX_VER          "nginx/0.1.20"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -112,7 +112,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char
                             continue;
                         }
 
-                        if (*s == '\n' || *s == '\r') {
+                        if (*s == LF || *s == CR) {
                             continue;
                         }
 
--- a/src/http/modules/ngx_http_fastcgi_handler.c
+++ b/src/http/modules/ngx_http_fastcgi_handler.c
@@ -68,23 +68,27 @@ typedef struct {
     size_t                        length;
     size_t                        padding;
 
+    ngx_uint_t                    header;
+
     ngx_http_fastcgi_upstream_t  *upstream;
 } ngx_http_fastcgi_ctx_t;
 
 
-#define NGX_HTTP_FASTCGI_REMOTE_ADDR          0x0002
-#define NGX_HTTP_FASTCGI_REMOTE_USER          0x0004
-#define NGX_HTTP_FASTCGI_SERVER_NAME          0x0008
-#define NGX_HTTP_FASTCGI_SERVER_ADDR          0x0010
-#define NGX_HTTP_FASTCGI_SERVER_PORT          0x0020
-#define NGX_HTTP_FASTCGI_SCRIPT_NAME          0x0040
-#define NGX_HTTP_FASTCGI_AUTH_TYPE            0x0080
-#define NGX_HTTP_FASTCGI_SERVER_PROTOCOL      0x0100
-#define NGX_HTTP_FASTCGI_SERVER_SOFTWARE      0x0200
-#define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE    0x0400
-#define NGX_HTTP_FASTCGI_REQUEST_URI          0x0800
-#define NGX_HTTP_FASTCGI_REDIRECT_STATUS      0x1000
-#define NGX_HTTP_FASTCGI_DOCUMENT_ROOT        0x2000
+#define NGX_HTTP_FASTCGI_REMOTE_ADDR          0x00000002
+#define NGX_HTTP_FASTCGI_REMOTE_USER          0x00000004
+#define NGX_HTTP_FASTCGI_SERVER_NAME          0x00000008
+#define NGX_HTTP_FASTCGI_SERVER_ADDR          0x00000010
+#define NGX_HTTP_FASTCGI_SERVER_PORT          0x00000020
+#define NGX_HTTP_FASTCGI_SCRIPT_NAME          0x00000040
+#define NGX_HTTP_FASTCGI_AUTH_TYPE            0x00000080
+#define NGX_HTTP_FASTCGI_SERVER_PROTOCOL      0x00000100
+#define NGX_HTTP_FASTCGI_SERVER_SOFTWARE      0x00000200
+#define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE    0x00000400
+#define NGX_HTTP_FASTCGI_REQUEST_URI          0x00000800
+#define NGX_HTTP_FASTCGI_REDIRECT_STATUS      0x00001000
+#define NGX_HTTP_FASTCGI_DOCUMENT_ROOT        0x00002000
+#define NGX_HTTP_FASTCGI_SCRIPT_FILENAME      0x00004000
+#define NGX_HTTP_FASTCGI_REMOTE_PORT          0x00008000
 
 
 #define NGX_HTTP_FASTCGI_RESPONDER      1
@@ -199,7 +203,10 @@ static ngx_conf_bitmask_t  ngx_http_fast
 
     { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS },
     { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI },
+
     { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT },
+    { ngx_string("script_filename"), NGX_HTTP_FASTCGI_SCRIPT_FILENAME },
+    { ngx_string("remote_port"), NGX_HTTP_FASTCGI_REMOTE_PORT },
 
     { ngx_null_string, 0 }
 };
@@ -421,16 +428,18 @@ ngx_http_fastcgi_handler(ngx_http_reques
 static ngx_int_t
 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
 {
-    u_char                             ch, *pos, addr_text[INET_ADDRSTRLEN];
-    size_t                             size, len, index, padding, addr_len;
+    u_char                             ch, *pos, addr_text[INET_ADDRSTRLEN],
+                                       port_text[sizeof("65535") - 1];
+    size_t                             size, len, index, padding,
+                                       addr_len, port_len;
     off_t                              file_pos;
     ngx_buf_t                         *b;
     socklen_t                          slen;
     ngx_chain_t                       *cl, *body;
-    ngx_uint_t                         i, n, next, *vindex;
+    ngx_uint_t                         i, n, next, *vindex, port;
     ngx_list_part_t                   *part;
     ngx_table_elt_t                   *header;
-    struct sockaddr_in                 sin;
+    struct sockaddr_in                 sin, *sinp;
     ngx_http_variable_t               *var;
     ngx_http_variable_value_t         *value;
     ngx_http_core_loc_conf_t          *clcf;
@@ -520,6 +529,12 @@ ngx_http_fastcgi_create_request(ngx_http
                  + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len;
     }
 
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
+        len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
+                 + sizeof("SCRIPT_FILENAME") - 1
+                 + flcf->root.len + r->uri.len + index;
+    }
+
     if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
         len += 1 + ((r->uri.len + index > 127) ? 4 : 1)
                  + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ;
@@ -529,6 +544,25 @@ ngx_http_fastcgi_create_request(ngx_http
         len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len;
     }
 
+    port_len = 0;
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_PORT) {
+
+        /* AF_INET only */
+
+        if (r->connection->sockaddr->sa_family == AF_INET) {
+            sinp = (struct sockaddr_in *) r->connection->sockaddr;
+
+            port = ntohs(sinp->sin_port);
+
+            if (port > 0 && port < 65536) {
+                port_len = ngx_sprintf(port_text, "%ui", port) - port_text;
+            }
+
+            len += 1 + 1 + sizeof("REMOTE_PORT") - 1 + port_len;
+        }
+    }
+
     if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
         len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len;
     }
@@ -831,6 +865,31 @@ ngx_http_fastcgi_create_request(ngx_http
     }
 
 
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
+        *b->last++ = sizeof("SCRIPT_FILENAME") - 1;
+
+        len = flcf->root.len + r->uri.len + index;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "SCRIPT_FILENAME",
+                             sizeof("SCRIPT_FILENAME") - 1);
+        b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
+        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+        if (index) {
+            b->last = ngx_cpymem(b->last, flcf->index.data, index);
+        }
+    }
+
+
     if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
         *b->last++ = sizeof("SCRIPT_NAME") - 1;
 
@@ -863,6 +922,14 @@ ngx_http_fastcgi_create_request(ngx_http
     }
 
 
+    if (port_len) {
+        *b->last++ = sizeof("REMOTE_PORT") - 1;
+        *b->last++ = (u_char) port_len;
+        b->last = ngx_cpymem(b->last, "REMOTE_PORT", sizeof("REMOTE_PORT") - 1);
+        b->last = ngx_cpymem(b->last, port_text, port_len);
+    }
+
+
     if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
         *b->last++ = sizeof("SERVER_NAME") - 1;
         *b->last++ = (u_char) r->server_name.len;
@@ -1151,12 +1218,13 @@ ngx_http_fastcgi_reinit_request(ngx_http
     }
 
     f->state = ngx_http_fastcgi_st_version;
+    f->header = 0;
 
     ngx_memzero(&f->upstream->headers_in,
                 sizeof(ngx_http_fastcgi_headers_in_t));
 
     if (f->upstream->headers_in.headers.part.elts) {
-        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 5,
+        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
                                          sizeof(ngx_table_elt_t)) == NGX_ERROR)
         {
             return NGX_ERROR;
@@ -1170,7 +1238,7 @@ ngx_http_fastcgi_reinit_request(ngx_http
 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r)
 {
     u_char                  *start, *last;
-    ngx_str_t               *status_line;
+    ngx_str_t               *status_line, line;
     ngx_int_t                rc, status;
     ngx_uint_t               i;
     ngx_table_elt_t         *h;
@@ -1191,7 +1259,7 @@ static ngx_int_t ngx_http_fastcgi_proces
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
-        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 5,
+        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
                                          sizeof(ngx_table_elt_t)) == NGX_ERROR)
         {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -1220,7 +1288,9 @@ static ngx_int_t ngx_http_fastcgi_proces
                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
             }
 
-            if (f->type != NGX_HTTP_FASTCGI_STDOUT) {
+            if (f->type != NGX_HTTP_FASTCGI_STDOUT
+                && f->type != NGX_HTTP_FASTCGI_STDERR)
+            {
                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                               "upstream sent unexpected FastCGI record: %d",
                               f->type);
@@ -1228,7 +1298,7 @@ static ngx_int_t ngx_http_fastcgi_proces
                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
             }
 
-            if (f->length == 0) {
+            if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                               "upstream closed prematurely FastCGI stdout");
 
@@ -1258,8 +1328,58 @@ static ngx_int_t ngx_http_fastcgi_proces
             return NGX_AGAIN;
         }
 
+
         /* f->state == ngx_http_fastcgi_st_data */
 
+        if (f->type == NGX_HTTP_FASTCGI_STDERR) {
+
+            if (f->header) {
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                              "upstream split a header in FastCGI records");
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            if (f->length) {
+                line.data = u->header_in.pos;
+
+                if (u->header_in.pos + f->length <= u->header_in.last) {
+                    line.len = f->length;
+                    u->header_in.pos += f->length;
+                    f->length = 0;
+                    f->state = ngx_http_fastcgi_st_padding;
+
+                } else { 
+                    line.len = u->header_in.last - u->header_in.pos;
+                    f->length -= u->header_in.last - u->header_in.pos;
+                    u->header_in.pos = u->header_in.last;
+                }
+
+                while (line.data[line.len - 1] == LF
+                       || line.data[line.len - 1] == CR
+                       || line.data[line.len - 1] == '.'
+                       || line.data[line.len - 1] == ' ')
+                {
+                    line.len--;
+                }
+
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "FastCGI sent in stderr: \"%V\"", &line);
+
+                if (u->header_in.pos == u->header_in.last) {
+                    return NGX_AGAIN;
+                }
+
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+
+            continue;
+        }
+
+
+        /* f->type == NGX_HTTP_FASTCGI_STDOUT */
+
         start = u->header_in.pos;
 
         if (u->header_in.pos + f->length < u->header_in.last) {
@@ -1276,6 +1396,8 @@ static ngx_int_t ngx_http_fastcgi_proces
             last = NULL;
         }
 
+        f->header = 1;
+
         for ( ;; ) {
 
             rc = ngx_http_parse_header_line(r, &u->header_in);
@@ -1572,6 +1694,8 @@ ngx_http_fastcgi_input_filter(ngx_event_
                 if (f->pos + f->length <= f->last) {
                     line.len = f->length;
                     f->pos += f->length;
+                    f->length = 0;
+                    f->state = ngx_http_fastcgi_st_padding;
 
                 } else { 
                     line.len = f->last - f->pos;
@@ -1579,21 +1703,25 @@ ngx_http_fastcgi_input_filter(ngx_event_
                     f->pos = f->last;
                 }
 
-                /*
-                 * TODO: copy split stderr output into buffer,
-                 *       clean it up
-                 */
+                while (line.data[line.len - 1] == LF
+                       || line.data[line.len - 1] == CR
+                       || line.data[line.len - 1] == '.'
+                       || line.data[line.len - 1] == ' ')
+                {
+                    line.len--;
+                }
 
                 ngx_log_error(NGX_LOG_ERR, p->log, 0,
-                              "FastCGI stderr: %V", &line);
+                              "FastCGI sent in stderr: \"%V\"", &line);
 
                 if (f->pos == f->last) {
                     break;
                 }
+
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
             }
 
-            f->state = ngx_http_fastcgi_st_version;
-
             continue;
         }