我在 Django 中间件中设置了一些非缓存标头来控制 xhr 请求的缓存。主要是因为 IE 大量缓存 ajax 请求。
class NeverCacheXhrMiddleware(object):
"""
sets no-cache headers for all xhr requests
xhr requests must send the HTTP_X_REQUESTED_WITH header to
be identified correctly as a xhr request using .is_ajax()
see: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers
"""
def process_response(self, request, response):
if request.is_ajax():
#add_never_cache_headers(response)
#patch_cache_control(response, no_cache=True)
response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response['Pragma'] = 'no-cache'
response['Expires'] = '0'
return response
当我在开发环境中仅使用 Gunicorn 部署应用程序时,此方法运行良好。在生产环境中,我们还在 Gunicorn 之前运行 NGINX,似乎 NGINX 正在覆盖 Django 设置的标头。
请查看以下屏幕截图来了解标题如何变化:
DEV 环境:
使用 NGINX 的 PROD 环境:
你知道该如何更改 NGINX 配置以便 NGINX 传递 Django 设置的标头吗?
nginx 配置如下:
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
include /path/to/sub_conf/*.conf;
}
nginx 服务器配置通过子配置包含:
server {
listen 80;
server_name localhost1;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
答案1
显然你可以设置proxy_ignore_headers让 Nginx 不改变你的标题。
proxy_ignore_headers Cache-Control Expires Pragma;
这可能是修复此问题的最简单的方法。您看到的情况可能是由 Nginx 中的此功能引起的:
Change: now nginx does not cache by default backend responses, if they have a "Set-Cookie" header line.
大概他们这样做是有原因的,但我无法解释为什么要实现这个功能。
但是,如果您尝试强制禁用所有缓存,因为“IE 正在大量缓存 ajax 请求”,那么您可能有一个更好的解决方案,即在每个 Ajax 请求后附加一个唯一的编号,这是一种强制客户端不缓存响应的更有弹性的方法。
答案2
问题不在于 nginx 没有传递 django 源中设置的标头,而在于 nginx 删除了所有带有下划线的客户端标头。
HTTP_X_REQUESTED_WITH
由于 Django在调用时寻找标头request.is_ajax()
,因此该请求从未被识别为 ajax 请求,因此未设置 no-cache 标头。
def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
通过在 nginx 配置中设置underscores_in_headers
to ,此问题已解决。on
邮政为我指明了正确的方向。