I use nginx as a reverse proxy and I would like it to cache POST requests. My back-end is correctly configured to return appropriate cache-control headers for POST requests. In nginx I have configured:
proxy_cache_methods POST;
proxy_cache_key "$request_method$request_uri$request_body";
This works great for small HTTP POST requests. However I started noticing that for large requests (e.g. file uploads) it seems like the $request_body
is ignored in the proxy_cache_key
. When a form containing a file upload is submitted twice with completely different data, nginx will return the cached result.
What could cause this? How can I configure nginx to use the $request_body
(or a hash of $request_body
) in the proxy_cache_key
even for large POST requests?
You can get around this by telling Nginx to forward the request straight to Apache, which runs on port: 9080.
Enabling nginx caching is recommended only for websites with a specific profile (for example, popular blogs or news websites): High traffic. The content is updated every few seconds.
Cache both static and dynamic content from your proxied web and application servers, to speed delivery to clients and reduce the load on the servers.
Some new directives are added, let's go through them one by one. Nginx caches the responses in the disk, proxy_cache_path specifies the path where the responses are to be stored. proxy_cache defines the shared memory zone used for storing the cache keys and other metadata. proxy_cache_key defines the caching key.
So it turns out that when $content_length > client_body_buffer_size
,
then the request body is written to a file and the variable $request_body == ""
.
See also http://mailman.nginx.org/pipermail/nginx/2013-September/040442.html
Rather than using the $request_body within the proxy_cache_key, you may more simply use $content_length. Of course, it comes with its own limitation, but if you know which query you will receive, it can be also a very interesting workaround.
proxy_cache_key "$scheme$request_method$host$request_uri$content_length";
You may alternatively use $request_body as well to keep the desired behavior for smaller request payload:
proxy_cache_key "$scheme$request_method$host$request_uri$request_body$content_length";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With