Nginx – Ignore nginx server error_page config for for one specific location directive

nginx

I have static error pages set up for my server, but I want to ignore those for urls starting with /api/ so the handler there can respond with a non-200 code, but not return the static error page.

Here is the existing config:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  example.com;
    root         /var/www/html/;
    index        index.php;

    error_log    /var/log/nginx/error.log;
    access_log   /var/log/nginx/access.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_intercept_errors on;
        fastcgi_index app.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_read_timeout 600;
    }

    error_page 404 /error/404.html;
    error_page 500 502 503 504 /error/50x.html;
    location ^~ /error/ {
        root /usr/share/nginx/html/;
    }
}

So I think I want to add a new location like:

location /api/ {
}

But I'm not sure what to use to tell it to not follow the server's error_page rule.

Best Answer

Alright, I was struggling with the same thing, but managed to find the (a?) solution.

On the highest level I've got:

server {

    include /etc/nginx/boilerplate/fancyerror_and_intercept.conf;


    location ~ (?<target>.*) {
        proxy_pass http://$backend;
    }

}

/etc/nginx/boilerplate/fancyerror_and_intercept.conf contains:

error_page 404 /40x.html;
error_page 403 /40x.html;
error_page 405 /40x.html;
error_page 500 /50x.html;
error_page 501 /50x.html;
error_page 502 /50x.html;
error_page 503 /50x.html;


location = /40x.html {
    root /etc/nginx/error_pages;
}
location = /50x.html {
    root /etc/nginx/error_pages;
}


more_set_headers -s '404 403 405 500 501 502 503 504' 'X-Robots-Tag: noindex, nofollow';
proxy_intercept_errors on;

In order to exclude the /api/ route (Location starts with /api/ and can contain anything after), add the following:

location ~ ^/api/ {
    error_page 527 error.html;
    proxy_intercept_errors off;
    proxy_pass http://$backend;
}

In essence the /api/ location is a duplicate of the general location, but with error_page redefined and intercept errors set to off.

This works, because as Tim stated earlier, the error_page directive resets any predefined error_pages. I've chosen error code 527, because we don't use CloudFlare see Wikipedia, List of HTTP status codes#Cloudflare. Because we proxy_pass our requests, you mileage may vary and you might have to change the proxy_intercept_errors off; to fastcgi_intercept_errors off;.