Subject: | CGI::Fast first-request Environment showing up in later requests |
The first request to a CGI::Fast daemon is recording certain environment
variables, and later requests are getting these as defaults if none are
defined.
The two which have affected me are HTTP_COOKIE, and PATH_INFO.
If the first request has no value, then all subsequent requests are
fine. However, if the first request has values, then these become
defaults for future requests which otherwise would have no value.
I've tested it both with dynamically starting FastCGIs, and with pre-
initialised ones via FastCGIServer, and both exhibit the same behaviour.
I've attached a test FastCGI script (test1) which illustrates the
problem. If you access it from a browser which has a cookie within the
path, or use an extra path, and then access it from a different browser
with no cookie/path, you get the cookie/path showing up.
This is a pretty big problem for apps which use a cookie to track a
session for authentication. If a pre-existing user accesses the app,
then their session cookie gets saved as the default, and subsequent
anonymous requests show up as authenticated to that user.
There may also be other env vars suffering the same issue, but these
were the two key ones that are impacting my apps.
As some further tests, I tested using just FCGI by itself (see test2).
It did not show the problem.
I then used a FCGI main loop, but using CGI internally (ie; not using
CGI::Fast) (see test3), and it also did not show the problem.
I copied CGI/Fast.pm, and found that if I added:
$Ext_Request = FCGI::Request();
...to BEGIN, if there's no FCGI_SOCKET_PATH, then using CGI::Fast works
fine.
ie;
BEGIN {
# ...
if ($ENV{FCGI_SOCKET_PATH}) {
# ...
}
else
{
$Ext_Request = FCGI::Request();
}
}
It seems that using one request, rather than just calling
FCGI::accept(), works properly.
Before I pinpointed the issue, I updated my CGI perl libs from CPAN, so
am using 3.52. The FCGI lib is 0.7.1. The server runs Debian Linux
5.0.6, with kernel 2.6.31.5. Perl is version 5.10.0.
Subject: | test1 |
#!/usr/bin/perl
# Test using CGI::Fast, illustrating problem with bleed of Cookie & Path Info.
use CGI::Fast;
use CGI::Cookie;
%Initial = ();
while (($key, $val) = each %ENV)
{
$Initial{$key} = $val;
}
$Count = 0;
while ($q = CGI::Fast->new())
{
$Count++;
print $q->header();
print "<h4>Current ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$ENV{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
print "<h4>Via CGI Methods:</h4>\n<dl>".
'<dt>remote_addr</dt><dd>'.$q->remote_addr."</dd>\n".
'<dt>raw_cookie</dt><dd>'.$q->raw_cookie."</dd>\n".
'<dt>path_info</dt><dd>'.$q->path_info."</dd>\n".
'<dt>query_string</dt><dd>'.$q->query_string."</dd>\n".
"</dl>";
print <<STOP;
<h4>Other</h4>
<dl>
<dt>Process</dt><dd>$$</dd>
<dt>Counter</dt><dd>$Count</dd>
</dl>
<h4>Versions</h4>
<dl>
<dt>CGI</dt><dd>$CGI::VERSION</dd>
<dt>CGI::Fast</dt><dd>$CGI::Fast::VERSION</dd>
<dt>CGI::Cookie</dt><dd>$CGI::Cookie::VERSION</dd>
<dt>FCGI</dt><dd>$FCGI::VERSION</dd>
</dl>
STOP
print "<h4>Initial ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$Initial{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
}
Subject: | test3 |
#!/usr/bin/perl
# Test using FCGI for the main loop, but CGI internally.
# This seems to NOT have the problem that CGI::Fast has.
use FCGI;
use CGI;
%Initial = ();
while (($key, $val) = each %ENV)
{
$Initial{$key} = $val;
}
my $request = FCGI::Request();
$Count = 0;
while ($request->Accept() >= 0)
{
$Count++;
my $q = CGI->new();
print $q->header();
# print "Content-type: text/html\n\n";
print "<h4>Current ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$ENV{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
print "<h4>Via CGI Methods:</h4>\n<dl>".
'<dt>remote_addr</dt><dd>'.$q->remote_addr."</dd>\n".
'<dt>raw_cookie</dt><dd>'.$q->raw_cookie."</dd>\n".
'<dt>path_info</dt><dd>'.$q->path_info."</dd>\n".
'<dt>query_string</dt><dd>'.$q->query_string."</dd>\n".
"</dl>";
print <<STOP;
<h4>Other</h4>
<dl>
<dt>Process</dt><dd>$$</dd>
<dt>Counter</dt><dd>$Count</dd>
</dl>
<h4>Versions</h4>
<dl>
<dt>CGI</dt><dd>$CGI::VERSION</dd>
<dt>CGI::Fast</dt><dd>$CGI::Fast::VERSION</dd>
<dt>CGI::Cookie</dt><dd>$CGI::Cookie::VERSION</dd>
<dt>FCGI</dt><dd>$FCGI::VERSION</dd>
</dl>
STOP
print "<h4>Initial ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$Initial{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
}
Subject: | test2 |
#!/usr/bin/perl
# Test using just FCGI, to check the problem isn't related to FCGI.
use FCGI;
%Initial = ();
while (($key, $val) = each %ENV)
{
$Initial{$key} = $val;
}
my $request = FCGI::Request();
$Count = 0;
while ($request->Accept() >= 0)
{
$Count++;
print "Content-type: text/html\n\n";
print "<h4>Current ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$ENV{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
print <<STOP;
<h4>Other</h4>
<dl>
<dt>Process</dt><dd>$$</dd>
<dt>Counter</dt><dd>$Count</dd>
</dl>
<h4>Versions</h4>
<dl>
<dt>FCGI</dt><dd>$FCGI::VERSION</dd>
</dl>
STOP
print "<h4>Initial ENV Vars:</h4>\n<dl>".join('',map { '<dt>'.$_.'</dt><dd>'.$Initial{$_}.'</dd>' } qw(REMOTE_ADDR HTTP_COOKIE PATH_INFO QUERY_STRING))."</dl>\n";
}