Nginx - 405 NOT ALLOWED - fastcgi timeout Nginx - 405 NOT ALLOWED - fastcgi timeout wordpress wordpress

Nginx - 405 NOT ALLOWED - fastcgi timeout


tl;dr—Your WordPress is too slow. Jump to the bottom to see how you can make NGINX return you the proper 504 GATEWAY TIMEOUT status code.

The longer version: You have a bunch of separate issues working together in an unhelpful way.

1. WordPress, your upstream server, is not responding fast enough

It takes longer than 4 minutes, that's why you see a 110: Connection timed out in your logs. The solution to the slowness is to speed up WordPress. As a workaround, you could give it more time to process the request. To do that, increase the number in your fastcgi_read_timeout 240; rule. Note that the timeout is given in seconds, so if you're fine with waiting 10 minutes, set this to 600.

I'd advise against increasing the timeout, though. You should really address the performance issue itself. Such long requests block resources in NGINX and WordPress, and therefore allow you to be DDoSed quite easily, even accidentally by yourself.

Because your upstream takes too long, NGINX would respond with a 504 GATEWAY TIMEOUT. It cannot because…

2. POST requests cannot be answered with static files

In your error_page location, you're telling NGINX to use static files to handle the requests. That's fine for GET or HEAD, but it does not work for POST, because it would ask NGINX to overwrite/create files. That's neither intended nor supported by NGINX. (The request would also fail using other modifying verbs such as PUT and DELETE, for the same reason.)

Note that you are using a named location, @error_page, for which the method remains POST, as the manual says:

If there is no need to change URI and method during internal redirection it is possible to pass error processing into a named location.

You already know part of this, which is why you added the error_page 405 =200 $uri; rule. Unfortunately, this did not save you, because…

3. Internal error_page redirects are not recursive by default

This is not mentioned in the documentation for the error_page manual, as far as I can see, but it is mentioned in the docs of the following directive:

Workaround: Enable recursive error_page redirects

The directive recursive_error_pages allows you to handle errors that occur while a previous error is being handled. From the docs:

 Enables or disables doing several redirects using the error_page directive. The number of such redirects is limited.

If you enable this, by putting recursive_error_pages on; into your server block, you'll allow the error_page 405 directive to kick in.

Unfortunately, since you're still requesting the same resource with your $uri part, WordPress will be queried again for the same URL, this time with a GET request. No idea how your WordPress handles that, but chances are the error that will occur then will not help you to debug this.

This really is just jumping around the problem; what you should get is the original 504. Therefore, I suggest you do the following, instead of enabling recursive error page redirects:

Solution: Use GET to fetch your error pages

I assume you still want to return your error.html even on a POST request. For that you need to force NGINX to drop the POST and handle the error with GET, so that static files can be used. The only way I've found to make this happen is to not use a named location (the ones with @ at the beginning), but an internal one instead.

To use this option, change your @error_page location to include a pseudo-path and the internal directive, for example like so:

    location /error_page {        internal;        root /usr/syno/share/nginx;        rewrite (.*) /error.html break;    }

Afterwards, modify the error_page directive, to use the new location:

    error_page 403 404 500 502 503 504 /error_page;

Resources: A helpful discussion on the NGINX mailing list.