I've got a funny problem with setting a cookie and then redirecting under mod_perl. I've had a regular cgi environment up until now, and the set cookie/redirect has never been an issue; everything has worked as expected. When I turned on mod_perl however, I get a status 200 and an html body being sent with the redirect url in it. The cookie is always being placed after the header and before the document body, even though I'm printing it before the redirect. I trimmed down the script to bare-bones so you can see what I mean:
#!/usr/local/bin/perl
use strict;
use warnings;
use CGI;
my $cgi = new CGI;
my $cookie = CGI::cookie(
'-name' => 'joe',
'-value' => 'fred',
'-path' => '/cgi-bin',
'-httponly' => 1,
);
print "Set-Cookie: $cookie\n";
print $cgi->redirect(-uri => 'http://example.com/cgi-bin/joe.cgi', -status => 303);
When I test this with curl under regular CGI, I get (domain name replaced and snipped for brevity):
< HTTP/1.1 303 See Other
< Date: Tue, 23 Oct 2012 16:26:55 GMT
< Server: Apache/2.2.22 (Ubuntu)
< Set-Cookie: joe=fred; path=/cgi-bin; HttpOnly
< Location: http://example.com/cgi-bin/joe.cgi
< Content-Length: 0
...which is what I expect. When I test this under mod_perl, I get:
< HTTP/1.1 200 OK
< Date: Tue, 23 Oct 2012 16:26:38 GMT
< Server: Apache/2.2.22 (Ubuntu)
< Location: http://example.com/cgi-bin/joe.cgi
< Transfer-Encoding: chunked
<
Set-Cookie: joe=fred; path=/cgi-bin; HttpOnly
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>200 OK</title>
</head><body>
<h1>OK</h1>
<p>The answer to your request is located <a href="http://example.com/cgi-bin/joe.cgi">here</a>.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at example.com Port 80</address>
</body></html>
I'm getting no warnings in logs. Any idea why mod_perl has decided to handle this redirect in such a bizarre way?
What actually fixed everything for me was using:
my $r = Apache2::RequestUtil->request;
$r->err_headers_out->add('Set-Cookie' => $cookie);
...for my cookie processing. This ensures cookies will work if you decide to redirect later.
I was trying to avoid polluting my pure cgi scripts with mod_perl so I could switch back and forth, but compromised with this. All other header processing works fine now.