Caching POST requests in NGinx (NGinx)

Ordinarily, you will not want to cache POST requests. RFC 2616 does allow, though, for the idea that responses to a POST may sometimes be cacheable.

Generally speaking, whether you consider POST cacheable will depend on what happens on the application back-end in response to that POST - if something is changed as a result then you'll almost certainly not want to cache, whereas if POST is being used to submit (say) search criteria, then you may be happy caching it.

My usecase was the one described above - on a search page, the search query is submitted via AJAX using POST - this means that if you navigate off the page and then click back, you need to wait for the search to run again. A short cache life on the request helps mitigate that.

In order to cache POST requests in NGinx you need to do two things

  • Tell Nginx to consider the method POST cacheable
  • Include the request body (i.e. the data submitted via POST in the cache key

The latter of these is important - it means you'll have a different cached entity for different submissions. However, you should be aware that POST bodies can be quite large, so calculating the cache key for these could be quite expensive (i.e. there's a potential DoS vector here)

Details

  • Language: NGinx

Snippet

proxy_cache_valid  200  45m;   # Cache 200's for 45 minutes 
proxy_cache_methods POST;      # Allow caching when method is POST
proxy_cache_key "$request_uri|$request_body";  # Include the post data in the cache key calculation

Usage Example

location /search {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_pass https://search_backend;

        proxy_cache static-cache;
        proxy_cache_lock on;
        proxy_cache_valid  200  45m;
        proxy_cache_use_stale updating;
        proxy_cache_methods POST;
        proxy_cache_key "$request_uri|$request_body";

        # Add a header so we can see whether the cache is working
        add_header X-Cached $upstream_cache_status;
        add_header X-Clacks-Overhead "GNU Terry Pratchett";
}