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

If I set a cookie in one sub like so
print $q->header( {-cookie=>$cookie} );
and then later in the same instantiation of the script go to print another header as the output at the end of the run I get Content-Type: text/html; charset=ISO-8859-1 printed above the head tags. I realize this is because of the previous header.

My question: Do I have to reconfigure the script so I print the cookie at the same time as the "text/html" header for the output page to prevent this eyesore?
TIA
jg<BR _____________________________________________________
It's not my tree.

Replies are listed 'Best First'.
Re: Header Visible In CGI output after cookie header is sent
by Masem (Monsignor) on Mar 04, 2002 at 04:35 UTC
    Short answer: yes. I've found that the best thing to do is never to try to call the header line inside subs, leaving that header call in the main parts of the routine, just to avoid this situation.

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

(cLive ;-) Re: Header Visible In CGI output after cookie header is sent
by cLive ;-) (Prior) on Mar 04, 2002 at 06:35 UTC
    If you print headers in several places (eg, depending on action to take), you might want to set up a couple of subs to keep your vars nice and local, eg:
    #!/usr/bin/perl -w use strict; use CGI; my $q = CGI->new(); # create cookie my $cookie1 = $q->cookie(-name=>'sessionID', -value=>'xyzzy', -expires=>'+1h', -path=>'/'); # set cookie set_cookie($cookie1); # create another cookie my $cookie2 = $q->cookie(-name=>'another_one', -value=>'abbaaba', -expires=>'+1h', -path=>'/'); # set other cookie set_cookie($cookie2); # or, set both cookies at the same time set_cookie($cookie1,$cookie2); print cookie_header(), $q->start_html, $q->p('hello'), $q->end_html; exit(0); # this is the localized 'cookie jar' :) { my @cookies = (); sub set_cookie { push @cookies, @_; } sub cookie_header { $q->header(-cookie=>[@cookies]); } }
    And if there's no cookies to be set, no problem as far as the script is concerned - so just replace $q->header with cookie_header() throughout and you can stop worrying.

    .02

    cLive ;-)

    --
    seek(JOB,$$LA,0);

Re: Header Visible In CGI output after cookie header is sent
by Trimbach (Curate) on Mar 04, 2002 at 13:00 UTC
    No one's mentioned this yet, so I will. In CGI.pm there's a special $HEADERS_ONCE flag that, when set, will suppress duplicate prints of the HTTP header information. In short, it does exactly what you want. Just put:
    #!/usr/bin/perl use CGI qw(:standard); $CGI::HEADERS_ONCE =1;
    at the top of your program and you can call header() as many times as you like and only the first print will make it to the browser. Easy cheesy. (No, this is not in the CGI.pm documentation. :-D)

    Gary Blackburn
    Trained Killer

Re: Header Visible In CGI output after cookie header is sent
by Anonymous Monk on Mar 04, 2002 at 06:45 UTC
    Depending of your version of CGI, the header function will look a little different, but here is the basic jist of it
    #### Method: header # Return a Content-Type: style header # #### 'header' => <<'END_OF_FUNC', sub header { my($self,@p) = self_or_default(@_); my(@header); return undef if $self->{'.header_printed'}++ and $HEADERS_ONCE; my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachmen +t,@other) = rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'], 'STATUS',['COOKIE','COOKIES'],'TARGET', 'EXPIRES','NPH','CHARSET', 'ATTACHMENT'],@p); $nph ||= $NPH; if (defined $charset) { $self->charset($charset); } else { $charset = $self->charset; } # rearrange() was designed for the HTML portion, so we # need to fix it up a little. foreach (@other) { next unless my($header,$value) = /([^\s=]+)=\"?(.+?)\"?$/; ($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeH +TML($value)/e; } $type ||= 'text/html' unless defined($type); $type .= "; charset=$charset" if $type ne '' and $type =~ m!^text/ +! and $type !~ /\bcharset\b/; # Maybe future compatibility. Maybe not. my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0'; push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph; push(@header,"Server: " . &server_software()) if $nph; push(@header,"Status: $status") if $status; push(@header,"Window-Target: $target") if $target; # push all the cookies -- there may be several if ($cookie) { my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} + : $cookie; foreach (@cookie) { my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string +: $_; push(@header,"Set-Cookie: $cs") if $cs ne ''; } } # if the user indicates an expiration time, then we need # both an Expires and a Date header (so that the browser is # uses OUR clock) push(@header,"Expires: " . expires($expires,'http')) if $expires; push(@header,"Date: " . expires(0,'http')) if $expires || $cookie +|| $nph; push(@header,"Pragma: no-cache") if $self->cache(); push(@header,"Content-Disposition: attachment; filename=\"$attachm +ent\"") if $attachment; push(@header,@other); push(@header,"Content-Type: $type") if $type ne ''; my $header = join($CRLF,@header)."${CRLF}${CRLF}"; if ($MOD_PERL and not $nph) { my $r = Apache->request; $r->send_cgi_header($header); return ''; } return $header; } END_OF_FUNC
    The header function behaves as it should. The reason you get the so called eyesore, is because the header has already been printed, and you're attempting to print it again, so at this point, it might be formatted like a header, but it's treated as content. The key value pairs that make up the http header are usually referred to as "http headers" but they're just fields of the http header. The http header is terminated by a "\n\n", which is what most people leave out when first printing a header on their own, and that is the purpose of the header function, to make sure a valid header is printed (one terminated with \n\n)....

    I suggest you learn more about HTTP and CGI, as well as read CGI.pm (in this case at least the header funtion), and you'll see why the answer to your question is yes.

Re: Header Visible In CGI output after cookie header is sent
by Ryszard (Priest) on Mar 04, 2002 at 06:07 UTC
    I asked this exact same question. With all due respect to masem, the short answer is no you dont.

      Err -- hold your horses, there. It isn't the exact same question. CGI::Application is a whole nother ball game than just plane ole CGI.pm. The problem you had, and both of the solutions which were given to you, are CGI::Application specific. Both solutions use the header_props method on CGI::Application, which does not exist in CGI.pm. Do not be so quick to assume that your question is identical to others'.

      As a side note, it's generally curtious to use the [id://130409|some node] format when giving links to other places in the Monastery, so as to not inadvertantly log out other monks.

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

        Ahhhhh whoops, that'll teach me to skim.

        mea culpa