Helping the user to understand what went wrong

Custom Errors

Preliminaries

This note describes how to configure the server to show custom error messages when an HTTP request fails.

The HTTP protocol defines how user-agents and servers should interact with each other when things don't go as expected. The most important and well-recognized part of this protocol is the use of status codes to indicate the type of failure that occurred.

When two computers are communicating with each other using requests and responses, the succinct nature of status codes is very good way to understand what went wrong and how to proceed. But when a human being is involved in the process, a three-digit status code can be a bit disconcerting.

Of course these days, when a user encounters a 404 status code, there's very little chance that it will be upsetting — it's just a part of being web-savvy. Nevertheless, in situations like this, a determined user should be given a chance to find the document that's missing. Many websites do this by giving the user a site search form on the page that displays the 404 error.

A webmaster can provide this capability using the custom errors section of the configuration file. This capability allows the webmaster to fully control the content, appearance, and functionality of the page displayed when an error occurs. The content can provide explanations of what happened and what the user can do about it, using a natural language suitable to the website's users. The appearance can match the rest of the website's appearance, providing an extra touch of professional polish to the website. And the functionality of the page can guide the user to hyperlinks or search forms to help them resolve the issue.

All of this can go beyond the humorous 404 pages that poke fun at what happened. The server can respond to each status code in distinct and meaningful ways. This can be especially important to software engineers during their development process. During active development, the custom errors module can be fully enabled; then when the website is in production and working as expected, the custom errors section can be reduced to just a handful of common situations, or turned off completely.

The server's default behavior is to use bare status codes, without any additional explanatory text. Even the short reason text, that was part of the HTTP/1.1 specification, has been dropped from HTTP/2.

Configuration

The modules section must include a custom-errors entry with the value on in order to enable the Custom Errors module.

The custom-errors section of the configuration comprises a set of entries, each of which has a status code and a path to an HTML file.

The status code must be listed first, and must be a numeric value in the 400 or 500 range. Values in the 100, 200 and 300 ranges are success codes, and return meaningful text in their response body, so further explanation is not necessary.

The HTML file path must be an absolute path on the server, referencing a file that contains well-formed HTML that will be sent to the requestor when the specified status code is encountered. The filename must be enclosed in GRAVE-ACCENT delimiters. The file that it references must be readable by the server process. It may be anywhere on the server; it does not have to be within the public document directory.

EBNF

SP ::= U+20
CR ::= U+0D
GRAVE-ACCENT ::= U+60
LEFT-CURLY-BRACKET ::= U+7B
RIGHT-CURLY-BRACKET ::= U+7D
status-code ::= [400-416] | [500-501]
file-system-chars ::= (ALPHA | DIGIT | )*
delimited-html-filename ::= GRAVE-ACCENT file-system-chars* GRAVE-ACCENT
custom-error-entry ::= status-code SP delimited-html-filename CR
custom-errors-section ::= 'custom-errors' SP LEFT-CURLY-BRACKET CR
custom-error-entry*
RIGHT-CURLY-BRACKET CR

† Legal file system characters vary by platform

Cookbook

Example 1: Custom errors disabled
modules {
custom-errors off
}
Example 2: Custom 404 only
modules {
custom-errors on
}
response {
custom-errors {
404 `/var/www/example.com/custom-errors/404-not-found.html`
}
}
Example 3: Custom errors fully specified
modules {
custom-errors on
}
response {
custom-errors {
400 `/var/www/example.com/custom-errors/400-bad-request.html`
403 `/var/www/example.com/custom-errors/403-forbidden.html`
404 `/var/www/example.com/custom-errors/404-not-found.html`
405 `/var/www/example.com/custom-errors/405-method-not-allowed.html`
406 `/var/www/example.com/custom-errors/406-not-acceptable.html`
409 `/var/www/example.com/custom-errors/409-conflict.html`
411 `/var/www/example.com/custom-errors/411-length-required.html`
412 `/var/www/example.com/custom-errors/412-precondition-failed.html`
414 `/var/www/example.com/custom-errors/414-uri-too-long.html`
415 `/var/www/example.com/custom-errors/415-unsupported-media-type.html`
416 `/var/www/example.com/custom-errors/416-range-not-satisfiable.html`
500 `/var/www/example.com/custom-errors/500-internal-server-error.html`
501 `/var/www/example.com/custom-errors/501-not-implemented.html`
}
}

Review

Key points to remember:

  • Custom error pages must be written using well-formed HTML.
  • The error-page text is returned in the original response body; it is not a redirection.

Helping the user to understand what went wrong