Perl CGI::Fast closes connections without sending data

cgi-application, fastcgi, nginx, perl

Solution

You are running a FastCGI server, but you are telling Nginx to connect to an HTTP server. These are not the same protocol.

To connect to a FastCGI server from Nginx, use `ngx_http_fastcgi_module`, not `ngx_http_proxy_module`, e.g.:

fastcgi_pass 127.0.0.1:5001;

Note that the `proxy_set_header` module is not applicable here, as FastCGI uses CGI environment variables, not headers. If you need to set extra headers, you can do so using the `fastcgi_param` directive, e.g.

fastcgi_param ENVIRONMENT_VARIABLE $value;

Nginx ships with some standard `fastcgi_param` directives in a file which you'll probably want to just import wholesale:

include fastcgi_params;

Problem

I am trying to deploy up a Perl application that uses `CGI::Application` through Nginx, using FastCGI to communicate between them. Nginx keeps returning "502 Bad Gateway", and the error log is filled with this: 2015/02/03 12:40:03 [error] 11209#0: *2 upstream prematurely closed connection while reading response header from upstream, client: 10.1.1.23, server: www.example.com, request: "GET /test.fcgi HTTP/1.1", upstream: "http://127.0.0.1:5001/test.fcgi", host: "www.example.com" Here is the Nginx site configuration: ``` upstream @perl { # I had been trying to use a socket, but I switched to TCP to try WireShark. # server unix:/var/run/nginx/my-app.sock; server 127.0.0.1:5001; } server { listen 80; listen 443 ssl; server_name www.example.com; root /home/example/sites/www.example.com; location ~* \.fcgi(/|$) { fastcgi_split_path_info ^(.+?\.cgi)(/.*)$; # (I know that the `if` is old-style, and that `try_files` is better, but that shouldn't affect whether it works or not.) if (!-f $document_root$fastcgi_script_name) { return 404; } proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Port 443; proxy_pass http://@perl; } } ``` To see if the problem is with the Perl application itself, I created a new fcgi application based on the test code found in the `CGI::Fast` documentation: ``` #!/usr/bin/perl -wT use CGI::Fast; # Added this to see if there are errors. # See http://perldoc.perl.org/CGI/Carp.html BEGIN { use CGI::Carp qw(carpout); open(LOG, ">>/home/example/sites/www.example.com/err.log") or die("Unable to open mycgi-log: $!\n"); carpout(LOG); } local $count = 0; $ENV{FCGI_SOCKET_PATH} = "127.0.0.1:5001"; $ENV{FCGI_LISTEN_QUEUE} = 100; while ( my $q = new CGI::Fast ) { $count++; print $q->header( "text/plain" ), "You are request number $count. Have a good day!\n"; } ``` When I run `./test.fcgi`, I can see in `netstat` that it has bound to port 5001. When I go to the URL in the browser, I still get a 502 with this super-simple app. There is nothing in the error log that `Carp` is writing to. I do not want to use plain CGI (via a wrapper script) because of the application's long startup time, and I can't convert the whole application to Plack/PSGI. How can I figure out why Nginx won't talk to Perl `CGI::Fast`, even to the plain example from the docs?

Original source