I have found a bug with sqwebmail when running under FastCGI.
In a virtual hosting environment (multiple DNS hostnames mapped to the same
physical server) it spits out redirects for the wrong hosts. This is because
some persistent data is being wrongly kept between invocations in
cgi/cgihttpscriptptr.c:
static const char *scriptptr=0; //<<< FastCGI: maintained between requests!
extern void error(const char *);
const char *cgihttpscriptptr()
{
if (!scriptptr)
{
char *p=getenv("SCRIPT_NAME");
char *h=getenv("HTTP_HOST");
... etc
Unfortunately this means that once one request has been serviced, and a
second request arrives using a different HTTP_HOST, you always get a
redirect back to the original host (e.g. when http_redirect_top() calls
cgiredirect())
Solution: the 'scriptptr' cache needs to be reinitialised for every request,
in both cgi/cgihttpscriptptr.c and cgi/cgihttpsscriptptr.c (There are other static
variables in cgi/cgi.c but I've not checked whether
there are any problems there or not).
For now I have reverted to running sqwebmail as a normal single-invocation
CGI.
Aside: There's one other minor issue I'd like to note, although this may be
a problem with Apache not sqwebmail. HTTP/1.1 redirects behave differently
from HTTP/1.0, in that they don't seem to generate the canned HTML redirect
message. Rather, you get a zero-length document with "Content-Type:
application/x-httpd-fcgi":
--------------------------------------------------------------------------
$ telnet 192.0.2.1 80
Trying 192.0.2.1...
Connected to webmail.example.com.
Escape character is '^]'.
GET /webmail HTTP/1.1
Host: webmail.example.com
HTTP/1.1 303 Moved
Date: Tue, 24 Jun 2003 11:49:11 GMT
Server: Apache/1.3.27 (Unix) PHP/4.3.1 mod_fastcgi/2.4.0 mod_throttle/3.1.2
mod_ssl/2.8.14 OpenSSL/0.9.6g
Cache-Control: no-store
Pragma: no-cache
URI: http://webmail.example.com/webmail?index=1
Vary: Host
Location: http://webmail.example.com/webmail?index=1
Transfer-Encoding: chunked
Content-Type: application/x-httpd-fcgi
0
--------------------------------------------------------------------------
But for HTTP/1.0 I get what I expected, which is a fake HTML document for
browsers to click if they don't support redirects:
--------------------------------------------------------------------------
$ telnet 192.0.2.1 80
Trying 192.0.2.1...
Connected to webmail.example.com.
Escape character is '^]'.
GET /webmail HTTP/1.0
Host: webmail.example.com
HTTP/1.1 302 Found
Date: Tue, 24 Jun 2003 11:49:36 GMT
Server: Apache/1.3.27 (Unix) PHP/4.3.1 mod_fastcgi/2.4.0 mod_throttle/3.1.2
mod_ssl/2.8.14 OpenSSL/0.9.6g
Cache-Control: no-store
Pragma: no-cache
URI: http://webmail.example.com/webmail?index=1
Location: http://webmail.example.com/webmail?index=1
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>302 Found</TITLE>
</HEAD><BODY>
<H1>Found</H1>
The document has moved <A
HREF="http://webmail.example.com/webmail?index=1">here</A>.<P>
<HR>
<ADDRESS>Apache/1.3.27 Server at webmail.example.com Port 80</ADDRESS>
</BODY></HTML>
Connection closed by foreign host.
--------------------------------------------------------------------------
This document is actually generated by Apache (ap_send_error_response in
src/main/http_protocol.c) but I can't see why it doesn't work for the
HTTP/1.1 case, since both 302 and 303 result codes should be handled almost
identically:
switch (status) {
case HTTP_MOVED_PERMANENTLY:
case HTTP_MOVED_TEMPORARILY:
case HTTP_TEMPORARY_REDIRECT:
ap_rvputs(r, "The document has moved <A HREF=\"",
ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
NULL);
break;
case HTTP_SEE_OTHER:
ap_rvputs(r, "The answer to your request is located <A HREF=\"",
ap_escape_html(r->pool, location), "\">here</A>.<P>\n",
NULL);
break;
So it might be drawing attention to some underlying problem... I just don't
know what that is :-)
Cheers,
Brian.