⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch05_05.htm

📁 用perl编写CGI的好书。本书从解释CGI和底层HTTP协议如何工作开始
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<?label 5.5. Handling Errors?><html><head><title>Handling Errors (CGI Programming with Perl)</title><link href="../style/style1.css" type="text/css" rel="stylesheet" /><meta name="DC.Creator" content="Scott Guelich, Gunther Birznieks and Shishir Gundavaram" /><meta scheme="MIME" content="text/xml" name="DC.Format" /><meta content="en-US" name="DC.Language" /><meta content="O'Reilly & Associates, Inc." name="DC.Publisher" /><meta scheme="ISBN" name="DC.Source" content="1565924193L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="CGI Programming with Perl" /><meta content="Text.Monograph" name="DC.Type" /></head><body bgcolor="#ffffff"><img src="gifs/smbanner.gif" alt="Book Home" usemap="#banner-map" border="0" /><map name="banner-map"><area alt="CGI Programming with Perl" href="index.htm" coords="0,0,466,65" shape="rect" /><area alt="Search this book" href="jobjects/fsearch.htm" coords="467,0,514,18" shape="rect" /></map><div class="navbar"><table border="0" width="515"><tr><td width="172" valign="top" align="left"><a href="ch05_04.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0" /></a></td><td width="171" valign="top" align="center"><a href="index.htm">CGI Programming with Perl</a></td><td width="172" valign="top" align="right"><a href="ch06_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0" /></a></td></tr></table></div><hr align="left" width="515" /><h2 class="sect1">5.5. Handling Errors</h2><p>While we are on the subject of handling <a name="INDEX-1192" /><a name="INDEX-1193" />output,we should also look at handling errors. One of the things thatdistinguishes an experienced developer from a novice is adequateerror handling. Novices expect things to always work as planned;experienced developers have learned otherwise.</p><a name="ch05-27-fm2xml" /><div class="sect2"><h3 class="sect2">5.5.1. Dying Gracefully</h3><p>The most common method that Perl developers use for handling errorsis Perl's built-in<tt class="function">die</tt><a name="INDEX-1194" /> function. Here is an example:</p><blockquote><pre class="code">open FILE, $filename or die "Cannot open $filename: $!";</pre></blockquote><p>If Perl is unable to open the file specified by<tt class="literal">$filename</tt>, <tt class="function">die</tt> will print anerror message to STDERR and terminate the script. The<tt class="function">open</tt> function, like most Perl commands thatinteract with the system, sets <tt class="literal">$!</tt> to the reasonfor the error if it fails.</p><p>Unfortunately, <tt class="function">die</tt> is not always the bestsolution for handling errors in your CGI scripts. As you will recallfrom <a href="ch03_01.htm">Chapter 3, "The Common Gateway Interface"</a>, output to STDERR is typically sentto the web server's error log, triggering the web server toreturn a <em class="emphasis">500 Internal ServerError</em><a name="INDEX-1195" /> <a name="INDEX-1,196" />. This is certainly not a veryuser-friendly response.</p><p>You should determine a policy for handling errors on your site. Youmay decide that <em class="emphasis">500 Internal Server Error</em> pages are acceptable forvery uncommon system errors like the inability to read or write tofiles. However, you may decide that you wish to display a formattedHTML page instead with information for users such as alternativeactions they can take or who to notify about the problem.</p><a name="ch05-28-fm2xml" /><div class="sect3"><h3 class="sect3">5.5.1.1. Trapping die</h3><p>It is possible to trap <a name="INDEX-1197" /><a name="INDEX-1198" /><a name="INDEX-1199" /><tt class="function">die</tt> so that it does notgenerate a <em class="emphasis">500 Internal Server Error</em> automatically. This isespecially useful because many common third-party modules use<tt class="function">die</tt> (and variants such as<tt class="function">croak</tt>) as their manner for responding to errors.If you know that a particular subroutine may call<tt class="function">die</tt>, you can catch this with an<tt class="function">eval</tt> block in Perl:</p><blockquote><pre class="code">eval {    dangerous_routine(  );    1;} or do {    error( $q, $@ || "Unknown error" );};</pre></blockquote><p>If <tt class="function">dangerous_routine</tt> does call<tt class="function">die</tt>, then <tt class="function">eval</tt> will catchit, set the special variable <tt class="literal">$@</tt> to the value ofthe <tt class="function">die</tt> message, pass control to the end of theblock, and return <tt class="literal">undef</tt>. This allows us to callanother subroutine to display our error more gracefully. Note that an<tt class="function">eval</tt> block will not trap<tt class="function">exit</tt>.</p><p>This works, but it certainly makes your code a lot more complex, andif your CGI script interacts with a lot of subroutines that might<tt class="function">die</tt>, then you must either place your entirescript within an <tt class="function">eval</tt> block or include lots ofthese blocks throughout your script.</p><p>Fortunately, there is a better way. You may already know that it ispossible to create a global signal handler to trap Perl's<tt class="function">die</tt> and <tt class="function">warn</tt> functions.This involves some rather advanced Perl; you can find specificinformation in <em class="citetitle">Programming Perl</em>. Fortunately,we don't have to worry about the specifics, because there is amodule that not only does this, but is written specifically for CGIscripts: CGI::Carp.</p></div></div><a name="ch05-29-fm2xml" /><div class="sect2"><h3 class="sect2">5.5.2. CGI::Carp</h3><p><a name="INDEX-1200" /><a name="INDEX-1201" />CGI::Carp is not partof the CGI.pm module, but it is also by Lincoln Stein, and it isdistributed with CGI.pm (and thus included with the most recentversions of Perl). It does two things: it creates more informativeentries in your error log, and it allows you to create a custom errorpage for fatal calls like <tt class="function">die</tt>. Simply by usingthe module, it adds a timestamp and the name of the running CGIscript to errors written to the error log by<tt class="function">die</tt><a name="INDEX-1202" />, <tt class="function">warn</tt>,<tt class="function">carp</tt>, <tt class="function">croak</tt>, and<tt class="function">confess</tt>. The last three functions are providedby the Carp module (included with Perl) and are often used by moduleauthors.</p><p>This still does not stop your web server from displaying<a name="INDEX-1203" /><em class="emphasis">500Internal Server Error</em> responses for these calls, however. CGI::Carpis most useful when you ask it to trap fatal calls. You can have itdisplay <a name="INDEX-1204" />fatal error messages in the<a name="INDEX-1205" />browser instead. This isespecially helpful during development and debugging. To do this,simply pass the <tt class="literal">fatalsToBrowser</tt> parameter to itwhen you use the module:</p><blockquote><pre class="code">use CGI::Carp qw( fatalsToBrowser );</pre></blockquote><p>In a production environment, you may not want<a name="INDEX-1206" />users to view your full errorinformation if they encounter an error. Fortunately, you can haveCGI::Carp trap errors and display your own custom error message. Todo this, you pass<em class="emphasis">CGI::Carp::set_message</em><a name="INDEX-1207" /> areference to a subroutine that takes a single argument and displaysthe content of a response.</p><blockquote><pre class="code">use CGI::Carp qw( fatalsToBrowser );BEGIN {    sub carp_error {        my $error_message = shift;        my $q = new CGI;          $q-&gt;start_html( "Error" ),          $q-&gt;h1( "Error" ),          $q-&gt;p( "Sorry, the following error has occurred: " );          $q-&gt;p( $q-&gt;i( $error_message ) ),          $q-&gt;end_html;    }    CGI::Carp::set_message( \&amp;carp_error );}</pre></blockquote><p>We will see how to incorporate this into a more general solutionlater in <a href="ch05_05.htm#ch05-67677">Example 5-3</a>.</p></div><a name="ch05-30-fm2xml" /><div class="sect2"><h3 class="sect2">5.5.3. Error Subroutines</h3><p>Most of our examples up to now and throughout the book includesubroutines or blocks of code for displaying<a name="INDEX-1208" /><a name="INDEX-1209" /><a name="INDEX-1210" />errors. Here is anexample:</p><blockquote><pre class="code">sub error {    my( $q, $error_message ) = shift;        print $q-&gt;header( "text/html" ),          $q-&gt;start_html( "Error" ),          $q-&gt;h1( "Error" ),          $q-&gt;p( "Sorry, the following error has occurred: " );          $q-&gt;p( $q-&gt;i( $error_message ) ),          $q-&gt;end_html;    exit;}</pre></blockquote><p>You can call this with a<a name="INDEX-1211" />CGI objectand a reason for the error. It will output an error page and thenexit in order to stop executing your script. Note that we<a name="INDEX-1212" />print the<a name="INDEX-1213" />HTTP header here. One of thebiggest challenges in creating a general solution for catching errorsis knowing whether or not to print an HTTP header: if one has alreadybeen printed and you print another, it will appear at the top of yourerror page; if one has not been printed and you do not print one aspart of the error message, you will trigger a <em class="emphasis">500 InternalServer Error</em><a name="INDEX-1214" /> instead.</p><p>Fortunately, CGI.pm has a feature that will track whether a headerhas been printed for you already. If you enable this feature, it willonly output an HTTP header once per CGI object. Any future calls to<tt class="function">header</tt> will silently do nothing. You can enable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -