When implementing Nginx as a reverse proxy, error handling becomes more complex than in standalone configurations. The primary challenge emerges from needing to:
- Maintain backend-originated JSON error details for 400 Bad Request responses
- Consistently serve custom error pages for all status codes
- Avoid default Nginx error pages under any circumstances
Here's a robust solution that addresses both requirements:
http {
# Define common error page path
proxy_intercept_errors on;
# Handle standard error codes
error_page 401 /error_pages/401.html;
error_page 403 /error_pages/403.html;
error_page 404 /error_pages/404.html;
error_page 500 502 503 504 /error_pages/50x.html;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
# Special handling for 400 responses
proxy_intercept_errors off;
proxy_next_upstream error timeout invalid_header http_400;
# Return to default error handling for other codes
error_page 400 = @fallback;
}
location @fallback {
proxy_intercept_errors on;
proxy_pass http://backend;
}
# Custom error page locations
location /error_pages/ {
internal;
root /var/www/html;
}
}
}
The solution combines several Nginx features:
Status-Code-Specific Interception
Using proxy_next_upstream
with http_400
allows passing through 400 responses while still intercepting other errors. The @fallback
named location ensures proper handling of all other status codes.
Comprehensive Error Coverage
To prevent any default Nginx pages from appearing, we recommend:
- Creating error pages for all standard HTTP status codes
- Implementing a catch-all error handler for unexpected codes
# Catch-all error handler
error_page 300-599 /error_pages/generic.html;
Verify your configuration with these test cases:
- Trigger 400 errors with malformed requests
- Test standard error codes (404, 500, etc.)
- Verify custom pages for obscure status codes (418, 429, etc.)
The additional error handling adds minimal overhead. For high-traffic sites, consider:
- Caching error pages with appropriate headers
- Using
error_page
directives in theserver
context rather than per-location - Keeping error page assets lightweight
When implementing Nginx as a reverse proxy, error handling becomes more complex than in standalone configurations. We need to maintain two key requirements simultaneously:
- Preserve backend-generated JSON error details for 400 Bad Request responses
- Consistently serve custom error pages for all other status codes
The solution involves combining several Nginx directives with conditional logic. Here's the approach:
http {
# Default error page configuration
proxy_intercept_errors on;
# Custom error pages for common status codes
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 500 502 503 504 /errors/50x.html;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
# Special handling for 400 errors
proxy_intercept_errors off;
proxy_next_upstream error timeout invalid_header http_400;
# Error response validation
proxy_set_header Accept application/json;
}
# Error page locations
location /errors/ {
internal;
root /var/www/html;
}
}
}
The configuration works through several mechanisms:
proxy_intercept_errors
is globally enabled but selectively disabled for 400 status handling- The
proxy_next_upstream
directive ensures proper handling of 400 errors - JSON content negotiation is enforced via
proxy_set_header
- All error pages are served from an internal location block
For complete coverage of all possible status codes, consider this pattern:
map $status $error_page {
default /errors/generic.html;
~^[4-5][0-9]{2}$ /errors/$status.html;
}
server {
# ... other configuration ...
error_page 400 = @no_intercept;
location @no_intercept {
proxy_pass http://backend;
proxy_intercept_errors off;
}
location / {
error_page 400 = @no_intercept;
# ... other proxy settings ...
}
}
The solution maintains efficiency by:
- Using Nginx's native pattern matching for status codes
- Minimizing conditional logic in the request path
- Leveraging internal redirects for error page serving