node.jsnginxx-accel-redirect

Nginx X-Accel-Redirect not working with node.js


I'm trying to set up authorized file access on nginx backed by node.js. For some reason all the examples don't work for me. I'm trying to server files from /data/private/files

My nginx configuration:

...
server {
    listen 4000;
    server_name localhost;

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

    location /files {
        root /data/private;
        internal;
}  

My node server.js:

var http = require('http');
http.createServer(function (req, res) {
  console.log(req.url);
  res.end('works');
}).listen(3000);

When I request http://localhost:4000/xyz then the request is correctly being passed on to node. When I request http://localhost:4000/files/test.jpg I just get a 404 and nothing gets passed to node. What am I doing wrong? When I commend out internal then test.jpg gets served correctly by nginx directly, so I assume the paths are correct?

I'm pretty sure I had this working at some point before but on a different server somewhere maybe with a different node and nginx version. Tried it with nginx 1.6.0 and 1.2.6, node v0.10.21. I've also added all the proxy_set_header and proxy_pass options that you find in all the examples, nothing works. I'm running this in a Vagrant based Ubuntu VM right now, but doesn't work on Mac either.

I know that I have to set the header through res.setHeader("X-Accel-Redirect", req.url);, but that's not the issue here as I don't even get to that phase where I could set the required header in node.


Solution

  • You misunderstand how internal and X-Accel-Redirect work.

    The main idea is that you go to some URL which is proxied to app. Then app decides whether you should get access to file or not. In former case it response with X-Accel-Redirect to protected url (one with internal).

    So you should go to some other URL, e.g. http://localhost:4000/get/files/test.jpg and your application could look like this:

    var http = require('http');
    http.createServer(function (req, res) {
      if (req.url.indexOf('/get/files/') == 0) {
        if (userHasRightToAccess()) {
          res.setHeader('X-Accel-Redirect', res.url.slice(4));
          res.end('');
        } else {
          // return some error
        }
      } else {
        console.log(req.url);
        res.end('works');
      }
    }).listen(3000);