Custom nginx error pages
For quite some time I've been using custom nginx error pages on this site.
My approach so far was to generate a bunch of static HTML with the various error messages and then configure them for each corresponding HTTP status codes in nginx.
As there are quite a number of HTTP errors, I used a little shell script to generate the whole config and HTML, in the end I had a huge file with snippets like the one below.
error_page 429 @custom_error_429; location @custom_error_429 { internal; more_set_headers 'Content-Type: text/html'; echo '<html>...</html>'; }
Now while implementing custom error pages for a different project, I tried to see if there is an easier way to do this.
Some searching lead to the One NGINX error page to rule them all article which describes an alternative approach leveraging the nginx SSI module to generate the error pages on the fly.
Instead of generating and defining a specific error page for each error, a single error page is used for all errors.
error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 431 451 500 501 502 503 504 505 506 507 508 510 511 /error.html; location = /error.html { ssi on; internal; root /var/www/default; }
nginx provides the status code as variable to our error page, but we also need the error message to make it more userfriendly.
For this we define a mapping of status codes to the error messages.
map $status $status_text { 400 'Bad Request'; 401 'Unauthorized'; 402 'Payment Required'; 403 'Forbidden'; 404 'Not Found'; 405 'Method Not Allowed'; 406 'Not Acceptable'; 407 'Proxy Authentication Required'; 408 'Request Timeout'; 409 'Conflict'; 410 'Gone'; 411 'Length Required'; 412 'Precondition Failed'; 413 'Payload Too Large'; 414 'URI Too Long'; 415 'Unsupported Media Type'; 416 'Range Not Satisfiable'; 417 'Expectation Failed'; 418 'I\'m a teapot'; 421 'Misdirected Request'; 422 'Unprocessable Entity'; 423 'Locked'; 424 'Failed Dependency'; 425 'Too Early'; 426 'Upgrade Required'; 428 'Precondition Required'; 429 'Too Many Requests'; 431 'Request Header Fields Too Large'; 451 'Unavailable For Legal Reasons'; 500 'Internal Server Error'; 501 'Not Implemented'; 502 'Bad Gateway'; 503 'Service Unavailable'; 504 'Gateway Timeout'; 505 'HTTP Version Not Supported'; 506 'Variant Also Negotiates'; 507 'Insufficient Storage'; 508 'Loop Detected'; 510 'Not Extended'; 511 'Network Authentication Required'; default 'Something went wrong'; }
Now we have the status and the status_text variables available in our error.html page.
<html><body> <h1><!--# echo var="status" default="" --> <!--# echo var="status_text" default="Something went wrong" --></h1> </body></html>