使用 NGINX 和 Gunicorn 保留 Django 的 http 标头

使用 NGINX 和 Gunicorn 保留 Django 的 http 标头

我在 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_headersto ,此问题已解决。on邮政为我指明了正确的方向。

相关内容