Nginx error page with JSON response

12,958

Solution 1

Try using map

map $http_accept $maintenance_page {
    default /maintenance.html;
    ~application/json /maintenance.json;
}

Then replace /maintenance.html by $maintenance_page

More details on http://nginx.org/en/docs/http/ngx_http_map_module.html

Solution 2

You can try the following approach:

  if (-f $document_root/system/maintenance.html) {
    return 503;
  }

  error_page 503 @maintenance;
  location @maintenance {
    internal;
    if ($http_accept ~ json) {
      return 503 "{}";
    }
    rewrite  ^(.*)$  /system/maintenance.html last;
    break;
  }

The main idea is check content-type of the request and return the page accordingly to it

Share:
12,958

Related videos on Youtube

Waseem
Author by

Waseem

Updated on September 18, 2022

Comments

  • Waseem
    Waseem almost 2 years

    I'm trying to serve a maintenance page to clients making request to my application when it is under maintenance. Following is my nginx configuration for that purpose.

    server {
      recursive_error_pages on;
      listen 80;
       ...
    
      if (-f $document_root/maintenance.html) {
        return 503;
      }
    
      error_page 404 /404.html;
      error_page 500 502 504 /500.html;
      error_page 503 @503;
    
      location = /404.html {
        root $document_root;
      }
      location = /500.html {
        root $document_root;
      }
      location @503 {
        error_page 405 =/maintenance.html;
        if (-f $request_filename) {
          break;
        }
        rewrite ^(.*)$ /maintenance.html break;
      }
    }
    

    Lets say I have enabled maintenance of my site by creating a $document_root/maintenance.html. This file, correctly, is served when a user makes a request with with Accept header of text/html.

    $ curl http://server.com/ -i -v -X GET -H "Accept: text/html"
    * Adding handle: conn: 0xf89420
    * Adding handle: send: 0
    * Adding handle: recv: 0
    * Curl_addHandleToPipeline: length: 1
    * - Conn 0 (0xf89420) send_pipe: 1, recv_pipe: 0
    * About to connect() to server.com port 80 (#0)
    *   Trying xxx.xxx.xxx.xxx...
    * Connected to server.com (xxx.xxx.xxx.xxx) port 80 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.33.0
    > Host: server.com
    > Accept: text/html
    > 
    < HTTP/1.1 503 Service Temporarily Unavailable
    HTTP/1.1 503 Service Temporarily Unavailable
    * Server nginx/1.1.19 is not blacklisted
    < Server: nginx/1.1.19
    Server: nginx/1.1.19
    < Date: Thu, 14 Nov 2013 11:16:16 GMT
    Date: Thu, 14 Nov 2013 11:16:16 GMT
    < Content-Type: text/html
    Content-Type: text/html
    < Content-Length: 27
    Content-Length: 27
    < Connection: keep-alive
    Connection: keep-alive
    
    < 
    This is under maintenance.
    * Connection #0 to host server.com left intact
    

    Now some clients set Accept header to application/json. How do I send them a JSON response instead of maintenance.html?

    Following is the response that I get when setting Accept to application/json.

    $ curl http://server.com/ -i -v -X GET -H "Accept: application/json"
    * Adding handle: conn: 0x190c430
    * Adding handle: send: 0
    * Adding handle: recv: 0
    * Curl_addHandleToPipeline: length: 1
    * - Conn 0 (0x190c430) send_pipe: 1, recv_pipe: 0
    * About to connect() to server.com port 80 (#0)
    *   Trying xxx.xxx.xxx.xxx...
    * Connected to server.com (xxx.xxx.xxx.xxx) port 80 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.33.0
    > Host: server.com
    > Accept: application/json
    > 
    < HTTP/1.1 503 Service Temporarily Unavailable
    HTTP/1.1 503 Service Temporarily Unavailable
    * Server nginx/1.1.19 is not blacklisted
    < Server: nginx/1.1.19
    Server: nginx/1.1.19
    < Date: Thu, 14 Nov 2013 11:15:50 GMT
    Date: Thu, 14 Nov 2013 11:15:50 GMT
    < Content-Type: text/html
    Content-Type: text/html
    < Content-Length: 27
    Content-Length: 27
    < Connection: keep-alive
    Connection: keep-alive
    
    < 
    This is under maintenance.
    * Connection #0 to host server.com left intact
    
  • geira
    geira over 6 years
    I guess you mean Accept header of the request. Only responses have Content-Type.