Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Message "X-Accel-Mapping header missing" in Nginx error log

I am running a Rails 3 site on Ubuntu 8.04 with Nginx 1.0.0 and Passenger 3.0.7.

In my Nginx error.log I started seeing the message X-Accel-Mapping header missing quite a lot. Googling lead me to the docs of Rack::Sendfile and to the Nginx docs.

Now, my app can be accessed through several domains and I am using send_file in my app to deliver some files specific to the domain they are requested from, e.g., if you come to domain1.com/favicon.ico I look up the favicon in at public/websites/domain1/favicon.ico. This works fine and I don't think I need/want to get Nginx involved and create some private area where I store those files, as the samples in the Rack::Sendfile docs suggest.

How can I get rid of the error message?

like image 324
Manuel Meurer Avatar asked Jun 04 '11 13:06

Manuel Meurer


2 Answers

this message means that Rack::Sendfile disabled X-Accel-Redirect for you, because you have missing configuration for it in nginx.conf...

I'm using Nginx + Passenger 3 + Rails 3.1.

Gathered information from this pages I've figured it out:

http://wiki.nginx.org/X-accel

http://greenlegos.wordpress.com/2011/09/12/sending-files-with-nginx-x-accel-redirect

http://code.google.com/p/substruct/source/browse/trunk/gems/rack-1.1.0/lib/rack/sendfile.rb?r=355

Serving Large Files Through Nginx via Rails 2.3 Using x-sendfile

I have controller which maps /download/1 requests to storage files which have their own directory structure, like this: storage/00/00/1, storage/01/0f/15 etc. So I need to pass this through Rails, but then I need to use send_file method which will use X-Accel-Redirect to send the final file to the browser through nginx directly.

Within the code I have this:

send_file(
  '/var/www/shared/storage/00/00/01', 
  :disposition => :inline, 
  :filename => @file.name # an absolute path to the file which you want to send
)

I replaced the filename for this example purposes

Now I had to add these lines to my nginx.conf:

server {
    # ... 

    passenger_set_cgi_param HTTP_X_ACCEL_MAPPING /var/www/shared/storage/=/storage/; 
    passenger_pass_header X-Accel-Redirect;

    location /storage {
      root /var/www/shared;
      internal;
    }

    # ...
}

The path /storage is not visible from outside world, it is internal only.

Rack::Sendfile gets the header X-Accel-Mapping, extracts the path from it and replaces /var/www/shared/storage with /storage.... Then it spits out the modified header:

X-Accel-Redirect: /storage/00/00/01

which is then processed by nginx.

I can see this works correctly as the file is downloaded 100x faster than before and no error is shown in the logs.

Hope this helps.

like image 176
3 revs, 2 users 83% Avatar answered Nov 16 '22 00:11

3 revs, 2 users 83%


We used the similar technique as NoICE described, but i replaced the "hard-coded" directory containing all the files with the regular expression describing the folder containing the folders containing the files.

Sounds hard, yeah? Just take a look on these (/etc/nginx/sites-available/my.web.site):

location /assets/(.+-[a-z0-9]+\.\w+) {
    root /home/user/my.web.site/public/assets/$1;
    internal;
}

location /images/(.+)(\?.*)? {
    root /home/user/my.web.site/public/images/$1;
    internal;
}

This should be used with this check:

location / {
    # ...

    if (-f $request_filename) {
        expires max;
        break;
    }

    # ...
}

to prevent the statics from Rails processing.

like image 30
shybovycha Avatar answered Nov 16 '22 01:11

shybovycha