The perlman:CGI::Carp POD's state that you may pass set_message() a coderef, and that in order to properly intercept compile-time errors it is necessary to place the error handler in a BEGIN block.
The following snippet is provided in the perlman:CGI::Carp POD for CGI::Carp:
use CGI::Carp qw(fatalsToBrowser set_message); BEGIN { sub handle_errors { my $msg = shift; print "<h1>Oh gosh</h1>"; print "<p>Got an error: $msg</p>"; } set_message(\&handle_errors); }
So far so good, except that this approach hopes that the HTTP header has already been created, and it bypasses the object methods supplied by CGI.pm. The O'Reilly book, "CGI Programming with Perl, 2nd ed." has a slightly different version of the above code snippet. This one is made to interact with the CGI object from CGI.pm:
use CGI; use CGI::Carp qw(fatalsToBrowser); BEGIN { sub carp_error { my $error_message = shift; my $q = new CGI; print $q->start_html( "Error" ), $q->h1( "Error" ), $q->p( "Sorry, the following error occurred: " ), $q->p( $q->i( $error_message ) ), $q->end_html; } CGI::Carp::set_message( \&carp_error ); }
But this example still only hopes that the HTTP header was created, and itself creates a couple of problems. One is probably just a style issue, and the other a header issue. First the style issue. Does it really make sense in this context to create a new CGI object (possibly in addition to the object already being used within the main portion of the CGI script)? Clearly the BEGIN block runs before the main script's CGI object is created, but the "carp_error" routine is going to create a new CGI object every time it tries to carp an error to the browser. What issues could arise out of the creation of multiple CGI objects within the same script?
CGI.pm's POD (perlman:lib:CGI) doesn't warn against using multiple objects. But I suspect that both the carp_error CGI object and the main script's CGI object will hold the same parameter list since neither call to 'new CGI' explicitly passes any other parameter list. That right there could be an issue, since both would be capable of tinkering with the parameters that came in upon invocation of the script. Do modifications to one CGI object's parameters affect those of another CGI object, if they both are the result of the same GET/POST action?
The next issue was that of multiple HTTP headers possibly being generated. The 'textbook' solution was to not print a CGI header. But that's a less than ideal solution. CGI.pm has a safeguard against multiple headers being created by turneing on the use CGI qw( -unique_headers ); option. However my experience is that the "-unique_headers" option only prevents against multiple headers being generated for the same object. As already mentioned, the CGI book's example might have multiple objects created.
In thinking about it I came up with this workaround; a hybred of the various examples from books, CGI::Carp POD, and CGI.pm POD.
#!/usr/bin/perl -T use strict; use warnings; use CGI qw( -headers_once ); use CGI::Carp qw( fatalsToBrowser ); my $q; # The CGI object will get file scope. BEGIN { $q = new CGI; # Construct the CGI object # within the BEGIN block. sub carp_error { my $error_message = shift; print $q->header( "text/html" ), $q->start_html( "Error" ), $q->h1( "Error" ), $q->p( "Sorry, the following error occurred: " ), $q->p( $q->i( $error_message ) ), $q->end_html; } CGI::Carp::set_message( \&carp_error ); }
However, this solution has another problem. The CGI object is passed into 'carp_error' as a global variable rather than as an object reference. That means that the object always has to be called $q, or the 'carp_error' routine will be trying to use a non-existant CGI object. And besides, it just seems like a kludgy solution.
Ideally 'carp_error' or 'handle_errors' (whatever you choose to call your Carp error handler) would have the ability to take a parameter in addition to the one that CGI::Carp passes to it; a parameter holding a reference to the main CGI object.
I'd like to hear what others are using who have spent a lot more time down the CGI development road than I.
Thanks for any input!
Dave
In reply to Proper use of CGI::Carp together with CGI.pm by davido
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |