Skip to content

Instantly share code, notes, and snippets.

@fkurz
Last active March 18, 2019 20:08
Show Gist options
  • Save fkurz/7ff47ebe6b7f6cf2314674695e94950e to your computer and use it in GitHub Desktop.
Save fkurz/7ff47ebe6b7f6cf2314674695e94950e to your computer and use it in GitHub Desktop.
Snippet: Nginx configuration for POST requests to static files

Nginx configuration for POST requests to static files

Problem

Nginx doesn't allow serving static content when responding to POST requests.

Solution

The solution first creates an HTTP 405 error for all requests (including POST requests) to a given location and then simply returns the result of a proxy pass GET request to the static resource instead of the error page.

Nginx Configuration File

Note: You have to substitute the variables (e.g. <server-name>) in order to apply the configuration file to your use case.

server {
  listen 443 ssl;

  root /usr/share/nginx/html;
  index index.html;

  server_name <server-name>;
  ssl_certificate /etc/nginx/ssl/tls.crt;
  ssl_certificate_key /etc/nginx/ssl/tls.key;

  # Using POST for static files is not supported by Nginx. We can however force and intercept a 405 error and reverse proxy the static content server listening on port <server-port>.
  error_page 405 =200 @post_static;
  location @post_static {
    # optional: `rewrite ^ <rewrite-rule> break;`
    proxy_pass http://<server-name>:<server-port>;
    proxy_redirect off;
    proxy_method GET;
  }

  # Force a 405 error to intercept
  location <target-location> {
    return 405; 
  }
}

server {
  listen <server-port>;
  server_name <server-name>;

  root <data-root>;
  index index.html;
}

Details of the Solution

We are adapting the solution described here. Note that in contrast to the linked solution the upstream server entry was not required. The configuration is intended for an HTTPS server configuration but can be adapted for HTTP.

We essentially need to take three steps to set up POST requests to static files:

  1. Force a 405 error for requests to the target location <target-location>

    location <target-location> {
        return 405; 
    }
    

    This location maps to the static content you want to return on POST requests.

  2. Intercept the 405 error and redirect to the pseudo location @post_static

     error_page 405 =200 @post_static;
     location @post_static {
       # optional: `rewrite ^ <rewrite-rule>;`
       proxy_pass http://<server-name>:<server-port>;
       proxy_redirect off;
       proxy_method GET;
     }
    

    The @post_static entry reverse proxies the request using GET to the static content server (described next). Note that you can additionally rewrite the request URL if necessary.

  3. Configure a static content server entry on a different port

    server {
      listen <server-port>;
      server_name <server-name>;
    
      root <data-root>;
      index index.html;
    }
    

    The <data-root> variable should point to the folder containing the static content. Requests to this server simply return files under location <data-root>/<url-path> (if they exist).

Notes

405 Error

The solution rests on raising a 405 error with the following configuration entry:

 location <target-location> {
    return 405; 
 }

We are not specifically checking for request type, so requests to this location with other request methods will also raise an error. This is fine as long the location only accepts POST requests anyway. Otherwise additional configuration is necessary.

OpenResty

A better solution than the one described above may be using OpenResty. You can use Lua code to create the response content and won't have to use the somewhat hacky 405 error recovery mechanism.

Sources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment