2

Using CGI::Carp, I would like to use set_die_handler to gracefully output an error message.

The web page is not expected to encounter an error, but if it does and it occurs somewhere after print header has already been called, it outputs the header as text and the page will most likely be formatted incorrectly.

As the question states, I would like to check if CGI::header() has already been called. This could be done by using a global variable and setting it every place I may have the function being called, but I am hoping this might already be performed internally; or there might be a way to parse what has already been sent to STDOUT. An example of non-working code:

BEGIN {
   set_die_handler(
       sub {
           print header if not CGI::header_called;
           # or possibly,something like: if (<STDOUT> !~ /Content\-Type/)
           ...
       });
}

Note:
Comments related to age of CGI.pm are accepted, but are also quickly dismissed :) It's realized that Perl has MVC frameworks

vol7ron
  • 40,809
  • 21
  • 119
  • 172

2 Answers2

10

It's not documented, but CGI does keep track of whether header has already been called or not.

>perl -e"use CGI qw( :cgi ); print header; print header;"
Content-Type: text/html; charset=ISO-8859-1

Content-Type: text/html; charset=ISO-8859-1


>perl -e"use CGI qw( :cgi -unique_headers ); print header; print header;"
Content-Type: text/html; charset=ISO-8859-1


>
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • very nice did not know about this – vol7ron Oct 10 '13 at 14:44
  • I'll also add that when using the command line, you should use the `-M` options for module loading :) – vol7ron Oct 10 '13 at 14:55
  • There's no should about it -- it's merely a little shorter -- and it wasn't clear the OP would have understood what `-MCGI=:cgi,-unique_headers` meant – ikegami Oct 10 '13 at 15:00
  • Ahh. I'll clarify -- yes the OP would have understood what the `-MCGI=:cgi,-unique_headers` is about; though, the OP is in the process of seeing if it's safe enough to call, since the OP has encountered some "malformed header" errors as a result. – vol7ron Oct 10 '13 at 19:14
  • Doesn't change the fact that it wasn't clear then. The code I presented will not cause malformed headers. Not calling `header` at all will do that. You might get the wrong header (existing header is for text/plain and the error message wants to send HTML, etc), but not a malformed header. – ikegami Oct 10 '13 at 19:18
  • Yes, the issue is it's not calling the header from the die handler. So the first line of output is the doctype (the first output line after header()), which is why the server sees this as a malformed header (it isn't). The question is why would CGI think a header had been printed, if it had not yet been; however, this isn't the forum for debugging. thx – vol7ron Oct 10 '13 at 19:51
1

CGI.pm keeps track of this information in an attribute called .header_printed, which you can check if you want. It's worth noting that this is an internal feature and is undocumented, so it's not guaranteed to continue working in future versions.

$ perl -MCGI -E'$c = CGI->new; say $c->header unless $c->{".header_printed"}; say $c->header unless $c->{".header_printed"};'
Content-Type: text/html; charset=ISO-8859-1
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • very nice not know about this either -- only selected the other answer because it came first, but I think seeing the attribute called this way was more beneficial to access hidden internals – vol7ron Oct 10 '13 at 14:52