HTTP status codes for error pages
The first digit says who is at fault:
- 2xx success, 3xx go elsewhere, 4xx the request was wrong, 5xx the server failed.
The ones worth a page
- 400 Bad Request: the request itself is malformed (bad form data, a failed origin check).
- 401 Unauthorized: really "unauthenticated": you haven't proven who you are. Must come with a
WWW-Authenticateheader saying how to log in. - 403 Forbidden: we know who you are, and the answer is still no. Logging in again won't help.
- 404 Not Found: nothing here. Also the polite answer for things you don't want to reveal exist, such as an admin page that is switched off.
- 500 Internal Server Error: a bug or crash on the server. The visitor can only retry.
- 503 Service Unavailable: temporarily down (overloaded, maintenance). Can carry
Retry-After.
Redirects worth knowing: 301 (moved for good: browsers and search engines update their links; use it when URLs change) and 302/307 (temporary).
HTTP Basic auth in one minute
The simplest login there is, fine for a one-person admin page over HTTPS:
- Server answers
401withWWW-Authenticate: Basic realm="admin"; the browser shows its own login box. - The browser retries with
Authorization: Basic base64(user:password), and repeats it on every request. - The server compares the password in constant time (hash both sides, then
timingSafeEqual), so response timing doesn't leak how many characters were right.
Base64 is encoding, not encryption: only use Basic auth over HTTPS.
Error pages are pages
- Return the right status code, not a 200 with an error message: browsers, crawlers and monitoring rely on it.
- Keep the site's navigation and style, say what happened in plain words, and offer a next step (home, back, try again for 5xx).
- In React Router, throwing
data(null, { status: 404 })or aResponsefrom a loader lands in the nearestErrorBoundary, which can render one shared error screen for every status.
Related: Afternoon on the live site.