hesh has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing a CGI script which displays a form, on submit sets some session variables and then redirects to a different page.

The problems is, to set the session variables I need to print the HTTP header first.

print $session->header();

But after printing the header I can't redirect to another page anymore.

$query->redirect('www.google.com'); fails.

Any idea how to solve this problem?

Replies are listed 'Best First'.
Re: [CGI] redirect after headers have been printed
by imp (Priest) on Jul 14, 2006 at 04:06 UTC
    There's more than one way to this this of course, but here are a few:

    1. Within CGI.pm

    #!/usr/bin/perl use strict; use warnings; use CGI; my $cgi = CGI->new; my $cookie = $cgi->cookie(-name => 'test', -value => 'testval', -expir +es => "+2h"); print $cgi->redirect( -location => 'http://perlmonks.com', -cookie => $cookie );
    2. Generate redirect with CGI, and scrape cookies from the session object's proposed header
    #!/usr/bin/perl use strict; use warnings; use CGI; # Define the session object however you were before, # I can't emulate it as you didn't say what # class was being used use Something; my $session = Something->new(); # Get the header that the session object wants to output my $session_header = $session->header(); # Filter out everything other than Set-Cookie headers $session_header = join("\n", grep /^Set-Cookie/, split("\n", $session_ +header)); #output the Set-Cookie headers if ($session_header) { print $session_header . "\n"; } #output the headers that CGI generates my $cgi = CGI->new; print $cgi->redirect('http://perlmonks.com');
    #1 would be my preferred solution.
    #2 is a bit too hackish for my tastes, and any developer who inherits the project will likely hurt you.
Re: [CGI] redirect after headers have been printed
by rodion (Chaplain) on Jul 14, 2006 at 03:52 UTC
    Take a look at how do I set a cookie and redirect in the PerlMonks Categorized Q & A section. This shows one way to do it.

    I'm a little rusty in this area, but I believe the problem with the way you were trying to do it is that "$session->header()" call is setting the coookie and sending the headers in one call, but redirect needs to come before the headers, so after the header() call is too late. Doing your own headers, as in the Q & A, allows you to get the components in the right order.

    The second answer in the Q&A avoids the problem by using refresh instead of redirect.

    Update: Fixed Link. (Thanks shmem)

Re: [CGI] redirect after headers have been printed
by NetWallah (Canon) on Jul 14, 2006 at 02:29 UTC
          "The problems is, to set the session variables I need to print the HTTP header first."

    Why do you need to do that ?

    Logically, you are either giving the user output, or redirecting him.
    If the user needs to be fed some information in response to the form, you can get the receiving (redirected) page to display that information, by passing that information either as a session variable, or via a querystring.

    In the absolutely last resort, you can output a page to the client, then use client-side refresh to redirect the page.

         "For every complex problem, there is a simple answer ... and it is wrong." --H.L. Mencken

      Why do you need to do that ?

      Simple -- you have a website that uses cookies for authentication. It senses someone's not logged in, and sends them to a login form. The form submits to a page -- that sets the necessary cookies, and then redirects them back to the page they originally attempted to access.

      Yes, there are other ways of doing this, but when the majority of your pages and other items (images, video, etc.) are static, it doesn't make sense to place the whole thing between a heavyweight CMS.

      Yes, this might be an XY Problem, but I've had the same problem before, when tool authors assume that this feature would never be needed, and yet it makes perfect sense to me.

Re: [CGI] redirect after headers have been printed
by jhourcle (Prior) on Jul 14, 2006 at 02:37 UTC

    For some reason, ColdFusion had this limitation back (can't both set cookies and do a redirect). I have no idea if it's been fixed in ColdFusion, as I haven't used it for years, but you can with mod_perl.

    I think you can do it if you just generate the headers yourself, rather than have the CGI module do it for you.

Re: [CGI] redirect after headers have been printed
by shmem (Chancellor) on Jul 14, 2006 at 13:25 UTC
    You could use meta tags in the header:
    <meta http-equiv="refresh" content="1; url=http://foo.bar.com/login.pl +">

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: [CGI] redirect after headers have been printed
by Khen1950fx (Canon) on Jul 14, 2006 at 03:42 UTC
    I tend to agree with NetWallah. And to amplify that a bit further, I'd recommend using CGI::Session. The CGI::Session::Tutorial explains it best, esp.the dropping of cookies and query_strings.

    See:CGI::Session::Tutorial