node.jsnginxx-accel-redirect

How to forward url parameters from Nginx to my server's API so I can allow/disallow users to view certain files?


I'm trying to create an "allowed users only" section and I managed to get this far, but I'm stuck.

I use auth_request module of Nginx and Express.js.

How can I send the requested url to my api route?

"/" is the generic URL, but /api/:filename should be fired only when a visitor tries to access a file, no matter what the file's location / URL is. In short, what I want to do is, "okay, I'm Nginx and I see that some visitor tries to access this file (or files, it checks individually). let's pass this file's name to Express.js server and let it check whether this user is allowed to see this image or not. If it says 200, I'll allow it. If it's 403, then no."

app.get('/api/:filename', function(req,res,next) {
  // This part decides what you're allowed to see.
  // Redis database query. Returns 0 or 1. 
  // 1 means 200, 0 means 403.
  res.sendStatus(200); 
  // It works if I omit :filename part, so this part is done in theory, 
  // but we didn't get the file name, so right now all we have is "yes
  // to all" or "no to all", it's not dynamic.
});

The question is, I don't know how to pass the requested url parameter from Nginx to my Express.js app (e.g. image.jpg, video.mp4 in http://localhost/api/:filename format) so I can check user's permission against database and return a dynamic response for every file.

Here's my Nginx config.

upstream localhost {
  ip_hash;
  server 127.0.0.1:8000;
  server 127.0.0.1:8001;
  server 127.0.0.1:8002;
  server 127.0.0.1:8003;
}

server {
  listen 80;
  server_name localhost;

  location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$ {
    root images;
    auth_request /api; // How to append requested filename to this URL?
  }

  location / {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_pass http://localhost;
  }
}

EDIT 1

location = /api {
  proxy_pass http://localhost;
  proxy_pass_request_body off;
  proxy_set_header Content-Length "";
  proxy_set_header X-Original-URI $request_uri;
}

Solution

  • Define a custom location for "/api" and append /api$request_uri (original uri) to proxy_pass;

    location = /api {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_pass http://localhost/api$request_uri;
    }