modperl_set_cookie_and_redirect

This is part of The Pile, a partial archive of some open source mailing lists and newsgroups.



To: <modperl@apache.org>
From: "Harrison" <harrison.clan@btinternet.com>
Subject: Send a cookie, AND a redirect ? 
Date: Thu, 8 Feb 2001 12:30:31 -0000

I can set a cookie fine using:

$r->content_type('text/html');
$r->header_out('Set-Cookie' =3D>$cookie);
$r->send_http_header;

And i can also send a redirect fine using:

$r->content_type('text/html');
$r->header_out('Location'=3D>$the_url);
return REDIRECT;

BUT!

how do i do both? if i use my redirect code, and add an
extra header_out , the cookie is not sent (because i have
not called send_http_header ? ).

If i add send_http_header, i see the full sent http_header
in my browser.

My idea was to have something like

$r->content_type('text/html');
$r->header_out('Location'=3D>$the_url);
$r->header_out('Set-Cookie' =3D>$cookie);
$r->send_http_header;
return REDIRECT;


Which does not work.

Thinking about it whilst typing this email, does header_out
have a field where i can set the REDIRECT status?

===

To: Harrison <harrison.clan@btinternet.com>
From: Steve Reppucci <sgr@logsoft.com>
Subject: Re: Send a cookie, AND a redirect ? 
Date: Thu, 8 Feb 2001 07:42:26 -0500 (EST)

I believe you want to use 'err_header_out' rather than
'header_out' if you're returning a status other than OK.

===

To: Harrison <harrison.clan@btinternet.com>
From: "Ken Y. Clark" <kclark@logsoft.com>
Subject: Re: Send a cookie, AND a redirect ? 
Date: Thu, 8 Feb 2001 09:56:51 -0500 (EST)

On Thu, 8 Feb 2001, Harrison wrote:

> Date: Thu, 8 Feb 2001 12:30:31 -0000
> From: Harrison <harrison.clan@btinternet.com>
> To: modperl@apache.org
> Subject: Send a cookie, AND a redirect ? 
> 
> Dear All.
> 
> I can set a cooke fine using:
> 
> $r->content_type('text/html');
> $r->header_out('Set-Cookie' =>$cookie);
> $r->send_http_header;
> 
> And i can also send a redirect fine using:
> 
> $r->content_type('text/html');
> $r->header_out('Location'=>$the_url);
> return REDIRECT;
> 
> BUT! 
> 
> how do i do both? if i use my redirect code, and add an extra header_out , the cookie is not sent (because i have not called send_http_header ? ).
> 
> If i add send_http_header, i see the full sent http_header in my browser.
> 
> My idea was to have something like 
> 
> $r->content_type('text/html');
> $r->header_out('Location'=>$the_url);
> $r->header_out('Set-Cookie' =>$cookie);
> $r->send_http_header;
> return REDIRECT;
> 
> 
> Which does not work.
> 
> Thinking about it whilst typing this email, does header_out have a field where i can set the REDIRECT status?
> 
> Thanks in advance, 
> 
> Richard Harrison.
> 

I've had good luck using Apache::Cookie.  Like so:

sub handler {
    my $apr = shift;
    my $cookie = Apache::Cookie->new($apr,
                            -name    => 'foo',
                            -value   => 'bar',
                            -expires => '+30m',
                            -domain  => 'baz.com',
                            -path    => '/');
    $cookie->bake;

    $apr->method_number(M_GET);
    $apr->method('GET');
    $apr->headers_in->unset('Content-length');
    $apr->headers_out->add('Location' => 'index.html');
    $apr->status(REDIRECT);
    $apr->send_http_header;
    return DONE;
}

===

To: "Harrison" <harrison.clan@btinternet.com>,
<modperl@apache.org>
From: Robert Landrum <rlandrum@capitoladvantage.com>
Subject: Re: Send a cookie, AND a redirect ?
Date: Thu, 8 Feb 2001 10:27:41 -0500

The problem is that Apache does not put the "Set-Cookie" before the 
"Location" when generating headers.  To fix this, you need to build 
the header yourself.  I've found that this works with Netscape and 
IE, but with IE, the place where you redirect to does not have access 
to the cookie that you just set.  All subsequent pages are able to 
read the cookie... It's a bug in IE.


     my $cookie = Apache::Cookie->new($r,
         -name => "MYCOOKIE",
         -value => "VALUE",
         -path => "/some/cookie/path"
     );

     my %headers = (
         "Location" => "/some/redirect/location",
         "Set-Cookie" => $cookie->as_string
     );
     my $header = "Status: 302 Moved\n";
     for my $h (qw(Set-Cookie Location)) {
         $header .= $h.": ".$headers{$h}."\n";
     }
     $header .= "\n";
     $r->send_cgi_header($header);
     return(REDIRECT);

I think this might also only work for local redirects.  I think I 
tried a remote redirect once and had it not work... I not certain of 
that.

===

To: <modperl@apache.org>
From: "Harrison" <harrison.clan@btinternet.com>
Subject: Re: Send a cookie, AND a redirect ? [resolved]
Date: Thu, 8 Feb 2001 19:37:41 -0000

Using err_header_out worked :)

$r->content_type('text/html');  
$r->err_header_out('Set-Cookie' => $cookie); 
$r->err_header_out('Location' => $the_url); 
return REDIRECT; 

===

To: harrison.clan@btinternet.com
From: yen-ying.chen-dreger@uniserv.de
Subject: AW: Send a cookie, AND a redirect ? 
Date: Thu, 8 Feb 2001 14:30:56 +0100 

Hallo Harrison,

Maybe You can try this one which i read somewhere:

> $r->header_out('Set-Cookie' =>$cookie);
my $query = new CGI ;
$r->print($query->redirect("$the_url")) ;
return OK ;
# maybe "return REDIRECT" is o.k., too

===

To: Harrison <harrison.clan@btinternet.com>
From: Jeff Beard <jeff@cyberxape.com>
Subject: Re: Send a cookie, AND a redirect ? 
Date: Thu, 8 Feb 2001 07:25:36 -0700 (MST)

Read the POD docs for Apache under the heading 'Setting up the response';

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: "Jeffrey W. Baker" <jwbaker@acm.org>
Subject: Redirection Location MUST be absolute (was Re: Send
a cookie, AND
Date: Thu, 8 Feb 2001 12:52:04 -0800 (PST)

On Thu, 8 Feb 2001, Robert Landrum wrote:

> The problem is that Apache does not put the "Set-Cookie" before the
> "Location" when generating headers.  To fix this, you need to build
> the header yourself.  I've found that this works with Netscape and
> IE, but with IE, the place where you redirect to does not have access
> to the cookie that you just set.  All subsequent pages are able to
> read the cookie... It's a bug in IE.
>
>
>      my $cookie = Apache::Cookie->new($r,
>          -name => "MYCOOKIE",
>          -value => "VALUE",
>          -path => "/some/cookie/path"
>      );
>
>      my %headers = (
>          "Location" => "/some/redirect/location",

I'd like to mention that the Location header MUST be absolute, NEVER
relative.  Absolute means that it must include the scheme!

http://www.w3.org/Protocols/rfc2068/rfc2068

14.30 Location

   The Location response-header field is used to redirect the recipient
   to a location other than the Request-URI for completion of the
   request or identification of a new resource. For 201 (Created)
   responses, the Location is that of the new resource which was created
   by the request.  For 3xx responses, the location SHOULD indicate the
   server's preferred URL for automatic redirection to the resource. The
   field value consists of a single absolute URL.

          Location       = "Location" ":" absoluteURI

   An example is

          Location: http://www.w3.org/pub/WWW/People.html


===

To: "Jeffrey W. Baker" <jwbaker@acm.org>
From: Robert Landrum <rlandrum@capitoladvantage.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Thu, 8 Feb 2001 16:23:06 -0500

If all browsers followed the W3 standards the world would be a better place...

They say "...field value consists of a single absolute URL."
                                                        ^^^
I think they mean URI because the example says "absoluteURI", not URL.

An absolute URI is

/some/location

But so is

http://www.somehost.com/some/location

Both are valid URIs and both absolute.  One is more qualified than the other.

A relative URI is

some/location

which is incorrect, and not what I meant in my message.

Which brings us to the next point...

By using relative *URLs* such as /some/location, you avoid changing 
the location field in the browser window, which is often desired.  If 
you use an absolute *URL*, the location field changes to the absolute 
URL.

You can try it with a simple perl script CGI.

#!/usr/bin/perl
print "Location: /some/location/\n\n";

or

#!/usr/bin/perl
print "Location: http://somehost.com/some/location/\n\n";

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: "Jeffrey W. Baker" <jwbaker@acm.org>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Thu, 8 Feb 2001 13:41:22 -0800 (PST)

On Thu, 8 Feb 2001, Robert Landrum wrote:

> If all browsers followed the W3 standards the world would be a better
> place...
>
> They say "...field value consists of a single absolute URL."
>                                                         ^^^ I think
> they mean URI because the example says "absoluteURI", not URL.
>
> An absolute URI is
>
> /some/location

No, that is not an absolute URI.  absoluteURI is defined unabiguously in
RFC 2068:

absoluteURI    = scheme ":" *( uchar | reserved )

So, you see, an absoluteURI MUST contain the scheme.

>
> But so is
>
> http://www.somehost.com/some/location
>
> Both are valid URIs and both absolute.  One is more qualified than the
> other.

No.

> A relative URI is
>
> some/location
>
> which is incorrect, and not what I meant in my message.
>
> Which brings us to the next point...
>
> By using relative *URLs* such as /some/location, you avoid changing
> the location field in the browser window, which is often desired.  If
> you use an absolute *URL*, the location field changes to the absolute
> URL.

This is the desired behavior.

===

To: "Jeffrey W. Baker" <jwbaker@acm.org>
From: Robert Landrum <rlandrum@capitoladvantage.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Thu, 8 Feb 2001 18:19:58 -0500

That's what the RFC says... But that's not the way that a browser 
handles it.  I don't know why browsers don't support the "standards," 
but that's not exactly the topic.

Every browser I've ever tested with, including LWP, lynx and AOL, 
have supported relative Location headers.

If the W3 wants to document it incorrectly or change the unofficial 
standard, then they are wasting their time.

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: merlyn@stonehenge.com (Randal L. Schwartz)
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie, AND  a redirect ?)
Date: 08 Feb 2001 15:51:42 -0800

>>>>> "Robert" == Robert Landrum <rlandrum@capitoladvantage.com> writes:

Robert> By using relative *URLs* such as /some/location, you avoid changing
Robert> the location field in the browser window, which is often desired.  If
Robert> you use an absolute *URL*, the location field changes to the absolute
Robert> URL.

Actually, I'll disagree with that.  NEVER use internal redirects
(which you call "relative URLs" but that's another story) unless you
are fully understanding about WHY *I* say *NEVER*, in my strongest
language.

As a hint... are you willing to be responsible for how all the
relative URLs in the resulting document are treated, including all
documents called from there?

The problem is that the browser still thinks it got
"/foo/bar/fred.html", so if an internal redirect was performed to
"/abc/def/ghi.html" and it had a relative link to "../xyz.html", the
browser will fetch "/foo/xyz.html", not to the correct
"/abc/xyz.html", since the browser had no visibility to the /abc part
of that equation.

NEVER use internal redirects.

At least not until you understand why I say "NEVER".

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: Michael Peppler <mpeppler@peppler.org>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Thu, 8 Feb 2001 16:22:49 -0800 (PST)

Robert Landrum writes:
 > 
 > Every browser I've ever tested with, including LWP, lynx and AOL, 
 > have supported relative Location headers.

I've made the mistake of using relative (i.e. without the scheme) URLs
in Location headers, and although it worked most of the time there
were situations where it broke (I now forget what that was - it was
some time ago).

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: Robin Berjon <robin@knowscape.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a
Date: Fri, 09 Feb 2001 01:28:49 +0100

At 18:19 08/02/2001 -0500, Robert Landrum wrote:
>Every browser I've ever tested with, including LWP, lynx and AOL, 
>have supported relative Location headers.

Lynx will likely give you a warning on that (though
admittedly it'll work).  A good number of Netscape servers
will react to it in an interestingly varied array of ways,
ranging from returning a 5xx (not always the same one) to
completely crashing, or going into what looks like an
endless loop consuming lots of cpu and memory.

You probably don't care if you're running modperl, but as is
often the case with many standard vs broken implementation
problem, you're usually better off sticking to the standard.

===

To: "Randal L. Schwartz" <merlyn@stonehenge.com>,
modperl@apache.org
From: ___cliff rayman___ <cliff@genwax.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie, AND  a 
Date: Thu, 08 Feb 2001 16:39:22 -0800

you are supposed to be able to use:
<base href="/foo/bar/fred.html">

which changes the base of the document.  if u really wanted to use internal
redirects, you would have to insure that all documents contained this tag,
or filter the page and include it yourself.

of course this is just a spec, determining which browsers properly use
it, is beyond me.


===

To: "Randal L. Schwartz" <merlyn@stonehenge.com>,
modperl@apache.org
From: ___cliff rayman___ <cliff@genwax.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie, AND  a 
Date: Thu, 08 Feb 2001 16:44:02 -0800

___cliff rayman___ wrote:

> you are supposed to be able to use:
> <base href="/foo/bar/fred.html">

make that:
<base href="http://host.mydomain.net/foo/bar/fred.html">

===

To: merlyn@stonehenge.com (Randal L. Schwartz)
From: Robert Landrum <rlandrum@capitoladvantage.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Thu, 8 Feb 2001 19:42:26 -0500

We only use absolute URLs /images/some.gif.  When dealing with 
apache, it's often neccesary to see the previous requests environment 
(error pages, etc.) so that you can show that information to the user 
and email it to the webmaster.  That's only possible with an internal 
redirect.  As in

ErrorDocument 503 /error.pl

Using a full path there causes you to lose all of that valuable 
information that was stored in the Environment.

ErrorDocument 503 http://www.somehost.com/error.pl

I almost always use external redirects, except when I don't want the 
page I'm redirecting to bookmarked.

But I definitly understand why you say *NEVER*.

===

To: Robert Landrum <rlandrum@capitoladvantage.com>
From: merlyn@stonehenge.com (Randal L. Schwartz)
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie, AND  a redirect ?)
Date: 08 Feb 2001 16:43:49 -0800

>>>>> "Robert" == Robert Landrum <rlandrum@capitoladvantage.com> writes:

Robert> That's what the RFC says... But that's not the way that a browser
Robert> handles it.  I don't know why browsers don't support the "standards,"
Robert> but that's not exactly the topic.

Robert> Every browser I've ever tested with, including LWP, lynx and AOL, have
Robert> supported relative Location headers.

No... they've never seen one in their life.  See below.

Robert> If the W3 wants to document it incorrectly or change the unofficial
Robert> standard, then they are wasting their time.

Wait... let's start getting some terminology straight.
Let's stop talking about "relative" and "absolute" URLs with
respect to the Location: CGI response.  That's just gonna
confuse terminology.

If a CGI script sends out a Location: header that doesn't
begin with a protocol (like http: or ftp:), then it's an
*internal* redirect.

For an internal redirect, the browser never sees the
transaction.  The web server just does a "goto", picking up
the new resource, delivering the content to the browser AS
IF IT WAS THE OLD URL.  The browser doesn't even know it
happened (thus the problem I said earlier about relative
URLs in the delivered document being broken).

If there was a Set-Cookie header on this internal redirect,
THE BROWSER NEVER SEES IT.

If the CGI script instead sends a protocol first in the
Location, (like http://perltraining.stonehenge.com), that's
an *external* redirect, and turns into one of the headers
sent to the browser, along with a Set-Cookie if present.
The *browser* then fetches the new URL as a separate
transaction.

Nearly always, what you want is an *external* redirect.  The
relative URLs in the new document are correct, and cookies
get set as needed.

If you are using an *internal* redirect, BE VERY VERY
CAREFUL THAT THIS IS WHAT YOU WANT.  Nearly
always... *never*.

Does that help?

====

To: modperl@apache.org
From: Tony Demark <tony-modperl@legaux.com>
Subject: Re: Redirection Location MUST be absolute (was Re:
Send a cookie,
Date: Fri, 9 Feb 2001 09:38:25 -0500

Let me bring this back to mod_perl for a sec:

>If a CGI script sends out a Location: header that doesn't begin with a
>protocol (like http: or ftp:), then it's an *internal* redirect.
>
>For an internal redirect, the browser never sees the transaction.  The
>web server just does a "goto", picking up the new resource, delivering
>the content to the browser AS IF IT WAS THE OLD URL.  The browser
>doesn't even know it happened (thus the problem I said earlier about
>relative URLs in the delivered document being broken).

Just for clarification, you are speaking _specifically_ about 
non-mod_perl CGIs, correct?

Doing this (via mod_perl):

$r->header_out(Location => '/foo/bar/');

causes an external redirect (REPLY headers being sent to the browser), as in:

glory:tony[1]% telnet www.uswx.com 80
Trying 207.106.24.123...
Connected to sundog.uswx.com.
Escape character is '^]'.
GET /us/wx/PA HTTP/1.0

HTTP/1.0 302 Found
Date: Fri, 09 Feb 2001 14:29:32 GMT
Server: Apache/1.3.9 (Unix) mod_perl/1.21
Location: /us/wx/PA/
Content-Type: text/html

<!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="/us/wx/PA/">here</A>.<P>
</BODY></HTML>

===


the rest of The Pile (a partial mailing list archive)

doom@kzsu.stanford.edu