1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
|
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This file is generated from xml source: DO NOT EDIT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<title>International Customized Server Error Messages - Apache HTTP Server</title>
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
<body id="manual-page"><div id="page-header">
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
<p class="apache">Apache HTTP Server Version 2.0</p>
<img alt="" src="../images/feather.gif" /></div>
<div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
<div id="path">
<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.0</a> > <a href="./">Miscellaneous Documentation</a></div><div id="page-content"><div id="preamble"><h1>International Customized Server Error Messages</h1>
<div class="toplang">
<p><span>Available Languages: </span><a href="../en/misc/custom_errordocs.html" title="English"> en </a></p>
</div>
<div class="warning"><h3>Warning:</h3>
<p>This document has not been fully updated
to take into account changes made in the 2.0 version of the
Apache HTTP Server. Some of the information may still be
relevant, but please use it with care.</p>
</div>
<p>This document describes an easy way to provide your Apache
HTTP Server with a set of customized error messages which take
advantage of <a href="../content-negotiation.html">Content
Negotiation</a> and <code class="module"><a href="../mod/mod_include.html">mod_include</a></code> to return
error messages generated by the server in the client's native
language.</p>
</div>
<div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#intro">Introduction</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#createdir">Creating an ErrorDocument directory</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#proxy">Customizing Proxy Error Messages</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#listings">HTML Listing of the Discussed Example</a></li>
</ul></div>
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="intro" id="intro">Introduction</a></h2>
<p>By using SSI, all <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> 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.</p>
<p>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>
<p>An example of a "document not found" message for a german
client might look like this:</p>
<p><img src="../images/custom_errordocs.gif" alt="[Needs graphics capability to display]" /></p>
<p>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.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="createdir" id="createdir">Creating an ErrorDocument directory</a></h2>
<p>For this concept to work as easily as possible, we must take
advantage of as much server support as we can get:</p>
<ol>
<li>By defining the MultiViews <code class="directive"><a href="../mod/core.html#options">Options</a></code>, we
enable the language selection of the most appropriate
language alternative (content negotiation).</li>
<li>By setting the <code class="directive"><a href="../mod/mod_negotiation.html#languagepriority">LanguagePriority</a></code>
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 <code class="module"><a href="../mod/mod_include.html">mod_include</a></code>
(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 <code class="directive"><a href="../mod/mod_mime.html#addhandler">AddHandler</a></code> and <code class="directive"><a href="../mod/mod_mime.html#addtype">AddType</a></code> directives
are useful for automatically SSI-expanding all files with a
<code>.shtml</code> suffix to <em>text/html</em>.</li>
<li>By using the <code class="directive"><a href="../mod/mod_alias.html#alias">Alias</a></code> 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 <code class="directive"><a href="../mod/core.html#directory"><Directory></a></code> 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 <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> in
the aliased <code>/errordocs</code> 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 <code class="directive"><a href="../mod/core.html#allowoverride">AllowOverride</a></code> directive tells
apache that it is not necessary to look for a .htaccess file
in the /errordocs directory: a minor speed optimization.</li>
</ol>
<p>The resulting <code>httpd.conf</code> configuration would then
look similar to this:</p>
<div class="note"><h3>Note</h3>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.</div>
<div class="example"><p><code>
LanguagePriority en fr de <br />
Alias /errordocs /usr/local/apache/errordocs <br />
<br />
<Directory /usr/local/apache/errordocs> <br />
<span class="indent">
AllowOverride none <br />
Options MultiViews IncludesNoExec FollowSymLinks <br />
AddType text/html .shtml <br />
<FilesMatch "\.shtml[.$]"> <br />
<span class="indent">
SetOutputFilter INCLUDES <br />
</span>
</FilesMatch> <br />
</span>
</Directory> <br />
<br />
# "400 Bad Request", <br />
ErrorDocument 400 /errordocs/400 <br />
# "401 Authorization Required", <br />
ErrorDocument 401 /errordocs/401 <br />
# "403 Forbidden", <br />
ErrorDocument 403 /errordocs/403 <br />
# "404 Not Found", <br />
ErrorDocument 404 /errordocs/404 <br />
# "500 Internal Server Error", <br />
ErrorDocument 500 /errordocs/500 <br />
</code></p></div>
<p>The directory for the error messages (here:
<code>/usr/local/apache/errordocs/</code>) must then be created
with the appropriate permissions (readable and executable by
the server uid or gid, only writable for the administrator).</p>
<h3><a name="naming" id="naming">Naming the Individual Error Document files</a></h3>
<p>By defining the <code>MultiViews</code> 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>
<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
<code>errordocs/403.shtml.<em>lang</em></code> is created and
filled with the error text in that language (<a href="#createdocs">see below</a>).</li>
<li>One fallback document called
<code>errordocs/403.shtml</code> is created, usually by
creating a symlink to the default language variant (<a href="#fallback">see below</a>).</li>
</ul>
<h3><a name="headfoot" id="headfoot">The Common Header and Footer Files</a></h3>
<p>By putting as much layout information in two special "include
files", the error documents can be reduced to a bare minimum.</p>
<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 SSI 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>.</p>
<p><strong>By changing this file, the layout of all generated
error messages can be changed in a second.</strong> (By
exploiting the features of SSI, 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>
<div class="example"><p><code>
for English, French and German versions (default english) <br />
<br />
foot.shtml.en, <br />
foot.shtml.fr, <br />
foot.shtml.de, <br />
foot.shtml symlink to <br />
foot.shtml.en
</code></p></div>
<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 name="createdocs" id="createdocs">Creating ErrorDocuments in Different Languages</a></h3>
<p>After all this preparation work, little remains to be said
about the actual documents. They all share a simple common
structure:</p>
<div class="example"><p><code>
<!--#set var="title" value="<em>error description title</em>" --> <br />
<!--#include virtual="head" --> <br />
<span class="indent">
<em>explanatory error text</em> <br />
</span>
<!--#include virtual="foot" -->
</code></p></div>
<p>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.</p>
<h3><a name="fallback" id="fallback">The Fallback Language</a></h3>
<p>Do we need a special handling for languages other than those we
have translations for? We did set the LanguagePriority, didn't
we?!</p>
<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>
<div class="example"><p><code>
for f in *.shtml.en <br />
do <br />
<span class="indent">
ln -s $f `basename $f .en` <br />
</span>
done
</code></p></div>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="proxy" id="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>
<div class="example"><p><code>
<!--#if expr="$REDIRECT_ERROR_NOTES = ''" --> <br />
<br />
<p> <br />
<span class="indent">
The server encountered an unexpected condition <br />
which prevented it from fulfilling the request. <br />
</span>
</p> <br />
<br />
<p> <br />
<span class="indent">
<a href="mailto:<!--#echo var="SERVER_ADMIN" -->" <br />
SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->"> <br />
Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s <br />
WebMaster</a>; it includes useful debugging information about <br />
the Request which caused the error. <br />
<br />
<pre><!--#printenv --></pre> <br />
</span>
</p> <br />
<br />
<!--#else --> <br />
<span class="indent">
<!--#echo var="REDIRECT_ERROR_NOTES" --><br />
</span>
<br />
<!--#endif -->
</code></p></div>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="listings" id="listings">HTML Listing of the Discussed Example</a></h2>
<p>So, to summarize our example, here's the complete listing of
the <code>400.shtml.en</code> 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.</p>
<div class="example"><p><code>
<!--#set var="title" value="Bad Request"--> <br />
<!--#include virtual="head" --><br />
<br />
<p> <br />
<span class="indent">
Your browser sent a request that this server could not understand: <br />
<blockquote> <br />
<span class="indent">
<strong><!--#echo var="REQUEST_URI" --></strong><br />
</span>
</blockquote> <br />
<br />
The request could not be understood by the server due to malformed <br />
syntax. The client should not repeat the request without <br />
modifications. <br />
</span>
</p> <br />
<br />
<p> <br />
<span class="indent">
<!--#if expr="$HTTP_REFERER != ''" --> <br />
<span class="indent">
Please inform the owner of <br />
<a href="<!--#echo var="HTTP_REFERER" -->">the referring page</a> about <br />
the malformed link. <br />
</span>
<br />
<!--#else --> <br />
<span class="indent">
Please check your request for typing errors and retry. <br />
</span>
<br />
<!--#endif --> <br />
</span>
</p> <br />
<br />
<!--#include virtual="foot" -->
</code></p></div>
<p>Here is the complete <code>head.shtml.en</code> file (the funny
line breaks avoid empty lines in the document after SSI
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 </p>
<div class="example"><p><code>BrowserMatch "^Mozilla/[2-4]" anigif</code></p></div>
<p>for browser types which support animated GIFs).</p>
<div class="example"><p><code>
<!--#if expr="$SERVER_NAME = /.*\.mycompany\.com/" --><br />
<span class="indent">
<!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" --><br />
<!--#set var="ALT_CorpLogo" value="Powered by Linux!" --><br />
</span>
<br />
<!--#else --> <br />
<span class="indent">
<!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" --> <br />
<!--#set var="ALT_CorpLogo" value="Powered by Linux!" --> <br />
</span>
<!--#endif--> <br />
<br />
<!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" --> <br />
<!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" --> <br />
<br />
<!--#if expr="$anigif" --> <br />
<span class="indent">
<!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" --> <br />
</span>
<!--#else--><br />
<span class="indent">
<!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" --><br />
</span>
<!--#endif--><br />
<br />
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <br />
<html> <br />
<head> <br />
<span class="indent">
<title> <br />
[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> <br />
</title> <br />
</span>
</head> <br />
<br />
<body bgcolor="white" background="<!--#echo var="IMG_BgImage" -->"> <br />
<span class="indent">
<h1 align="center"> <br />
[<!--#echo var="REDIRECT_STATUS" -->]
<!--#echo var="title" --> <br />
<img src="<!--#echo var="IMG_CorpLogo" -->" <br />
alt="<!--#echo var="ALT_CorpLogo" -->" align="right"> <br />
</h1> <br />
<br />
<hr />
<!-- ======================================================== --> <br />
<div>
</span>
</code></p></div>
<p>and this is the <code>foot.shtml.en</code> file:</p>
<div class="example"><p><code>
<span class="indent">
</div> <br />
<hr /> <br />
<br />
<div align="right"> <br />
<span class="indent">
<small>Local Server time:
<!--#echo var="DATE_LOCAL" --></small> <br />
</span>
</div> <br />
<br />
<div align="center"><br />
<span class="indent">
<a href="<!--#echo var="DOC_Apache" -->"> <br />
<img src="<!--#echo var="IMG_Apache" -->" border="0" align="bottom" <br />
alt="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></a> <br />
<br /><br />
<small><!--#set var="var" value="Powered by $SERVER_SOFTWARE -- <br />
File last modified on $LAST_MODIFIED" --> <br />
<!--#echo var="var" --></small> <br />
</span>
</div> <br />
<br />
<p>If the indicated error looks like a misconfiguration, please inform <br />
<a href="mailto:<!--#echo var="SERVER_ADMIN" -->" <br />
subject="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" -->] <br />
<!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->"> <br />
<!--#echo var="SERVER_NAME" -->'s WebMaster</a>.<br />
</p><br />
</span>
<br />
</body><br />
</html>
</code></p></div>
<p>If you have tips to contribute, send mail to <a href="mailto:martin@apache.org">martin@apache.org</a></p>
</div></div>
<div class="bottomlang">
<p><span>Available Languages: </span><a href="../en/misc/custom_errordocs.html" title="English"> en </a></p>
</div><div id="footer">
<p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
</body></html>
|