From: Martin Kraemer
- $Revision: 1.104 $ ($Date: 1998/01/26 16:53:48 $)
+ $Revision: 1.105 $ ($Date: 1998/02/05 09:58:38 $)
The latest version of this FAQ is always available from the main
@@ -142,6 +142,9 @@
Apache Server Frequently Asked Questions
ErrorDocument
401
work?
ErrorDocument
+ and SSI to simplify customized error messages?
+
ErrorDocument
+ and SSI to simplify customized error messages?
+
+
+ Have a look at this document.
+ It shows in example form how you can a combination of XSSI and
+ negotiation to tailor a set of ErrorDocument
s to your
+ personal taste, and returning different internationalized error
+ responses based on the client's native language.
+
+
+By using XSSI, all customized messages
+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.
+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.
+
+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. +
++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... +
+An example of a "document not found" message for a german client might
+look like this:
+
+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", i.e., when the error
+actually occurs.
+
src/main/http_protocol.c
+ if you wish to see apache's standard messages), an
+ ErrorDocument
+ in the aliased /errordocs 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 not handled by a
+ custom document will be dealt with by the server in the standard way
+ (i.e., a plain error message in english).
+ + 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 + AddHandler server-parsed .shtml + </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 ++The directory for the error messages (here: +/usr/local/apache/errordocs/) must then be created with the +appropriate permissions (readable and executable by the server uid or gid, +only writable for the administrator). + +
+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): +
+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 title
.
+By changing this file, the layout of all generated error
+messages can be changed in a second.
+(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).
+
+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. +
+For simplicity, the header file is simply called head.shtml
+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.
+Example: for english, french and german versions (default english)
+foot.shtml.en
,
+foot.shtml.fr
,
+foot.shtml.de
,
+foot.shtml
symlink to foot.shtml.en
+Both files are then simply included into the error document by using the
+directives <!--#include virtual="head" -->
+and <!--#include virtual="foot" -->
+respectively: the rest of the magic occurs in mod_negotiation and
+in mod_include.
+
+
+See the listings below to see an actual HTML
+implementation of the discussed example.
+
+
+Creating ErrorDocuments in different languages
+
+After all this preparation work, little remains to be said about the
+actual documents. They all share a simple common structure:
+
+<!--#set var="title" value="error description title" --> +<!--#include virtual="head" --> + explanatory error text +<!--#include virtual="foot" --> ++In the listings section, 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. + +
+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? +
+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. +
+So, in this situation it appears to be easier to define a fallback language +(by copying or linking, e.g., 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. +
+A simple shell script to do it (execute within the errordocs/ dir): +
+ for f in *.shtml.en + do + ln -s $f `basename $f .en` + done ++ +
+
+ ++<!--#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" --> +
BrowserMatch "^Mozilla/[2-4]" anigif
+<!--#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> +
+ + </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> +
+
+