Search code examples
restnginxwebserver

Don't serve static files if backend is offline


I have the following nginx config that handles serving my static website and redirecting requests to my REST backend:

server {
    listen 80 default_server;
    server_name _;

    # Host static content directly
    location / {
        root /var/www/html;
        index index.html;
        try_files $uri $uri/ =404;
    }

    # Forward api requests to REST server
    location /api {
        proxy_pass http://127.0.0.1:8080;
    }

}

If my REST backend goes offline the proxy module returns an HTTP status of "502 Bad Gateway" and I can redirect requests to a status page by adding the following:

# Rewrite "502 Bad Gateway" to "503 Service unavailable"
error_page 502 =503 @status_offline;

# Show offline status page whenever 503 status is returned
error_page 503 @status_offline;
location @status_offline {
    root /var/www/html;
    rewrite ^(.*)$ /status_offline.html break;
}

However, this will only work for requests that access the REST backend directly. How can I redirect requests to my static website in the same way whenever the backend is offline?


Solution

  • Nginx does have some health check and status monitoring capabilities that seem like they could be related, but I couldn't find a proper way to use them.

    While its intended use case is actually for authorization, I found nginx's auth_request module to work for me:

    # Host static content directly
    location / {
        # Check if REST server is online before serving site
        auth_request /api/status; # Continues when 2xx HTTP status is returned
        # If not, redirect to offline status page
        error_page 500 =503 @status_offline;
    
        root /var/www/html;
        index index.html;
        try_files $uri $uri/ =404;
    }
    

    It will call /api/status as a subrequest before serving the static content and will only continue when the subrequest returns an HTTP status in the 200 range. It seems to return status 500 when the server is offline.

    This method might have some performance implications since you're now always doing an extra request, but that seems to be an inherent requirement of checking whether your service is online.