mirror of
https://github.com/apache/httpd.git
synced 2025-06-06 09:01:00 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@96194 13f79535-47bb-0310-9956-ffa450edef68
490 lines
20 KiB
HTML
490 lines
20 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta name="generator" content="HTML Tidy, see www.w3.org" />
|
|
|
|
<title>International Customized Server Error Messages</title>
|
|
</head>
|
|
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
|
|
|
|
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
|
vlink="#000080" alink="#FF0000">
|
|
<!--#include virtual="header.html" -->
|
|
|
|
<h1 align="center">Using XSSI and <samp>ErrorDocument</samp> to
|
|
configure customized international server error responses</h1>
|
|
|
|
<h2>Index</h2>
|
|
|
|
<ul>
|
|
<li><a href="#intro">Introduction</a></li>
|
|
|
|
<li><a href="#createdir">Creating an ErrorDocument
|
|
directory</a></li>
|
|
|
|
<li><a href="#docnames">Naming the individual error document
|
|
files</a></li>
|
|
|
|
<li><a href="#headfoot">The common header and footer
|
|
files</a></li>
|
|
|
|
<li><a href="#createdocs">Creating ErrorDocuments in
|
|
different languages</a></li>
|
|
|
|
<li><a href="#fallback">The fallback language</a></li>
|
|
|
|
<li><a href="#proxy">Customizing Proxy Error
|
|
Messages</a></li>
|
|
|
|
<li><a href="#listings">HTML listing of the discussed
|
|
example</a></li>
|
|
</ul>
|
|
<hr />
|
|
|
|
<h2><a id="intro" name="intro">Introduction</a></h2>
|
|
This document describes an easy way to provide your apache WWW
|
|
server with a set of customized error messages which take
|
|
advantage of <a href="../content-negotiation.html">Content
|
|
Negotiation</a> and <a href="../mod/mod_include.html">eXtended
|
|
Server Side Includes (XSSI)</a> to return error messages
|
|
generated by the server in the client's native language. <br />
|
|
<br />
|
|
|
|
|
|
<p>By using XSSI, all <a
|
|
href="../mod/core.html#errordocument">customized messages</a>
|
|
can share a homogenous and consistent style and layout, and
|
|
maintenance work (changing images, changing links) is kept to a
|
|
minimum because all layout information can be kept in a single
|
|
file.<br />
|
|
Error documents can be shared across different servers, or
|
|
even hosts, because all varying information is inserted at the
|
|
time the error document is returned on behalf of a failed
|
|
request.</p>
|
|
|
|
<p>Content Negotiation then selects the appropriate language
|
|
version of a particular error message text, honoring the
|
|
language preferences passed in the client's request. (Users
|
|
usually select their favorite languages in the preferences
|
|
options menu of today's browsers). When an error document in
|
|
the client's primary language version is unavailable, the
|
|
secondary languages are tried or a default (fallback) version
|
|
is used.</p>
|
|
|
|
<p>You have full flexibility in designing your error documents
|
|
to your personal taste (or your company's conventions). For
|
|
demonstration purposes, we present a simple generic error
|
|
document scheme. For this hypothetic server, we assume that all
|
|
error messages...</p>
|
|
|
|
<ul>
|
|
<li>possibly are served by different virtual hosts (different
|
|
host name, different IP address, or different port) on the
|
|
server machine,</li>
|
|
|
|
<li>show a predefined company logo in the right top of the
|
|
message (selectable by virtual host),</li>
|
|
|
|
<li>print the error title first, followed by an explanatory
|
|
text and (depending on the error context) help on how to
|
|
resolve the error,</li>
|
|
|
|
<li>have some kind of standardized background image,</li>
|
|
|
|
<li>display an apache logo and a feedback email address at
|
|
the bottom of the error message.</li>
|
|
</ul>
|
|
<br />
|
|
<br />
|
|
|
|
|
|
<p>An example of a "document not found" message for a german
|
|
client might look like this:<br />
|
|
<img src="../images/custom_errordocs.gif"
|
|
alt="[Needs graphics capability to display]" /><br />
|
|
All links in the document as well as links to the server's
|
|
administrator mail address, and even the name and port of the
|
|
serving virtual host are inserted in the error document at
|
|
"run-time", <em>i.e.</em>, when the error actually occurs.</p>
|
|
|
|
<h2><a id="createdir" name="createdir">Creating an
|
|
ErrorDocument directory</a></h2>
|
|
For this concept to work as easily as possible, we must take
|
|
advantage of as much server support as we can get:
|
|
|
|
<ol>
|
|
<li>By defining the <a
|
|
href="../mod/core.html#options">MultiViews option</a>, we
|
|
enable the language selection of the most appropriate
|
|
language alternative (content negotiation).</li>
|
|
|
|
<li>By setting the <a
|
|
href="../mod/mod_negotiation.html#languagepriority">LanguagePriority</a>
|
|
directive we define a set of default fallback languages in
|
|
the situation where the client's browser did not express any
|
|
preference at all.</li>
|
|
|
|
<li>By enabling <a href="../mod/mod_include.html">Server Side
|
|
Includes</a> (and disallowing execution of cgi scripts for
|
|
security reasons), we allow the server to include building
|
|
blocks of the error message, and to substitute the value of
|
|
certain environment variables into the generated document
|
|
(dynamic HTML) or even to conditionally include or omit parts
|
|
of the text.</li>
|
|
|
|
<li>The <a
|
|
href="../mod/mod_mime.html#addhandler">AddHandler</a> and <a
|
|
href="../mod/mod_mime.html#addtype">AddType</a> directives
|
|
are useful for automatically XSSI-expanding all files with a
|
|
<samp>.shtml</samp> suffix to <em>text/html</em>.</li>
|
|
|
|
<li>By using the <a
|
|
href="../mod/mod_alias.html#alias">Alias</a> directive, we
|
|
keep the error document directory outside of the document
|
|
tree because it can be regarded more as a server part than
|
|
part of the document tree.</li>
|
|
|
|
<li>The <a
|
|
href="../mod/core.html#directory"><Directory></a>-Block
|
|
restricts these "special" settings to the error document
|
|
directory and avoids an impact on any of the settings for the
|
|
regular document tree.</li>
|
|
|
|
<li>For each of the error codes to be handled (see RFC2068
|
|
for an exact description of each error code, or look at
|
|
<code>src/main/http_protocol.c</code> if you wish to see
|
|
apache's standard messages), an <a
|
|
href="../mod/core.html#errordocument">ErrorDocument</a> in
|
|
the aliased <samp>/errordocs</samp> directory is defined.
|
|
Note that we only define the basename of the document here
|
|
because the MultiViews option will select the best candidate
|
|
based on the language suffixes and the client's preferences.
|
|
Any error situation with an error code <em>not</em> handled
|
|
by a custom document will be dealt with by the server in the
|
|
standard way (<em>i.e.</em>, a plain error message in
|
|
english).</li>
|
|
|
|
<li>Finally, the <a
|
|
href="../mod/core.html#allowoverride">AllowOverride</a>
|
|
directive tells apache that it is not necessary to look for a
|
|
.htaccess file in the /errordocs directory: a minor speed
|
|
optimization.</li>
|
|
</ol>
|
|
The resulting <samp>httpd.conf</samp> configuration would then
|
|
look similar to this: <small>(Note that you can define your own
|
|
error messages using this method for only part of the document
|
|
tree, e.g., a /~user/ subtree. In this case, the configuration
|
|
could as well be put into the .htaccess file at the root of the
|
|
subtree, and the <Directory> and </Directory>
|
|
directives -but not the contained directives- must be
|
|
omitted.)</small>
|
|
<pre>
|
|
LanguagePriority en fr de
|
|
Alias /errordocs /usr/local/apache/errordocs
|
|
<Directory /usr/local/apache/errordocs>
|
|
AllowOverride none
|
|
Options MultiViews IncludesNoExec FollowSymLinks
|
|
AddType text/html .shtml
|
|
<FilesMatch "\.shtml[.$]">
|
|
SetOutputFilter INCLUDES
|
|
</FilesMatch>
|
|
</Directory>
|
|
# "400 Bad Request",
|
|
ErrorDocument 400 /errordocs/400
|
|
# "401 Authorization Required",
|
|
ErrorDocument 401 /errordocs/401
|
|
# "403 Forbidden",
|
|
ErrorDocument 403 /errordocs/403
|
|
# "404 Not Found",
|
|
ErrorDocument 404 /errordocs/404
|
|
# "500 Internal Server Error",
|
|
ErrorDocument 500 /errordocs/500
|
|
</pre>
|
|
The directory for the error messages (here:
|
|
<samp>/usr/local/apache/errordocs/</samp>) must then be created
|
|
with the appropriate permissions (readable and executable by
|
|
the server uid or gid, only writable for the administrator).
|
|
|
|
<h3><a id="docnames" name="docnames">Naming the individual
|
|
error document files</a></h3>
|
|
By defining the <samp>MultiViews</samp> option, the server was
|
|
told to automatically scan the directory for matching variants
|
|
(looking at language and content type suffixes) when a
|
|
requested document was not found. In the configuration, we
|
|
defined the names for the error documents to be just their
|
|
error number (without any suffix).
|
|
|
|
<p>The names of the individual error documents are now
|
|
determined like this (I'm using 403 as an example, think of it
|
|
as a placeholder for any of the configured error
|
|
documents):</p>
|
|
|
|
<ul>
|
|
<li>No file errordocs/403 should exist. Otherwise, it would
|
|
be found and served (with the DefaultType, usually
|
|
text/plain), all negotiation would be bypassed.</li>
|
|
|
|
<li>For each language for which we have an internationalized
|
|
version (note that this need not be the same set of languages
|
|
for each error code - you can get by with a single language
|
|
version until you actually <em>have</em> translated
|
|
versions), a document
|
|
<samp>errordocs/403.shtml.<em>lang</em></samp> is created and
|
|
filled with the error text in that language (<a
|
|
href="#createdocs">see below</a>).</li>
|
|
|
|
<li>One fallback document called
|
|
<samp>errordocs/403.shtml</samp> is created, usually by
|
|
creating a symlink to the default language variant (<a
|
|
href="#fallback">see below</a>).</li>
|
|
</ul>
|
|
|
|
<h3><a id="headfoot" name="headfoot">The common header and
|
|
footer files</a></h3>
|
|
By putting as much layout information in two special "include
|
|
files", the error documents can be reduced to a bare minimum.
|
|
|
|
<p>One of these layout files defines the HTML document header
|
|
and a configurable list of paths to the icons to be shown in
|
|
the resulting error document. These paths are exported as a set
|
|
of XSSI environment variables and are later evaluated by the
|
|
"footer" special file. The title of the current error (which is
|
|
put into the TITLE tag and an H1 header) is simply passed in
|
|
from the main error document in a variable called
|
|
<code>title</code>.<br />
|
|
<strong>By changing this file, the layout of all generated
|
|
error messages can be changed in a second.</strong> (By
|
|
exploiting the features of XSSI, you can easily define
|
|
different layouts based on the current virtual host, or even
|
|
based on the client's domain name).</p>
|
|
|
|
<p>The second layout file describes the footer to be displayed
|
|
at the bottom of every error message. In this example, it shows
|
|
an apache logo, the current server time, the server version
|
|
string and adds a mail reference to the site's webmaster.</p>
|
|
|
|
<p>For simplicity, the header file is simply called
|
|
<code>head.shtml</code> because it contains server-parsed
|
|
content but no language specific information. The footer file
|
|
exists once for each language translation, plus a symlink for
|
|
the default language.</p>
|
|
|
|
<p><strong>Example:</strong> for English, French and German
|
|
versions (default english)<br />
|
|
<code>foot.shtml.en</code>,<br />
|
|
<code>foot.shtml.fr</code>,<br />
|
|
<code>foot.shtml.de</code>,<br />
|
|
<code>foot.shtml</code> symlink to
|
|
<code>foot.shtml.en</code></p>
|
|
|
|
<p>Both files are included into the error document by using the
|
|
directives <code><!--#include virtual="head" --></code>
|
|
and <code><!--#include virtual="foot" --></code>
|
|
respectively: the rest of the magic occurs in mod_negotiation
|
|
and in mod_include.</p>
|
|
|
|
<p>See <a href="#listings">the listings below</a> to see an
|
|
actual HTML implementation of the discussed example.</p>
|
|
|
|
<h3><a id="createdocs" name="createdocs">Creating
|
|
ErrorDocuments in different languages</a></h3>
|
|
After all this preparation work, little remains to be said
|
|
about the actual documents. They all share a simple common
|
|
structure:
|
|
<pre>
|
|
<!--#set var="title" value="<em>error description title</em>" -->
|
|
<!--#include virtual="head" -->
|
|
<em>explanatory error text</em>
|
|
<!--#include virtual="foot" -->
|
|
</pre>
|
|
In the <a href="#listings">listings section</a>, you can see an
|
|
example of a [400 Bad Request] error document. Documents as
|
|
simple as that certainly cause no problems to translate or
|
|
expand.
|
|
|
|
<h3><a id="fallback" name="fallback">The fallback
|
|
language</a></h3>
|
|
Do we need a special handling for languages other than those we
|
|
have translations for? We did set the LanguagePriority, didn't
|
|
we?!
|
|
|
|
<p>Well, the LanguagePriority directive is for the case where
|
|
the client does not express any language priority at all. But
|
|
what happens in the situation where the client wants one of the
|
|
languages we do not have, and none of those we do have?</p>
|
|
|
|
<p>Without doing anything, the Apache server will usually
|
|
return a [406 no acceptable variant] error, listing the choices
|
|
from which the client may select. But we're in an error message
|
|
already, and important error information might get lost when
|
|
the client had to choose a language representation first.</p>
|
|
|
|
<p>So, in this situation it appears to be easier to define a
|
|
fallback language (by copying or linking, <em>e.g.</em>, the
|
|
english version to a language-less version). Because the
|
|
negotiation algorithm prefers "more specialized" variants over
|
|
"more generic" variants, these generic alternatives will only
|
|
be chosen when the normal negotiation did not succeed.</p>
|
|
|
|
<p>A simple shell script to do it (execute within the
|
|
errordocs/ dir):</p>
|
|
<pre>
|
|
for f in *.shtml.en
|
|
do
|
|
ln -s $f `basename $f .en`
|
|
done
|
|
</pre>
|
|
|
|
<h2><a id="proxy" name="proxy">Customizing Proxy Error
|
|
Messages</a></h2>
|
|
|
|
<p>As of Apache-1.3, it is possible to use the
|
|
<code>ErrorDocument</code> mechanism for proxy error messages
|
|
as well (previous versions always returned fixed predefined
|
|
error messages).</p>
|
|
|
|
<p>Most proxy errors return an error code of [500 Internal
|
|
Server Error]. To find out whether a particular error document
|
|
was invoked on behalf of a proxy error or because of some other
|
|
server error, and what the reason for the failure was, you can
|
|
check the contents of the new <code>ERROR_NOTES</code> CGI
|
|
environment variable: if invoked for a proxy error, this
|
|
variable will contain the actual proxy error message text in
|
|
HTML form.</p>
|
|
|
|
<p>The following excerpt demonstrates how to exploit the
|
|
<code>ERROR_NOTES</code> variable within an error document:</p>
|
|
<pre>
|
|
<!--#if expr="$REDIRECT_ERROR_NOTES = ''" -->
|
|
<p>
|
|
The server encountered an unexpected condition
|
|
which prevented it from fulfilling the request.
|
|
</p>
|
|
<p>
|
|
<A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->"
|
|
SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->">
|
|
Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s
|
|
WebMaster</A>; it includes useful debugging information about
|
|
the Request which caused the error.
|
|
<pre><!--#printenv --></pre>
|
|
</p>
|
|
<!--#else -->
|
|
<!--#echo var="REDIRECT_ERROR_NOTES" -->
|
|
<!--#endif -->
|
|
</pre>
|
|
|
|
<h2><a id="listings" name="listings">HTML listing of the
|
|
discussed example</a></h2>
|
|
So, to summarize our example, here's the complete listing of
|
|
the <samp>400.shtml.en</samp> document. You will notice that it
|
|
contains almost nothing but the error text (with conditional
|
|
additions). Starting with this example, you will find it easy
|
|
to add more error documents, or to translate the error
|
|
documents to different languages.
|
|
<hr />
|
|
<pre>
|
|
<!--#set var="title" value="Bad Request"
|
|
--><!--#include virtual="head" --><P>
|
|
Your browser sent a request that this server could not understand:
|
|
<BLOCKQUOTE>
|
|
<STRONG><!--#echo var="REQUEST_URI" --></STRONG>
|
|
</BLOCKQUOTE>
|
|
The request could not be understood by the server due to malformed
|
|
syntax. The client should not repeat the request without
|
|
modifications.
|
|
</P>
|
|
<P>
|
|
<!--#if expr="$HTTP_REFERER != ''" -->
|
|
Please inform the owner of
|
|
<A HREF="<!--#echo var="HTTP_REFERER" -->">the referring page</A> about
|
|
the malformed link.
|
|
<!--#else -->
|
|
Please check your request for typing errors and retry.
|
|
<!--#endif -->
|
|
</P>
|
|
<!--#include virtual="foot" -->
|
|
</pre>
|
|
<hr />
|
|
Here is the complete <samp>head.shtml</samp> file (the funny
|
|
line breaks avoid empty lines in the document after XSSI
|
|
processing). Note the configuration section at top. That's
|
|
where you configure the images and logos as well as the apache
|
|
documentation directory. Look how this file displays two
|
|
different logos depending on the content of the virtual host
|
|
name ($SERVER_NAME), and that an animated apache logo is shown
|
|
if the browser appears to support it (the latter requires
|
|
server configuration lines of the form <br />
|
|
<code>BrowserMatch "^Mozilla/[2-4]" anigif</code><br />
|
|
for browser types which support animated GIFs).
|
|
<hr />
|
|
<pre>
|
|
<!--#if expr="$SERVER_NAME = /.*\.mycompany\.com/"
|
|
--><!--#set var="IMG_CorpLogo"
|
|
value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif"
|
|
--><!--#set var="ALT_CorpLogo" value="Powered by Linux!"
|
|
--><!--#else
|
|
--><!--#set var="IMG_CorpLogo"
|
|
value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif"
|
|
--><!--#set var="ALT_CorpLogo" value="Powered by Linux!"
|
|
--><!--#endif
|
|
--><!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif"
|
|
--><!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/"
|
|
--><!--#if expr="$anigif"
|
|
--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif"
|
|
--><!--#else
|
|
--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif"
|
|
--><!--#endif
|
|
--><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>
|
|
[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
|
|
</TITLE>
|
|
</HEAD>
|
|
<BODY BGCOLOR="white" BACKGROUND="<!--#echo var="IMG_BgImage" -->"><UL>
|
|
<H1 ALIGN="center">
|
|
[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
|
|
<IMG SRC="<!--#echo var="IMG_CorpLogo" -->"
|
|
ALT="<!--#echo var="ALT_CorpLogo" -->" ALIGN=right>
|
|
</H1>
|
|
<HR><!-- ======================================================== -->
|
|
<DIV>
|
|
</pre>
|
|
<hr />
|
|
and this is the <samp>foot.shtml.en</samp> file:
|
|
<hr />
|
|
<pre>
|
|
</DIV>
|
|
<HR>
|
|
<DIV ALIGN="right"><SMALL><SUP>Local Server time:
|
|
<!--#echo var="DATE_LOCAL" -->
|
|
</SUP></SMALL></DIV>
|
|
<DIV ALIGN="center">
|
|
<A HREF="<!--#echo var="DOC_Apache" -->">
|
|
<IMG SRC="<!--#echo var="IMG_Apache" -->" BORDER=0 ALIGN="bottom"
|
|
ALT="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></A><BR>
|
|
<SMALL><SUP><!--#set var="var"
|
|
value="Powered by $SERVER_SOFTWARE -- File last modified on $LAST_MODIFIED"
|
|
--><!--#echo var="var" --></SUP></SMALL>
|
|
</DIV>
|
|
<ADDRESS>If the indicated error looks like a misconfiguration, please inform
|
|
<A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->"
|
|
SUBJECT="Feedback about Error message [<!--#echo var="REDIRECT_STATUS"
|
|
-->] <!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->">
|
|
<!--#echo var="SERVER_NAME" -->'s WebMaster</A>.
|
|
</ADDRESS>
|
|
</UL></BODY>
|
|
</HTML>
|
|
</pre>
|
|
<hr />
|
|
|
|
<h3>More welcome!</h3>
|
|
If you have tips to contribute, send mail to <a
|
|
href="mailto:martin@apache.org">martin@apache.org</a>
|
|
<!--#include virtual="footer.html" -->
|
|
</body>
|
|
</html>
|
|
|