55

I have a Sinatra application hosted with Unicorn, and nginx in front of it. When the Sinatra application errors out (returns 500), I'd like to serve a static page, rather than the default "Internal Server Error". I have the following nginx configuration:

server {
  listen 80 default;
  server_name *.example.com;
  root /home/deploy/www-frontend/current/public;

  location / {
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_connect_timeout 5;
    proxy_read_timeout 240;
    proxy_pass http://127.0.0.1:4701/;
  }

  error_page 500 502 503 504 /50x.html;
}

The error_page directive is there, and I have sudo'd as www-data (Ubuntu) and verified I can cat the file, thus it's not a permission problem. With the above config file, and service nginx reload, the page I receive on error is still the same "Internal Server Error".

What's my error?

François Beausoleil
  • 16,265
  • 11
  • 67
  • 90

4 Answers4

107

error_page handles errors that are generated by nginx. By default, nginx will return whatever the proxy server returns regardless of http status code.

What you're looking for is proxy_intercept_errors

This directive decides if nginx will intercept responses with HTTP status codes of 400 and higher.

By default all responses will be sent as-is from the proxied server.

If you set this to on then nginx will intercept status codes that are explicitly handled by an error_page directive. Responses with status codes that do not match an error_page directive will be sent as-is from the proxied server.

Golu
  • 414
  • 5
  • 16
Stephen Emslie
  • 10,539
  • 9
  • 32
  • 28
  • 2
    I knew it was a question of RTFM. Thanks for taking the time to provide a great answer! – François Beausoleil Jan 03 '12 at 17:10
  • 14
    Just a quick note to a 4 years old response - now `proxy_intercept_errors` works for errors equal or greater to 300. – Tisho Feb 25 '16 at 10:09
  • After setting this directive on, the custom error page gets enabled, but custom response headers sent from the upstream are getting dropped. Any ideas how to resolve this part? – Vinay Mundada May 20 '20 at 13:33
23

You can set proxy_intercept_errors especially for that location

location /some/location {
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_connect_timeout 5;
    proxy_read_timeout 240;
    proxy_pass http://127.0.0.1:4701/;
    proxy_intercept_errors on; # see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors

    error_page 400 500 404 ... other statuses ... =200 /your/path/for/custom/errors;
}

and you can set instead 200 other status what you need

Trenton
  • 1,438
  • 1
  • 10
  • 7
Alexey
  • 812
  • 13
  • 22
  • 8
    Using `proxy_intercept_errors;` (without argument) is no longer valid in current nginx. Use `proxy_intercept_errors on;` instead. – Marian Dec 02 '14 at 07:47
  • 1
    Quick question about the semantics here... setting `proxy_intercept_errors` to `on` means that the custom page is returned, and setting to `off` means the nginx page is returned, correct? – speedplane Jun 14 '16 at 01:20
  • 1
    I am using a FASTCGI even If I turn proxy_intercept_errors on it still won't intercept the error. It won't even intercept 404 errors. – Aftab Naveed Nov 22 '17 at 04:34
6

People who are using FastCGI as their upstream need this parameter turned on

fastcgi_intercept_errors on;

For my PHP application, I am using it in my upstream configuration block

 location ~ .php$ { ## Execute PHP scripts
    fastcgi_pass   php-upstream; 
    fastcgi_intercept_errors on;
    error_page 500 /500.html;
 }
Aftab Naveed
  • 3,652
  • 3
  • 26
  • 40
0

As mentioned by Stephen in this response, using proxy_intercept_errors on; can work. Though in my case, as seen in this answer, using uwsgi_intercept_errors on; did the trick...

Community
  • 1
  • 1
ppython
  • 485
  • 6
  • 19