Return 503 for POST request in Nginx
Asked Answered
N

3

7

I have simple configuration file that is used to server custom 503 error page at a time of maintenance. The relevant part is this:

server {
    listen      80 default;
    root        /usr/share/nginx/html;
    server_name example.com;

    location / {
        if (-f $document_root/503.json) {
            return 503;
        }
    }

    # error 503 redirect to 503.json
    error_page 503 @maintenance;
    location @maintenance {
        rewrite ^(.*)$ /503.json break;
    }
}

The problem is Nginx figures out that any request resolves in a static file and any POST, PUT and DELETE requests get 405 (method not allowed) response.

So the question is: how do I tell Nginx to serve my page for any HTTP method?

Nationalist answered 23/4, 2013 at 23:35 Comment(1)
Did you come up with a solution to this?Aetna
A
9

I ran into this today. It seems the issue is due to nginx (like most servers) not letting you POST to a static file.

The solution is to capture 405 errors in your @503 location block, serving the maintenance page. In addition, you will have to enable @recursiveerrorpages@, since you are first, intentionally, throwing a 503 error, and then the user is throwing a 405 by posting to your static file:

recursive_error_pages on;

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

error_page 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 @503;
location @503 {

  error_page 405 = /system/maintenance.html;

  # Serve static assets if found.
  if (-f $request_filename) {
    break;
  }

  rewrite ^(.*)$ /system/maintenance.html break;
}

Source: https://www.onehub.com/blog/2009/03/06/rails-maintenance-pages-done-right/

Annora answered 23/4, 2015 at 7:9 Comment(4)
the status code returned to the post request in this case will still be a 405 in this case though, correct?Actino
@MohamedHafez nope, it should return a 503. It's explained fully in the linked source article, but from memory it's redirecting to the maintenance page and then explicitly throwing a 503Annora
Sadly this also redirects to the maintenance page on the browser url for me. I've been trying all day to rewrite and not redirect.Ukulele
It threw Invalid argument exception for error_page. I added status redirect, as in nginx manual: error_page 405 =503 /mymaintenancepage.html; and then it worked fine.Knurl
T
0

Maybe try forcing the 405 requests to be the actual URI:

error_page 405 = $uri;
Textualism answered 24/4, 2013 at 0:15 Comment(2)
Not sure what you mean. Actual URI results in 405. I want 503.Nationalist
See this if it works error_page 405 =503 /50x.html;Turro
A
0

Don't know why, but my POST requset only get 405 when using named location.

so I change @ to /, with internal, then GET/POST will get 503 with json.

error_page 503 /503;
location /503
{
    internal;

    root /path/to/config;
    try_files /503.json =404;
}

internal doc here

I am on nginx/1.24.0

Ashburn answered 17/2 at 3:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.