Nginx – Preserve http headers from Django using NGINX and Gunicorn

djangogunicornnginx

I'm setting some non-caching headers in a Django middleware to control caching of xhr request. Mostly because IE is caching ajax request heavily.

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

This works fine when I deployed my app using only Gunicorn in an dev environment. In the production environment we also run NGINX in front of Gunicorn, and it seems NGINX is overwriting the headers set by Django.

See this screenshots to see the how the headers change:

DEV Env.:

response headers in dev env.

PROD Env. with NGINX:

response headers in prod env.

Any idea what to change in the NGINX configuration in order that NGINX passes the headers set by Django?

nginx conf. looks like this:

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 conf. included via sub conf:

server {
    listen       80;
    server_name  localhost1;

location / {
    proxy_pass http://127.0.0.1:8000;
    }
}

Best Answer

Apparently you can set proxy_ignore_headers to get Nginx to not alter your headers.

proxy_ignore_headers Cache-Control Expires Pragma;

which may be the simplest way of fixing it. What you're seeing may be caused by this feature in Nginx:

Change: now nginx does not cache by default backend responses, if they have a "Set-Cookie" header line.

Presumably they didn't do that without some reason, but I can't explain why that feature was implemented.

However if you're trying to force all caching to be disabled because "IE is caching ajax request heavily" you may have a better solution in just appending a unique number to each Ajax request, which is a more resilient way of forcing clients to not cache responses.