Rails XSendfile via Nginx

Francis Daly francis at daoine.org
Wed May 9 22:37:58 UTC 2012

On Wed, May 09, 2012 at 11:21:23PM +0200, Ari King wrote:

Hi there,

> I modified the applications url paths to--
> www.foo.bar.com/recipes/:id/video/:filename
> > Probably you want to include "~" in your second location directive:
> Tried adding the (regex) tilde, but that did not solve the issue.

Ok, so we'll have to try to find exactly what you want/expect to happen.

We can then compare it to what currently happens, and see what to change
to make things match.

> > So: if the client wishes to get access to the file "test.video", what
> > public url will they use to access it?
> www.foo.bar.com/recipes/1/video/example_one.ogg

For this request, the "location" is "/recipes/1/video/example_one.ogg".

If your configuration is:

  location / {}
  location /recipes/(.*)/video {}

then that will match the first location.

If your configuration is

  location / {}
  location ~ /recipes/(.*)/video {}

then it will match the second location.

If that request is processed in the first location, I think it will try
to serve the file


if it exists, or else proxy_pass to


If the request is processed in the second location, it will return 404
because that location is marked "internal".

> > What is the X-Accel-Redirect header that the backend sends to nginx?
> How can I find this out? When I curl directly to the backend server I
> get these headers: see http://pastebin.com/CVLjhLRJ

I suspect that your backend (rails?) server pays attention to the various
headers you have configured using "proxy_set_header", and will respond
differently if they are present. If you repeat the curl command with
some or all of those, you might see a different response.

I'd probably look in the debug log to find what nginx thinks is going on;
either that or use something like tcpdump to see what is happening.

> > And where on the filesystem is the file "test.video"?
> The video files are stored according to their respective ids; note the
> paths are different AFTER the "videos" directory --
> /var/www/app/current/uploads/videos/1/original/example_one.ogg
> /var/www/app/current/uploads/videos/2/original/example_two.ogg

Ok, so it's a file path which can be derived from components of the url.

> This leads me to believe the issue is with the alias mapping, i.e.
> /var/www/app/current/uploads/videos/=/video;

What's that?

I see it in your

      proxy_set_header  X-Accel-Mapping   /var/www/app/current/uploads/videos/=/video;

directive, but that's nothing to do with nginx (unless I'm missing something).

> I tried changing it to the following, but that did not work. I'm not
> even sure if that type of mapping is allowed. Does anyone know if alias
> mapping allows regex? I couldn't find any thing in the docs.

I'm not aware of alias mapping.

The docs for the nginx alias directive are at http://nginx.org/r/alias

You can use regex captures in the alias directive.

> /lessons/(.*)/video/=/var/www/app/current/uploads/videos/$1/original/;

I'm still unclear on what it is that you want.

When someone requests the url


do you want nginx to directly send them the contents of the file 


or do you want your rails backend server to do some processing and
decide whether or not they should be sent the contents of that file,
or do you want something else to happen? (If "something else", then
describe what else.)

If we can start with a clear understanding of the answer to that question,
then the rest of the configuration may become obvious.

Francis Daly        francis at daoine.org

More information about the nginx mailing list