mirror of
				https://github.com/apache/httpd.git
				synced 2025-10-30 08:05:39 +03:00 
			
		
		
		
	actives SSIs. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88072 13f79535-47bb-0310-9956-ffa450edef68
		
			
				
	
	
		
			434 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 | |
| <HTML>
 | |
| <HEAD>
 | |
| <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>
 | |
| <P>
 | |
| <H2>Index</H2>
 | |
| <UL>
 | |
|  <LI><A HREF="#intro">Introduction</A>
 | |
|  <LI><A HREF="#createdir">Creating an ErrorDocument directory</A>
 | |
|  <LI><A HREF="#docnames">Naming the individual error document files</A>
 | |
|  <LI><A HREF="#headfoot">The common header and footer files</A>
 | |
|  <LI><A HREF="#createdocs">Creating ErrorDocuments in different languages</A>
 | |
|  <LI><A HREF="#fallback">The fallback language</A>
 | |
|  <LI><A HREF="#proxy">Customizing Proxy Error Messages</A>
 | |
|  <LI><A HREF="#listings">HTML listing of the discussed example</A>
 | |
| </UL>
 | |
| <HR>
 | |
| <H2><A 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.
 | |
| </P>
 | |
| <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...
 | |
| <UL>
 | |
| <LI>possibly are served by different virtual hosts (different host name,
 | |
|     different IP address, or different port) on the server machine,
 | |
| <LI>show a predefined company logo in the right top of the message
 | |
|     (selectable by virtual host),
 | |
| <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>have some kind of standardized background image,
 | |
| <LI>display an apache logo and a feedback email address at the bottom
 | |
|     of the error message.
 | |
| </UL>
 | |
| </P>
 | |
| 
 | |
| <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 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>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>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>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>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>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>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>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.
 | |
| </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 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):
 | |
| <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>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>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>).
 | |
| </UL>
 | |
| 
 | |
| <H3><A 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>
 | |
| 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>
 | |
| 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>
 | |
| <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>
 | |
| 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>
 | |
| 
 | |
| See <A HREF="#listings">the listings below</A> to see an actual HTML
 | |
| implementation of the discussed example.
 | |
| 
 | |
| 
 | |
| <H3><A 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 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>
 | |
| 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>
 | |
| 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> 
 | |
| A simple shell script to do it (execute within the errordocs/ dir):
 | |
| <PRE>
 | |
|   for f in *.shtml.en
 | |
|   do
 | |
|      ln -s $f `basename $f .en`
 | |
|   done
 | |
| </PRE>
 | |
| 
 | |
| <P>
 | |
| </P>
 | |
| 
 | |
| <H2><A 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 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>
 | |
| 
 |