Can nginx be made to cache upstream responses containing an X-Accel-Redirect header?

I am using nginx as a reverse proxy in front of application server. The application responds with an X-Accel-Redirect header telling nginx which static file to serve. What I'd like to be able to do is have nginx cache some of these upstream responses so it can serve the correct file without hitting the app server.

Unfortunately, this doesn't work: nginx seems to refuse to cache any response with an X-Accel-Redirect header. If I don't use X-Accel-Redirect and get the app server to return the file itself then caching works perfectly. However this isn't very efficient as the app server then has to read the file off disk and send it to nginx, which then writes the file back to disk (in its cache) and sends it to the client.

Here is a stripped down version of my nginx config:

proxy_cache_path /tmp/nginx-cache keys_zone=testzone:10m;

server {
    location / {
        proxy_cache testzone;
        proxy_pass http://localhost:8000/;
    }

    location /static-files/ {
        internal;
        alias /var/static-files/;
    }
}

Does anyone know if what I'm attempting to do is possible? My suspicion is that when nginx spots the X-Accel-Redirect header it immediately jumps to processing the supplied URI and skips the normal caching logic, but it would be nice to have this confirmed.


Solution 1:

I had a similar situation where nginx didn't want to cache my stuff, since a webapp I was using was trying to set cookies I didn't want to set.

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers

Unless you want to hire someone to hack the source-code, what you might try doing is have nginx be a proxy to itself, and then to the web-app.

With the one in the middle, you ignore the X-Accel-Redirect header, and thus cache should engage again.

With the one on the front, you don't do caching, but proxy requests to the one in the middle that caches X-Accel-Redirect responses.

I don't see any reason why something like this shouldn't work! :-)