Moshe Katz
Moshe Katz

Reputation: 16873

Perl CGI::Fast closes connections without sending data

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?

Upvotes: 4

Views: 561

Answers (1)

user149341
user149341

Reputation:

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;

Upvotes: 6

Related Questions