I have a legacy Perl CGI script written with CGI.pm
, which replies its progress by printing some lines of text through the CGI interface. Its legacy client would then read the response line by line and do whatever.
I'm unable to setup nginx to make it work, because of buffering issues.
My setup:
- CentOS 7 + EPEL
yum install fcgi fcgi-devel spawn-fcgi
fcgiwrap
recently needed a patch to support aNO_BUFFERING
environment variable, to turn off buffering. This is described in this answer on ServerFault. However, it's puzzling:- the debian bug report linked in that answer claims the patch has been applied upstream by
fcgiwrap
, but there is nothing related to it in the upstream github repository, excepting for an open issue which has never been replied to. Anyway, the patch has been applied to debian packages, but the EPEL package does not include it, so: git clone
the repository- applied
debian_patches_add-environment-variable-NO_BUFFERING-to-disable-out.patch
from the above debian bugreport. autoreconf -i && ./configure && make && make install
- the debian bug report linked in that answer claims the patch has been applied upstream by
Configured
span-fcgi
, this is\etc\sysconfig\spawn-fcgi
:
OPTIONS="-u nginx -g nginx -a 127.0.0.1 -p 9001 -P /var/run/spawn-fcgi.pid -- /usr/local/sbin/fcgiwrap -f"
- Configured
nginx
for fastcgi:
location ~ .cgi$ {
fastcgi_pass 127.0.0.1:9001;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_request_buffering off;
fastcgi_read_timeout 900s;
fastcgi_param NO_BUFFERING 1;
gzip off;
include /etc/nginx/fastcgi_params;
}
Other info:
- The perl script does
$| = 1;
so afaik the script itself should not be buffering its own output. - The perl script also sends the
X-Accel-Buffering: no
HTTP header, which is often referred to as required to disable buffering with nginx, although afaik it should not be needed withfastcgi_buffering off
in the configuration file. - By listening on the 9001 port with
netcat
(nc -l 9001 > request.txt
), I've checked thatnginx
correctly passes theNO_BUFFERING
variable in the request along with all the other parameters. - By doing
cat request.txt | nc localhost 9001
, I see thatfcgiwrap
is what is buffering the output: if I kill the spawned cgi process midway, I get all the output generated until then. - The CGI script is launched and working fine otherwise, just the client is not receiving the data line by line (but I need the
fastcgi_read_timeout 900s
line above to avoid timeouts). - I'm not sure I fully understand the
fcgiwrap
source code, but the patch is trivial: it just callsFCGI_fflush
after every write if theNO_BUFFERING
environment variable was set. However, just to be sure, I replacedunbuffered = !!getenv("NO_BUFFERING");
withunbuffered = 1;
, with no success.
So can someone spot what I'm missing?