nginx not returning Cache-Control header from upstream gunicorn
nginx not returning Cache-Control header from upstream gunicorn
I'm using WhiteNoise to serve static files from a Django app running under gunicorn. For some reason, the Cache-Control
and Access-Control-Allow-Origin
headers returned by the gunicorn backend are not being passed back to the client through the nginx proxy.
Cache-Control
Access-Control-Allow-Origin
Here's what the response looks like for a sample request to the gunicorn backend:
% curl -I -H "host: www.myhost.com" -H "X-Forwarded-Proto: https" http://localhost:8000/static/img/sample-image.1bca02e3206a.jpg
HTTP/1.1 200 OK
Server: gunicorn/19.8.1
Date: Mon, 02 Jul 2018 14:20:42 GMT
Connection: close
Content-Length: 76640
Last-Modified: Mon, 18 Jun 2018 09:04:15 GMT
Access-Control-Allow-Origin: *
Cache-Control: max-age=315360000, public, immutable
Content-Type: image/jpeg
When I make a request for the same file via the nginx server, the two headers are missing.
% curl -I -H "Host: www.myhost.com" -k https://my.server.com/static/img/sample-image.1bca02e3206a.jpg
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 02 Jul 2018 14:09:25 GMT
Content-Type: image/jpeg
Content-Length: 76640
Last-Modified: Mon, 18 Jun 2018 09:04:15 GMT
Connection: keep-alive
ETag: "5b27758f-12b60"
Accept-Ranges: bytes
My nginx config is pretty much what is documented in the gunicorn deployment docs, i.e. I haven't enabled nginx caching (nginx -T | grep -i cache
is empty) or done anything else I would think is out of the ordinary.
nginx -T | grep -i cache
What am I missing?
location /
You haven't enabled caching in Nginx and you want to know why it's not returning caching directives in it's response headers? A proxy server isn't just a pipe which your connection flows through unchanged to it's destination.
– miknik
Jul 2 at 22:19
@AlexandrTatarinov Yes! Thanks :-) I'm so used to defining a "location /static" in other scenarios that I assumed, because I had left it out, nginx was not handling the file. I forgot about "root"...
– Will Harris
Jul 3 at 6:59
2 Answers
2
The problem is that you have
location / {
try_files $uri @proxy_to_app;
}
directive in nginx config, so nginx just serves files himself and gunicorn doesn't even knows about it, and of course can't add headers.
It turns out I had forgotten the root
directive I had configured many months ago, which was now picking up the static files. My error was in assuming that since I hadn't configured a location /static
directive, nginx would be proxying all requests to the backend.
root
location /static
The solution for me was to remove the $uri
reference from the try_files
directive:
$uri
try_files
location / {
try_files /dev/null @proxy_to_app;
}
Alternatively, I could have simply put the contents of the @proxy_to_app
location block directly inside the location /
block.
@proxy_to_app
location /
Thanks to Alexandr Tatarinov for the suggestion in the comments.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
does gunicorn actually get the request? can you see some sort of logs? maybe nginx just serves files himself? there is
location /
block in default config under your link.– Alexandr Tatarinov
Jul 2 at 19:54