1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 4<html xmlns="http://www.w3.org/1999/xhtml"> 5 <head> 6 <meta name="generator" content="HTML Tidy, see www.w3.org" /> 7 8 <title>International Customized Server Error Messages</title> 9 </head> 10 <!-- Background white, links blue (unvisited), navy (visited), red (active) --> 11 12 <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" 13 vlink="#000080" alink="#FF0000"> 14 <div align="CENTER"> 15 <img src="../images/sub.gif" alt="[APACHE DOCUMENTATION]" /> 16 17 <h3>Apache HTTP Server Version 1.3</h3> 18 </div> 19 20 21 <h1 align="CENTER">Using XSSI and <samp>ErrorDocument</samp> to 22 configure customized international server error responses</h1> 23 24 <h2>Index</h2> 25 26 <ul> 27 <li><a href="#intro">Introduction</a></li> 28 29 <li><a href="#createdir">Creating an ErrorDocument 30 directory</a></li> 31 32 <li><a href="#docnames">Naming the individual error document 33 files</a></li> 34 35 <li><a href="#headfoot">The common header and footer 36 files</a></li> 37 38 <li><a href="#createdocs">Creating ErrorDocuments in 39 different languages</a></li> 40 41 <li><a href="#fallback">The fallback language</a></li> 42 43 <li><a href="#proxy">Customizing Proxy Error 44 Messages</a></li> 45 46 <li><a href="#listings">HTML listing of the discussed 47 example</a></li> 48 </ul> 49 <hr /> 50 51 <h2><a id="intro" name="intro">Introduction</a></h2> 52 53 <p>This document describes an easy way to provide your apache 54 WWW server with a set of customized error messages which take 55 advantage of <a href="../content-negotiation.html">Content 56 Negotiation</a> and <a href="../mod/mod_include.html">eXtended 57 Server Side Includes (XSSI)</a> to return error messages 58 generated by the server in the client's native language.</p> 59 60 <p>By using XSSI, all <a 61 href="../mod/core.html#errordocument">customized messages</a> 62 can share a homogenous and consistent style and layout, and 63 maintenance work (changing images, changing links) is kept to a 64 minimum because all layout information can be kept in a single 65 file.<br /> 66 Error documents can be shared across different servers, or 67 even hosts, because all varying information is inserted at the 68 time the error document is returned on behalf of a failed 69 request.</p> 70 71 <p>Content Negotiation then selects the appropriate language 72 version of a particular error message text, honoring the 73 language preferences passed in the client's request. (Users 74 usually select their favorite languages in the preferences 75 options menu of today's browsers). When an error document in 76 the client's primary language version is unavailable, the 77 secondary languages are tried or a default (fallback) version 78 is used.</p> 79 80 <p>You have full flexibility in designing your error documents 81 to your personal taste (or your company's conventions). For 82 demonstration purposes, we present a simple generic error 83 document scheme. For this hypothetic server, we assume that all 84 error messages...</p> 85 86 <ul> 87 <li>possibly are served by different virtual hosts (different 88 host name, different IP address, or different port) on the 89 server machine,</li> 90 91 <li>show a predefined company logo in the right top of the 92 message (selectable by virtual host),</li> 93 94 <li>print the error title first, followed by an explanatory 95 text and (depending on the error context) help on how to 96 resolve the error,</li> 97 98 <li>have some kind of standardized background image,</li> 99 100 <li>display an apache logo and a feedback email address at 101 the bottom of the error message.</li> 102 </ul> 103 104 <p>An example of a "document not found" message for a german 105 client might look like this:<br /> 106 <img src="../images/custom_errordocs.gif" 107 alt="[Needs graphics capability to display]" /><br /> 108 All links in the document as well as links to the server's 109 administrator mail address, and even the name and port of the 110 serving virtual host are inserted in the error document at 111 "run-time", <em>i.e.</em>, when the error actually occurs.</p> 112 113 <h2><a id="createdir" name="createdir">Creating an 114 ErrorDocument directory</a></h2> 115 For this concept to work as easily as possible, we must take 116 advantage of as much server support as we can get: 117 118 <ol> 119 <li>By defining the <a 120 href="../mod/core.html#options">MultiViews option</a>, we 121 enable the language selection of the most appropriate 122 language alternative (content negotiation).</li> 123 124 <li>By setting the <a 125 href="../mod/mod_negotiation.html#languagepriority">LanguagePriority</a> 126 directive we define a set of default fallback languages in 127 the situation where the client's browser did not express any 128 preference at all.</li> 129 130 <li>By enabling <a href="../mod/mod_include.html">Server Side 131 Includes</a> (and disallowing execution of cgi scripts for 132 security reasons), we allow the server to include building 133 blocks of the error message, and to substitute the value of 134 certain environment variables into the generated document 135 (dynamic HTML) or even to conditionally include or omit parts 136 of the text.</li> 137 138 <li>The <a 139 href="../mod/mod_mime.html#addhandler">AddHandler</a> and <a 140 href="../mod/mod_mime.html#addtype">AddType</a> directives 141 are useful for automatically XSSI-expanding all files with a 142 <samp>.shtml</samp> suffix to <em>text/html</em>.</li> 143 144 <li>By using the <a 145 href="../mod/mod_alias.html#alias">Alias</a> directive, we 146 keep the error document directory outside of the document 147 tree because it can be regarded more as a server part than 148 part of the document tree.</li> 149 150 <li>The <a 151 href="../mod/core.html#directory"><Directory></a>-Block 152 restricts these "special" settings to the error document 153 directory and avoids an impact on any of the settings for the 154 regular document tree.</li> 155 156 <li>For each of the error codes to be handled (see RFC2068 157 for an exact description of each error code, or look at 158 <code>src/main/http_protocol.c</code> if you wish to see 159 apache's standard messages), an <a 160 href="../mod/core.html#errordocument">ErrorDocument</a> in 161 the aliased <samp>/errordocs</samp> directory is defined. 162 Note that we only define the basename of the document here 163 because the MultiViews option will select the best candidate 164 based on the language suffixes and the client's preferences. 165 Any error situation with an error code <em>not</em> handled 166 by a custom document will be dealt with by the server in the 167 standard way (<em>i.e.</em>, a plain error message in 168 english).</li> 169 170 <li>Finally, the <a 171 href="../mod/core.html#allowoverride">AllowOverride</a> 172 directive tells apache that it is not necessary to look for a 173 .htaccess file in the /errordocs directory: a minor speed 174 optimization.</li> 175 </ol> 176 The resulting <samp>httpd.conf</samp> configuration would then 177 look similar to this: <small>(Note that you can define your own 178 error messages using this method for only part of the document 179 tree, e.g., a /~user/ subtree. In this case, the configuration 180 could as well be put into the .htaccess file at the root of the 181 subtree, and the <Directory> and </Directory> 182 directives -but not the contained directives- must be 183 omitted.)</small> 184<pre> 185 LanguagePriority en fr de 186 Alias /errordocs /usr/local/apache/errordocs 187 <Directory /usr/local/apache/errordocs> 188 AllowOverride none 189 Options MultiViews IncludesNoExec FollowSymLinks 190 AddType text/html .shtml 191 AddHandler server-parsed .shtml 192 </Directory> 193 # "400 Bad Request", 194 ErrorDocument 400 /errordocs/400 195 # "401 Authorization Required", 196 ErrorDocument 401 /errordocs/401 197 # "403 Forbidden", 198 ErrorDocument 403 /errordocs/403 199 # "404 Not Found", 200 ErrorDocument 404 /errordocs/404 201 # "500 Internal Server Error", 202 ErrorDocument 500 /errordocs/500 203</pre> 204 The directory for the error messages (here: 205 <samp>/usr/local/apache/errordocs/</samp>) must then be created 206 with the appropriate permissions (readable and executable by 207 the server uid or gid, only writable for the administrator). 208 209 <h3><a id="docnames" name="docnames">Naming the individual 210 error document files</a></h3> 211 By defining the <samp>MultiViews</samp> option, the server was 212 told to automatically scan the directory for matching variants 213 (looking at language and content type suffixes) when a 214 requested document was not found. In the configuration, we 215 defined the names for the error documents to be just their 216 error number (without any suffix). 217 218 <p>The names of the individual error documents are now 219 determined like this (I'm using 403 as an example, think of it 220 as a placeholder for any of the configured error 221 documents):</p> 222 223 <ul> 224 <li>No file errordocs/403 should exist. Otherwise, it would 225 be found and served (with the DefaultType, usually 226 text/plain), all negotiation would be bypassed.</li> 227 228 <li>For each language for which we have an internationalized 229 version (note that this need not be the same set of languages 230 for each error code - you can get by with a single language 231 version until you actually <em>have</em> translated 232 versions), a document 233 <samp>errordocs/403.shtml.<em>lang</em></samp> is created and 234 filled with the error text in that language (<a 235 href="#createdocs">see below</a>).</li> 236 237 <li>One fallback document called 238 <samp>errordocs/403.shtml</samp> is created, usually by 239 creating a symlink to the default language variant (<a 240 href="#fallback">see below</a>).</li> 241 </ul> 242 243 <h3><a id="headfoot" name="headfoot">The common header and 244 footer files</a></h3> 245 By putting as much layout information in two special "include 246 files", the error documents can be reduced to a bare minimum. 247 248 <p>One of these layout files defines the HTML document header 249 and a configurable list of paths to the icons to be shown in 250 the resulting error document. These paths are exported as a set 251 of XSSI environment variables and are later evaluated by the 252 "footer" special file. The title of the current error (which is 253 put into the TITLE tag and an H1 header) is simply passed in 254 from the main error document in a variable called 255 <code>title</code>.<br /> 256 <strong>By changing this file, the layout of all generated 257 error messages can be changed in a second.</strong> (By 258 exploiting the features of XSSI, you can easily define 259 different layouts based on the current virtual host, or even 260 based on the client's domain name).</p> 261 262 <p>The second layout file describes the footer to be displayed 263 at the bottom of every error message. In this example, it shows 264 an apache logo, the current server time, the server version 265 string and adds a mail reference to the site's webmaster.</p> 266 267 <p>For simplicity, the header file is simply called 268 <code>head.shtml</code> because it contains server-parsed 269 content but no language specific information. The footer file 270 exists once for each language translation, plus a symlink for 271 the default language.</p> 272 273 <p><strong>Example:</strong> for English, French and German 274 versions (default english)<br /> 275 <code>foot.shtml.en</code>,<br /> 276 <code>foot.shtml.fr</code>,<br /> 277 <code>foot.shtml.de</code>,<br /> 278 <code>foot.shtml</code> symlink to 279 <code>foot.shtml.en</code></p> 280 281 <p>Both files are included into the error document by using the 282 directives <code><!--#include virtual="head" --></code> 283 and <code><!--#include virtual="foot" --></code> 284 respectively: the rest of the magic occurs in mod_negotiation 285 and in mod_include.</p> 286 287 <p>See <a href="#listings">the listings below</a> to see an 288 actual HTML implementation of the discussed example.</p> 289 290 <h3><a id="createdocs" name="createdocs">Creating 291 ErrorDocuments in different languages</a></h3> 292 After all this preparation work, little remains to be said 293 about the actual documents. They all share a simple common 294 structure: 295<pre> 296<!--#set var="title" value="<em>error description title</em>" --> 297<!--#include virtual="head" --> 298 <em>explanatory error text</em> 299<!--#include virtual="foot" --> 300</pre> 301 In the <a href="#listings">listings section</a>, you can see an 302 example of a [400 Bad Request] error document. Documents as 303 simple as that certainly cause no problems to translate or 304 expand. 305 306 <h3><a id="fallback" name="fallback">The fallback 307 language</a></h3> 308 Do we need a special handling for languages other than those we 309 have translations for? We did set the LanguagePriority, didn't 310 we?! 311 312 <p>Well, the LanguagePriority directive is for the case where 313 the client does not express any language priority at all. But 314 what happens in the situation where the client wants one of the 315 languages we do not have, and none of those we do have?</p> 316 317 <p>Without doing anything, the Apache server will usually 318 return a [406 no acceptable variant] error, listing the choices 319 from which the client may select. But we're in an error message 320 already, and important error information might get lost when 321 the client had to choose a language representation first.</p> 322 323 <p>So, in this situation it appears to be easier to define a 324 fallback language (by copying or linking, <em>e.g.</em>, the 325 english version to a language-less version). Because the 326 negotiation algorithm prefers "more specialized" variants over 327 "more generic" variants, these generic alternatives will only 328 be chosen when the normal negotiation did not succeed.</p> 329 330 <p>A simple shell script to do it (execute within the 331 errordocs/ dir):</p> 332<pre> 333 for f in *.shtml.en 334 do 335 ln -s $f `basename $f .en` 336 done 337</pre> 338 339 <h2><a id="proxy" name="proxy">Customizing Proxy Error 340 Messages</a></h2> 341 342 <p>As of Apache-1.3, it is possible to use the 343 <code>ErrorDocument</code> mechanism for proxy error messages 344 as well (previous versions always returned fixed predefined 345 error messages).</p> 346 347 <p>Most proxy errors return an error code of [500 Internal 348 Server Error]. To find out whether a particular error document 349 was invoked on behalf of a proxy error or because of some other 350 server error, and what the reason for the failure was, you can 351 check the contents of the new <code>ERROR_NOTES</code> CGI 352 environment variable: if invoked for a proxy error, this 353 variable will contain the actual proxy error message text in 354 HTML form.</p> 355 356 <p>The following excerpt demonstrates how to exploit the 357 <code>ERROR_NOTES</code> variable within an error document:</p> 358<pre> 359 <!--#if expr="$REDIRECT_ERROR_NOTES = ''" --> 360 <p> 361 The server encountered an unexpected condition 362 which prevented it from fulfilling the request. 363 </p> 364 <p> 365 <A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->" 366 SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->"> 367 Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s 368 WebMaster</A>; it includes useful debugging information about 369 the Request which caused the error. 370 <pre><!--#printenv --></pre> 371 </p> 372 <!--#else --> 373 <!--#echo var="REDIRECT_ERROR_NOTES" --> 374 <!--#endif --> 375</pre> 376 377 <h2><a id="listings" name="listings">HTML listing of the 378 discussed example</a></h2> 379 So, to summarize our example, here's the complete listing of 380 the <samp>400.shtml.en</samp> document. You will notice that it 381 contains almost nothing but the error text (with conditional 382 additions). Starting with this example, you will find it easy 383 to add more error documents, or to translate the error 384 documents to different languages. 385 <hr /> 386<pre> 387<!--#set var="title" value="Bad Request" 388--><!--#include virtual="head" --><P> 389 Your browser sent a request that this server could not understand: 390 <BLOCKQUOTE> 391 <STRONG><!--#echo var="REQUEST_URI" --></STRONG> 392 </BLOCKQUOTE> 393 The request could not be understood by the server due to malformed 394 syntax. The client should not repeat the request without 395 modifications. 396 </P> 397 <P> 398 <!--#if expr="$HTTP_REFERER != ''" --> 399 Please inform the owner of 400 <A HREF="<!--#echo var="HTTP_REFERER" -->">the referring page</A> about 401 the malformed link. 402 <!--#else --> 403 Please check your request for typing errors and retry. 404 <!--#endif --> 405 </P> 406<!--#include virtual="foot" --> 407</pre> 408 <hr /> 409 Here is the complete <samp>head.shtml</samp> file (the funny 410 line breaks avoid empty lines in the document after XSSI 411 processing). Note the configuration section at top. That's 412 where you configure the images and logos as well as the apache 413 documentation directory. Look how this file displays two 414 different logos depending on the content of the virtual host 415 name ($SERVER_NAME), and that an animated apache logo is shown 416 if the browser appears to support it (the latter requires 417 server configuration lines of the form <br /> 418 <code>BrowserMatch "^Mozilla/[2-4]" anigif</code><br /> 419 for browser types which support animated GIFs). 420 <hr /> 421<pre> 422<!--#if expr="$SERVER_NAME = /.*\.mycompany\.com/" 423--><!--#set var="IMG_CorpLogo" 424 value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" 425--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 426--><!--#else 427--><!--#set var="IMG_CorpLogo" 428 value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" 429--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 430--><!--#endif 431--><!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" 432--><!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" 433--><!--#if expr="$anigif" 434--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" 435--><!--#else 436--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" 437--><!--#endif 438--><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> 439<HTML> 440 <HEAD> 441 <TITLE> 442 [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> 443 </TITLE> 444 </HEAD> 445 <BODY BGCOLOR="white" BACKGROUND="<!--#echo var="IMG_BgImage" -->"><UL> 446 <H1 ALIGN="center"> 447 [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> 448 <IMG SRC="<!--#echo var="IMG_CorpLogo" -->" 449 ALT="<!--#echo var="ALT_CorpLogo" -->" ALIGN=right> 450 </H1> 451 <HR><!-- ======================================================== --> 452 <DIV> 453</pre> 454 <hr /> 455 and this is the <samp>foot.shtml.en</samp> file: 456 <hr /> 457<pre> 458 </DIV> 459 <HR> 460 <DIV ALIGN="right"><SMALL><SUP>Local Server time: 461 <!--#echo var="DATE_LOCAL" --> 462 </SUP></SMALL></DIV> 463 <DIV ALIGN="center"> 464 <A HREF="<!--#echo var="DOC_Apache" -->"> 465 <IMG SRC="<!--#echo var="IMG_Apache" -->" BORDER=0 ALIGN="bottom" 466 ALT="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></A><BR> 467 <SMALL><SUP><!--#set var="var" 468 value="Powered by $SERVER_SOFTWARE -- File last modified on $LAST_MODIFIED" 469 --><!--#echo var="var" --></SUP></SMALL> 470 </DIV> 471 <ADDRESS>If the indicated error looks like a misconfiguration, please inform 472 <A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->" 473 SUBJECT="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" 474 -->] <!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->"> 475 <!--#echo var="SERVER_NAME" -->'s WebMaster</A>. 476 </ADDRESS> 477 </UL></BODY> 478</HTML> 479</pre> 480 <hr /> 481 482 <h3>More welcome!</h3> 483 If you have tips to contribute, send mail to <a 484 href="mailto:martin@apache.org">martin@apache.org</a> 485 <hr /> 486 487 <h3 align="CENTER">Apache HTTP Server Version 1.3</h3> 488 <a href="./"><img src="../images/index.gif" alt="Index" /></a> 489 <a href="../"><img src="../images/home.gif" alt="Home" /></a> 490 491 </body> 492</html> 493 494