Hello,

This changeset adds support for FastCGI FCGI_END_REQUEST record type.
Now nginx does not process this type of FastCGI record.
In case of usage php fastcgi upstream which finishes FastCGI
requests before end of script using fastcgi_finish_request() call
it leads to "upstream sent unexpected FastCGI record: 3 while reading
response header from upstream" error messages and 502 for clients.

Changeset parses FCGI_END_REQUEST FastCGI records and ignores it
if keep_conn is enabled and record has type FCGI_REQUEST_COMPLETE.


Kind regards,
Dmitry Saprykin
# HG changeset patch
# User Dmitry Saprykin <[email protected]>
# Date 1404466764 -14400
#      Fri Jul 04 13:39:24 2014 +0400
# Branch keep_conn_fix
# Node ID 1fa8e428eb6c6790203100e741987b925c2ecf25
# Parent  602c0d46a2bb4d86c036c75b3103b916a17380d1
* added FASTCGI_END_REQUEST processing

diff -r 602c0d46a2bb -r 1fa8e428eb6c src/http/modules/ngx_http_fastcgi_module.c
--- a/src/http/modules/ngx_http_fastcgi_module.c	Fri Jul 04 13:31:17 2014 +0400
+++ b/src/http/modules/ngx_http_fastcgi_module.c	Fri Jul 04 13:39:24 2014 +0400
@@ -53,6 +53,15 @@
     ngx_http_fastcgi_st_padding
 } ngx_http_fastcgi_state_e;
 
+typedef enum {
+    ngx_http_fastcgi_pst_request_complete = 0,
+    ngx_http_fastcgi_pst_cant_mpx_conn,
+    ngx_http_fastcgi_pst_overloaded,
+    ngx_http_fastcgi_pst_unknown_role
+} ngx_http_fastcgi_protocol_status_e;
+
+#define NGX_HTTP_FASTCGI_END_REQUEST_CONTENT_LEN  8
+#define NGX_HTTP_FASTCGI_END_REQUEST_STATUS_OFFSET  4
 
 typedef struct {
     u_char                        *start;
@@ -62,6 +71,7 @@
 
 typedef struct {
     ngx_http_fastcgi_state_e       state;
+    ngx_http_fastcgi_protocol_status_e protocol_status;
     u_char                        *pos;
     u_char                        *last;
     ngx_uint_t                     type;
@@ -1236,6 +1246,8 @@
     ngx_http_fastcgi_split_part_t  *part;
     ngx_http_upstream_main_conf_t  *umcf;
 
+    ngx_http_fastcgi_protocol_status_e protocol_status;
+
     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
 
     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
@@ -1263,7 +1275,8 @@
             }
 
             if (f->type != NGX_HTTP_FASTCGI_STDOUT
-                && f->type != NGX_HTTP_FASTCGI_STDERR)
+                && f->type != NGX_HTTP_FASTCGI_STDERR
+                && f->type != NGX_HTTP_FASTCGI_END_REQUEST)
             {
                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                               "upstream sent unexpected FastCGI record: %d",
@@ -1305,6 +1318,33 @@
 
         /* f->state == ngx_http_fastcgi_st_data */
 
+        if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
+            if (f->length != NGX_HTTP_FASTCGI_END_REQUEST_CONTENT_LEN) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                    "upstream sent wrong fastcgi_end_request record");
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            protocol_status = (u_char)u->buffer.pos[NGX_HTTP_FASTCGI_END_REQUEST_STATUS_OFFSET];
+
+            flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+            if (!flcf->keep_conn || protocol_status != ngx_http_fastcgi_pst_request_complete) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                    "upstream sent unexpected request_end fastcgi record %d",
+                    protocol_status
+                );
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            u->buffer.pos += f->length;
+            f->length = 0;
+            f->state = ngx_http_fastcgi_st_padding;
+
+            continue;
+        }
+
         if (f->type == NGX_HTTP_FASTCGI_STDERR) {
 
             if (f->length) {


_______________________________________________
nginx-devel mailing list
[email protected]
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to