Re: CGI Error Handling
by davorg (Chancellor) on Dec 10, 2001 at 15:17 UTC
|
I think it's important to differentiate between the
different types of errors that you're handling. For errors
that are caused by invalid user input, it's a good idea
to create an error page that tells them what to correct in
their input - probably including the current input you've
got and pointing out what needs to be fixed.
For anything that is outside of the user's control
(missing files on the server, invalid permissions, that
kind of thing) I think that it's a waste of time creating
clever error reporting pages. You're probably not going to
give the user any information that will mean anything to
him than the default web server error page and you run the risk of giving a passing cracker too much information.
The "vanilla" 500 Error page is fine for most purposes. Of course, there's nothing to stop you replacing it with another that better reflects the look and feel of your site.
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] |
|
eval {
#any code in here
yourSub();
}
if ($@){
# $@ contains err message if error occurs
warn " continue with script but there has been an erro $@ \n";
#run error handling routine
ErrorHandle();
}
The average user finds a standard Apache error page v scary so I try and make an error doc for every error possible.
ErrorDocument 404 /missing.html
ErrorDocument 401 /auth_error.html
Update amended to consider below
| [reply] [d/l] [select] |
|
Two important pieces of advice.
The first is to pick an
indentation style indenting between 2-4 spaces, and then
start using it. Now. Running your code through
perltidy will show
you what it looks like.
The second is to call functions with explicit parameters.
That means using parens. As documented in perlsub, if you
use just the plain & and in
a function you call another function, that other function
will get the parameters to the first as arguments.
Believe me. You may think these are picky details. But
they are not. The first strongly impacts how easy it is
to pick out your logic at a glance. The second is causing
a subtle set of side-effects that may or may not be
intended which a maintainance programmer may or may not
know enough to notice.
| [reply] |
|
Re: CGI Error Handling
by giulienk (Curate) on Dec 10, 2001 at 14:57 UTC
|
I don't know your exact needs but i think you should check out CGI::Carp module. use CGI::Carp qw(fatalsToBrowser);
die "Error! $error" if ($error);
This output the error to the browser in a pretty way.
gkinueliileunikg | [reply] [d/l] |
|
Whilst this is great to use when you're developing a
script, I wouldn't advise using it in production code. This
is because the error messages that it gives can be a source
of useful information for anyone trying to crack your site.
In some cases, just knowing that you've got Perl installed
on you server can give crackers a head start.
Error messages like this belong in the server error
log where the webmaster can read them. There's a good
reason why Apache gives a plain 500 error page by
default.
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] |
|
It almost sounds like you're warning people away from using CGI::Carp entirely. (You probably aren't, but I wanted to post this for the benefit of other readers that might also be confused.) It's mainly the fatalsToBrowser and warningsToBrowser bits that we don't want to see in production code. CGI::Carp's primary purpose is to format out nice, debug-friendly error messages in your server's error logs, so I definitely recommend its use even in production code.
| [reply] [d/l] [select] |
|
Thanks for the hint, but CGI::Carp is out of the question. I need something that produces an errorpage in the same style as the application ist.
| [reply] |
|
CGI::Carp can easily be told to use your own template or function for generating the error message to the user. Check out the documentation for specifics.
| [reply] |
Re: CGI Error Handling
by Lucky (Scribe) on Dec 10, 2001 at 17:13 UTC
|
The simplest way to handle errors is eval block.
It acts like java try{}catch{} statement.
For example:
eval{ ...code...};
if ($@) { handle error }
For complex error handling Error.pm module exists. It's very useful for
scripts with an object-oriented structure.
Example:
use Error;
try{
do something...
}catch Error::Simple with{
handling...
}finally{
...
}
Looks like Java code :-) | [reply] [d/l] [select] |
|
| [reply] |
Re: CGI Error Handling
by Lucky (Scribe) on Dec 10, 2001 at 16:48 UTC
|
There is one useful package in Perl standard library - CGI::Carp.
It will help you to redirect ALL errors and warnings to your
own log file.
BEGIN{
use CGI::Carp qw(carpout);
open LOG, $logfile or die "Couldn't open log file: $!";
carpout(LOG);
}
see also 'man CGI::Carp'; | [reply] [d/l] |
Re: CGI Error Handling
by bmccoy (Beadle) on Dec 10, 2001 at 16:56 UTC
|
A lot depends on the error -- an application level error (bad user input, unavailable resource, etc) I usually handle with my own exception handling routines. Fatal exceptions I usually dump into the web server using somehting like CGI::Carp. It also lets you print error messages to the browser screen, but this shouldn't be done for a production, just as a debugging tool.
-- Brett
Go not to the Elves for counsel, for they will say both no and yes | [reply] |
|
I mean application level error. How does your own exception handling routine look like?
I usually write a database-abstraction-layer (and plan to write a general modul for this purpose). I'm not sure how I should handle errors that occur in this layer. Should the script specify an error template and the database-layers shows this page if an error occurs? Or should the database-layer only return a false value and stores the errortext/-code in a datastructure? The script then can retrieve this errortext and prints the errortemplate.
| [reply] |
Re: CGI Error Handling
by edebill (Scribe) on Dec 10, 2001 at 22:34 UTC
|
One thing to keep in mind is the difference between development/debugging error messages, and the user friendly error messages that should be displayed to actual users. Most users don't know what to do with a stack trace or a DBI error message - and as someone else already mentioned, that can be a security risk. Useability folks will scream if you mention anything technical in an error message.
On the other hand, carp, die() and company are your friends during dev.
I like to wrap most everything in eval{} blocks so that major errors can be wrapped with user friendly text, and uses UNIX::Syslog to log error messages. This gives me the chance to grab the $DBI::errst which typically has some great debug info in it for db errors.
This works great for production, but we tend to leave the eval{}'s out while first coding something - verbose error messages are a big help while debugging. Unfortunately, doing anything as a two pass operation means sometimes the eval{}'s don't get added before it goes to production.
| [reply] |
|
I like the idea of putting code in eval-blocks, but is this also efficient/state-of-the-art/perlish?
eval {
open(FH, $file) or die "NO_OPEN";
$text = join('', <FH>) or die "NO_READ";
close(FH) or die "NO_CLOSE";
}
if ($@) { ... }
instead of
open(FH, $file) or &error("NO_OPEN", $file, $!);
my $text = join('', <FH>) or &error("NO_READ", $file, $!);
close(FH) or &error("NO_CLOSE", $file, $!);
What approach do you find better? | [reply] [d/l] [select] |
|
| [reply] |
|
In your example, the second option is actually more readable. But if the function call on the left is longer, and you start wrapping things will get pretty ugly. What's more, if you do something like $sth->execute and the transaction fails (e.g. from bad SQL or an RI constraint) $sth->execute will call die() for you - and an eval block is the only way to catch it.
I prefer to use the same method for something every time - so I go for nothing but eval blocks. Using two different constructs to do the same thing in the same bit of software just makes things harder to maintain. YMMV.
| [reply] |