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

Hi monks, I've taken up CGI recently. I have a cgi program which calculates votes based on the option chosen at a web page. When the user clicks on 'Vote' button, i want poll.cgi to redirect to results.cgi.

Here's the code in poll.cgi that I'm using.

print redirect ("http://10.20.91.122/cgi-bin/result.cgi");
Now on clicking 'Vote' I see:
Status: 302 Found Location: http://10.20.91.122/cgi-bin/result.cgi

What am I doing wrong here?
Here's the complete poll.cgi code:
#!C:/Perl/bin/perl -wT use CGI qw(:standard); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); use strict; use Fcntl qw(:flock :seek); print header; print start_html("Poll"); my $outfile="poll.txt"; if(param('club')){ open(POLL,">>$outfile") or dienice ("Can't open poll.txt: $!"); flock(POLL, LOCK_EX); seek(POLL,0,SEEK_END); print POLL param('club')."\n"; close(POLL); } print end_html; #redirect to result.cgi print redirect ("http://10.20.91.122/cgi-bin/result.cgi"); sub dienice { my($msg) = @_; print header; print start_html("Error"); print h2("Error"); print $msg; print end_html; exit; }

Replies are listed 'Best First'.
Re: CGI redirect
by dsheroh (Monsignor) on Aug 05, 2009 at 15:18 UTC
    An HTTP response can only have one set of headers. The redirect must be the absolute first thing you print - no print header;, no print start_html;, no print end_html;. Nothing. (And there's generally little point in printing anything else after it).

      Though there is sometimes point in exit()ing after it. There's a fairly well known attack which involves client-side trickery to avoid following a refresh, because sometimes (i.e. in very poorly written code) you'll get a valid page of data instead of, for instance, the redirected login page you should have got.

      Hi monks, I've taken up CGI recently

      ... I'm not sure that's something you admit to in public... (kidding)

      Thanks for the reply. I removed the headers from poll.cgi. Now I get a 'Page cannot be displayed error'. The problem is, poll.cgi takes the vote and writes it to a file. results.cgi reads the file after each vote and populates a table.

      poll.cgi
      #!C:/Perl/bin/perl -wT use CGI qw(:standard); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); use strict; use Fcntl qw(:flock :seek); my $outfile="poll.txt"; if(param('club')){ open(POLL,">>$outfile") or dienice ("Can't open poll.txt: $!"); flock(POLL, LOCK_EX); seek(POLL,0,SEEK_END); print POLL param('club')."\n"; close(POLL); } #redirect to result.cgi print redirect ("http://10.20.91.122/cgi-bin/results.cgi"); sub dienice { my($msg) = @_; print header; print start_html("Error"); print h2("Error"); print $msg; print end_html; exit; }
      results.cgi
      #!C:/Perl/bin/perl -wT use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use strict; use Fcntl qw(:flock :seek); print header; print start_html; my $outfile="poll.txt"; open(POLL,"$outfile") or dienice("Can't open $outfile:$!"); #set a shared lock on the file flock(POLL,LOCK_SH); #seek the beginning of the file seek(POLL,0,SEEK_SET); my(%count,$total_count); $total_count=0; foreach my $i ("mutd","che","ars","liv","none"){ $count{$i}=0; } while(my $rec=<POLL>){ chomp($rec); $total_count = $total_count+1; $count{$rec} = $count{$rec}+1; } print <<END; <b>Which is your favorite club?</b><br> <table border=0 width=50%> <tr> <td>Manchester United<td> <td>$count{mutd} votes<td> <tr> <td>Arsenal<td> <td>$count{ars} votes<td> <tr> <td>Chelsea<td> <td>$count{che} votes<td> <tr> <td>Liverpool<td> <td>$count{liv} votes<td> <tr> <td>Others<td> <td>$count{none} votes<td> </table> END print end_html; sub dienice { my($msg) = @_; print h2("Error"); print $msg; print end_html; exit; }
        Thanks guys. Now it works. I removed all the headers (header,start_html,end_html) and used :
        print "Location: http://abc/xyz\n\n"
        Now it redirects correctly.
Re: CGI redirect
by Foxpond Hollow (Sexton) on Aug 05, 2009 at 15:47 UTC
    I would think there's also going to be a problem with dienice, since if it gets called it will be printing a new header and start/end html information right in the middle of of the "Poll" html.