0

I have some problems with a specific setup that I want to achieve:

Summary:

  • Nginx acts as a reverse-proxy
  • Backend running at http://localhost:8080/
  • Nginx may return HTTP 403 ($block_access = true), in that case I want to show a custom error page (/errors/403.html)
  • Backend may return HTTP 404, in that case I also want to show a custom error page (/errors/404.html)

Problems:

  • Custom HTTP 403 page does not work, the default Nginx 403 page gets served instead
  • Custom HTTP 404 page for the backend works
  • If I remove proxy_intercept_errors from the location block, the custom 403 page works for Nginx but the custom 404 page for the proxy obviously doesn't work anymore

Configuration:

server { listen 443 ssl http2; server_name mydomain.com; # Reverse proxy configuration location / { # Let Nginx handle basic blocking behavior if ($block_access) { return 403; } # Proxy request to backend proxy_pass http://localhost:8080/; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Connection $http_connection; # Only intercept 404 errors from the backend proxy_intercept_errors on; error_page 404 /errors/404.html; # Serve custom 404 error page location = /errors/404.html { root /var/www/html; internal; } } # Serve custom 403 error page for blocked access ($block_access = true) error_page 403 /errors/403.html; location = /errors/403.html { root /var/www/html; internal; } location /errors/ { root /var/www/html; try_files $uri $uri/ =404; } } 

I am more or less at a complete loss with the search for a solution...

1 Answer 1

1

https://nginx.org/r/error_page

These directives are inherited from the previous configuration level if and only if there are no error_page directives defined on the current level.

So you have to repeat directive for 403.

location / { proxy_pass http://localhost:8080/; proxy_intercept_errors on; # ... error_page 403 /errors/403.html; error_page 404 /errors/404.html; } 

UPD: if you want to separate 403 from upstream you could use “fake” error code in your check and replace it to real code in error_page directive.

location / { if ($block_access) { return 453; } # ... error_page 453 =403 /errors/403.html; error_page 404 /errors/404.html; } error_page 453 =403 /errors/403.html; # ... 
3
  • This causes another problem for me, which is why I didn't want to catch the 403 from the backend. Sometimes my backend uses 403 for access control, then instead of a JSON my custom error page is returned which breaks the application. :( Commented Mar 19 at 14:44
  • 1
    @ShadowEagle see update Commented Mar 19 at 14:56
  • Perfect, simple but effective to use a custom error code to avoid a conflict with the existing one from the upstream! Thank you very much. Commented Mar 24 at 14:05

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.