Nginx 405 not using specified error_page (static contents)

Predominant asked:

I’ve got a webserver that is designed to return 503 for all content except the favicon requests. This is a failover server that is set as a lower priority on load balancers. In the event that backend application servers are all offline, requests will overflow onto this web server, serving a 503 and some static content apologising for the service outage.

Its working fine for GET requests. However, its returning 405 default responses when a PUT/POST request is sent to the server.

Here is a snippet of my configuration:

# FILE: nginx.conf
daemon off;
pid /hab/svc/sorry-web/var/pid;
worker_processes auto;

events {
  worker_connections 512;
http {
  rewrite_log on;

  # Temporary files
  client_body_temp_path /hab/svc/sorry-web/var/client-body;
  fastcgi_temp_path /hab/svc/sorry-web/var/fastcgi;
  proxy_temp_path /hab/svc/sorry-web/var/proxy;
  scgi_temp_path /hab/svc/sorry-web/var/scgi_temp_path;
  uwsgi_temp_path /hab/svc/sorry-web/var/uwsgi;

  # Mime Types
  include /hab/svc/sorry-web/config/mime.types;

  server_tokens off;
  more_clear_headers Server;
  server_names_hash_bucket_size 256;

  variables_hash_max_size 8192;
  variables_hash_bucket_size 512;

  # GZip
  gzip on;
  gzip_http_version 1.1;
  gzip_comp_level 2;
  gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

  # Default server
  include /hab/svc/sorry-web/config/default_server;
# FILE: default_server.conf
server {
  listen 7003 default_server;
  server_name _;
  error_page 405 502 503 504 =503 @content;
  root /hab/pkgs/sorry/sorry-web/0.3.0/20200803032212/htdocs/default/busy;
  location @content {
    try_files $uri /index.html =404;
  location / {
    try_files __force_503__.html =503;
  include /hab/svc/sorry-web/config/favicon.conf;

And the response from a POST request:

# curl -vvv -XPOST http://localhost:7003/something
*   Trying
* Connected to localhost ( port 7003 (#0)
> POST /something HTTP/1.1
> Host: localhost:7003
> User-Agent: curl/7.68.0
> Accept: */*
* Mark bundle as not supporting multiuse
< HTTP/1.1 405 Not Allowed
< Date: Mon, 03 Aug 2020 03:22:41 GMT
< Content-Type: text/html
< Content-Length: 154
< Connection: keep-alive
<head><title>405 Not Allowed</title></head>
<center><h1>405 Not Allowed</h1></center>
* Connection #0 to host localhost left intact

My answer:

This happens because you specified a named location in error_page. In this case the request method is not changed, but passed on to that location in an internal redirect. So it is effectively trying to POST to a static file. Thus you get a 405 because nginx could not POST to a static file to get the desired error_page. (This is really meant for use when the error page will be dynamically generated by some web application.)

If you simply want to serve a static content to all such requests, point to the desired document directly in error_page rather than a named location.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.