POST response caching does not work in nginx

2.6k Views Asked by At

My task is to implement microcaching strategy using nginx, that is, cache responses of some POST endpoints for a few seconds.

In http section of the nginx.conf I have the following:

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;

Then I have location in server:

    location /my-url/ {
      root dir;
      client_max_body_size 50k;
      proxy_cache cache;
      proxy_cache_valid 10s;
      proxy_cache_methods POST;
      proxy_cache_key "$request_uri|$request_body";
      proxy_ignore_headers Vary;

      add_header X-Cached $upstream_cache_status;

      proxy_pass http://my-upstream;
    }

The application located at my-upstream outputs Cache-Control: max-age=10 which, if I understand correctly, should make the responses cacheable.

But when I make repetitive requests using curl in short time (less than 10 seconds)

curl -v --data "a=b&c=d" https://my-host/my-url/1573

all of them reach the backend (according to backend logs). Also, X-Cached is always MISS.

Request and response follow:

> POST /my-url/1573 HTTP/1.1
> Host: my-host
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 113
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 113 out of 113 bytes
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 08 May 2018 07:16:10 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Keep-Alive: timeout=60
< Vary: Accept-Encoding
< X-XSS-Protection: 1
< X-Content-Type-Options: nosniff
< Strict-Transport-Security: max-age=31536000
< Cache-Control: max-age=10
< Content-Language: en-US
< X-Cached: MISS

So the caching does not work.

  1. What am I doing wrong here?
  2. Is there any logging facility in nginx that would allow to see why it chooses not to cache a response?
2

There are 2 best solutions below

1
Roman Puchkovskiy On BEST ANSWER

It turned out that the following directive (which was defined globally) prevented caching from working:

proxy_buffering off;

When I override it under location config with proxy_buffering on;, caching starts working.

So, to make caching work with POST requests, we have to do the following:

  1. Output Cache-Control: public, max-age=10 header on the server
  2. Add proxy_cache_path config and location config in nginx (examples are given in the question text)
  3. Make sure that proxy_buffering is on for the location on which we want to have caching enabled.
0
Adam On

To elaborate on @Roman Puchkovskiy's answer above - my origin server was returning the following headers:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache

I configured my server to return this instead:

Cache-Control: max-age=3600, public

And now Nginx behaves as expected ✅

I first tried adding this directive to my nginx.conf:

...
location /blah {
  ...
  proxy_ignore_headers Cache-Control;
}

But it looks like that directive doesn't work the way I thought it would.

Note that I wasn't required to add proxy_buffering on to my nginx.conf so it seems I wasn't affected by that issue.