Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the CGI CPAN distribution.

Report information
The Basics
Id: 15065
Status: resolved
Priority: 0/
Queue: CGI

People
Owner: MARKSTOS [...] cpan.org
Requestors: williams [...] tni.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: CGI should support 'Set-Cookie' header
When using mod_perl with CGI::Cookie, the recommended way to set cookies is: $r->headers_out->set('Set-Cookie' => $c); but when running as a cgi script the recommended way to set cookies is: print header(-cookie=>$c); So here's the problem: when running as a cgi script using a mod_perl emulator (such as HTML::Mason::FakeApache or Apache::Emulator) we would like to use the mod_perl recommended method, so we can switch transparently between mod_perl and cgi. However, using the 'Set-Cookie' header does not work with *multiple* cookies, because CGI.pm only looks for multiple cookies under the 'Cookie' or 'Cookies' headers.
Attach a test case.
use lib '.'; use Test::More qw(no_plan); use CGI; $cgi= CGI->new; like( $cgi->header('-content-type','foo/fum','-set-cookie',['a=b','b=c']), qr/Set-cookie: a=b\s+Set-cookie: b=c/si, 'Set-Cookie' ); ## If you have HTML::Mason installed, this will illustrate the ## problem when using the FakeApache module. # #use HTML::Mason::FakeApache; # #my $r = HTML::Mason::FakeApache->new(); #$r->err_headers_out->add('Set-Cookie'=>'a=b'); #$r->err_headers_out->add('Set-Cookie'=>'b=c'); #print $r->http_header;
Attach patch to fix the bug. please apply :)
--- CGI.pm 2005/10/14 21:55:50 1.1 +++ CGI.pm 2005/10/14 21:55:59 @@ -1400,7 +1400,7 @@ my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) = rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'], - 'STATUS',['COOKIE','COOKIES'],'TARGET', + 'STATUS',['COOKIE','COOKIES','SET-COOKIE'],'TARGET', 'EXPIRES','NPH','CHARSET', 'ATTACHMENT','P3P'],@p);
Thanks for the bug report and patch. I'm marking this bug as "rejected" now only because it has been inactive since 2005. If you are still interested in a change in CGI.pm, you can reply to re-open the ticket. Mark On Fri Oct 14 17:47:38 2005, guest wrote: Show quoted text
> When using mod_perl with CGI::Cookie, the recommended way to set > cookies is: > > $r->headers_out->set('Set-Cookie' => $c); > > but when running as a cgi script the recommended way to set cookies > is: > > print header(-cookie=>$c); > > So here's the problem: when running as a cgi script using a mod_perl > emulator (such as HTML::Mason::FakeApache or Apache::Emulator) we > would like to use the mod_perl recommended method, so we can switch > transparently between mod_perl and cgi. However, using the 'Set- > Cookie' header does not work with *multiple* cookies, because > CGI.pm only looks for multiple cookies under the 'Cookie' or > 'Cookies' headers.
Well, it's nice to hear from someone after all this time. Re-opening as requested. Is there anything else I can do? On Mon Jul 20 18:53:50 2009, MARKSTOS wrote: Show quoted text
> Thanks for the bug report and patch. > > I'm marking this bug as "rejected" now only because it has been inactive > since 2005. If you are still interested in a change in CGI.pm, you can > reply to re-open the ticket. > > Mark
On Fri Oct 14 17:47:38 2005, guest wrote: Show quoted text
> When using mod_perl with CGI::Cookie, the recommended way to set > cookies is: > > $r->headers_out->set('Set-Cookie' => $c); > > but when running as a cgi script the recommended way to set cookies > is: > > print header(-cookie=>$c); > > So here's the problem: when running as a cgi script using a mod_perl > emulator (such as HTML::Mason::FakeApache or Apache::Emulator) we > would like to use the mod_perl recommended method, so we can switch > transparently between mod_perl and cgi. However, using the 'Set- > Cookie' header does not work with *multiple* cookies, because > CGI.pm only looks for multiple cookies under the 'Cookie' or > 'Cookies' headers.
I'd like to understand the request better. CGI.pm does support the "Set-Cookie" header... that's exactly what the cookie() method is using. Also, CGI.pm works tranparently when switching to and from mod_perl. So, it's not clear what is requesting to be changed. Mark
Subject: CGI should support 'Set-Cookie' header (for multiple cookies)
On Tue Jul 21 21:11:18 2009, MARKSTOS wrote: Show quoted text
> I'd like to understand the request better. CGI.pm does support the > "Set-Cookie" header... that's exactly what the cookie() method is using. > Also, CGI.pm works tranparently when switching to and from mod_perl. So, > it's not clear what is requesting to be changed. > Mark
Note that the problem is with setting *MULTIPLE* cookies, as I do in the cgi.t test file. CGI supports passing an arrayref if you use "Cookie" or "Cookies" as the header, but not if you use "Set-Cookie". Set-Cookie will pass through a scalar correctly, but an arrayref will come out with "ARRAY(9393030)" for the cookie value. This patch makes "Set-Cookie" work the same as "Cookie" and "Cookies". Bottom line is that CGI and mod_perl are not compatible when trying to set multiple cookies. The fix for CGI is extremely simple, since it already does the right thing, but with the wrong header label. To illustrate: $cgi->header('-cookie'=>'x=y') # Set-cookie: x=y $cgi->header('-set-cookie'=>'x=y') # Set-cookie: x=y $cgi->header('-cookie'=>['x=y','a=b']) # Set-Cookie: x=y # Set-Cookie: a=b $cgi->header('-set-cookie'=>['x=y','a=b']) # Set-cookie: ARRAY(0x816607c) The patch fixes the last case.
Still broken in CGI-3.49 Jon Craig posted on the Mason-users mailing list that the redirect function has the same bug as the header function. Here is a new patch to fix both. It also includes tests in t/html.t
Subject: cgi.patch
--- lib/CGI.pm 2010-01-29 07:41:54.000000000 -0700 +++ lib/CGI.pm 2010-02-25 13:10:51.000000000 -0700 @@ -1538,7 +1538,7 @@ my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) = rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'], - 'STATUS',['COOKIE','COOKIES'],'TARGET', + 'STATUS',['COOKIE','COOKIES','SET-COOKIE'],'TARGET', 'EXPIRES','NPH','CHARSET', 'ATTACHMENT','P3P'],@p); @@ -1640,7 +1640,7 @@ sub redirect { my($self,@p) = self_or_default(@_); my($url,$target,$status,$cookie,$nph,@other) = - rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES'],NPH],@p); + rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES','SET-COOKIE'],NPH],@p); $status = '302 Found' unless defined $status; $url ||= $self->self_url; my(@o); --- t/html.t 2009-09-09 09:28:57.000000000 -0600 +++ t/html.t 2010-02-25 13:09:44.000000000 -0700 @@ -1,6 +1,6 @@ #!/usr/local/bin/perl -w -use Test::More tests => 33; +use Test::More tests => 40; END { ok $loaded; } use CGI ( ':standard', '-no_debug', '*h3', 'start_table' ); @@ -125,15 +125,47 @@ my $cookie = cookie( -name => 'fred', -value => [ 'chocolate', 'chip' ], -path => '/' ); - is $cookie, 'fred=chocolate&chip; path=/', "cookie()"; my $h = header( -Cookie => $cookie ); - like $h, qr!^Set-Cookie: fred=chocolate&chip\; path=/${CRLF}Date:.*${CRLF}Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!s, "header(-cookie)"; +$h = header( '-set-cookie' => $cookie ); +like $h, + qr!^Set-[Cc]ookie: fred=chocolate&chip\; path=/${CRLF}(Date:.*${CRLF})?Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!s, + "header(-set-cookie)"; + +my $cookie2 = + cookie( -name => 'ginger', -value => 'snap' , -path => '/' ); +is $cookie2, 'ginger=snap; path=/', "cookie2()"; + +$h = header( -cookie => [ $cookie, $cookie2 ] ); +like $h, + qr!^Set-Cookie: fred=chocolate&chip\; path=/${CRLF}Set-Cookie: ginger=snap\; path=/${CRLF}(Date:.*${CRLF})?Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!s, + "header(-cookie=>[cookies])"; + +$h = header( '-set-cookie' => [ $cookie, $cookie2 ] ); +like $h, + qr!^Set-Cookie: fred=chocolate&chip\; path=/${CRLF}Set-Cookie: ginger=snap\; path=/${CRLF}(Date:.*${CRLF})?Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!s, + "header(-set-cookie=>[cookies])"; + +$h = redirect('http://elsewhere.org/'); +like $h, + qr!Status: 302 Found${CRLF}Location: http://elsewhere.org/!s, + "redirect"; + +$h = redirect(-url=>'http://elsewhere.org/', -cookie=>[$cookie,$cookie2]); +like $h, + qr!Status: 302 Found${CRLF}Set-[Cc]ookie: \Q$cookie\E${CRLF}Set-[Cc]ookie: \Q$cookie2\E${CRLF}(Date:.*${CRLF})?Location: http://elsewhere.org/!s, + "redirect with cookies"; + +$h = redirect(-url=>'http://elsewhere.org/', '-set-cookie'=>[$cookie,$cookie2]); +like $h, + qr!Status: 302 Found${CRLF}Set-[Cc]ookie: \Q$cookie\E${CRLF}Set-[Cc]ookie: \Q$cookie2\E${CRLF}(Date:.*${CRLF})?Location: http://elsewhere.org/!s, + "redirect with set-cookies"; + is start_h3, '<h3>'; is end_h3, '</h3>';
This issue has been copied to: https://github.com/leejo/CGI.pm/issues/47 please take all future correspondence there. This ticket will remain open but please do not reply here. This ticket will be closed when the github issue is dealt with.
Patches applied, thanks. Will go out with the next version.