【问题标题】:Nginx + Rails + sendfile : file not foundNginx + Rails + sendfile:找不到文件
【发布时间】:2018-11-20 11:24:08
【问题描述】:

最近为 nginx+rails 设置 sendfile 时遇到问题。我们有一种已经被 nginx 处理的文件下载,我们想添加第二条规则来处理另一个位置的另一种文件,但到目前为止我们没有成功。

Ruby 控制器:

def download_file
  send_file("/srv/www/myapp/shared/tmp/directory/file.zip")
end

环境配置文件:

Rails.application.configure do
  # ..  
  config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
  # ..
end

Nginx 配置:

upstream myapp {
  server 127.0.0.1:9292;
}

server {
  listen 80;    
  server_name myapp.tld;

  client_max_body_size 10M;

  root /srv/www/myapp/current/public; 

  # This first block works perfectly
  location /__working_file {
    internal;
    alias /var/lib/myapp;
  }    

  # This second block does not work at all
  location /__new_files {
    internal;
    alias /srv/www/myapp/shared/tmp/directory;
  }

  location / {
    root /srv/www/myapp/current/public;
    try_files $uri @app;
  }

  location @app {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;

    proxy_set_header X-Sendfile-Type X-Accel-Redirect;
    # This first rule works perfectly
    proxy_set_header X-Accel-Mapping /var/lib/myapp/=/__working_file/;
    # This second rule doesn't
    proxy_set_header X-Accel-Mapping /srv/www/myapp/shared/tmp/directory/=/__new_files/;

    proxy_pass_header Server;
    proxy_read_timeout 300;

    proxy_pass http://myapp;
  }
}

结果

当访问控制器动作时,send_file 命令被触发,然后我们在浏览器中得到一个“找不到文件”,没有下载任何东西,rails 日志显示如下:

Sent file /srv/www/myapp/shared/tmp/directory/file.zip (0.4ms)
Completed 200 OK in 169ms (ActiveRecord: 37.5ms)
Started GET "/srv/www/myapp/shared/tmp/directory/file.zip" for 109.190.197.126 at 2018-11-20 11:34:44 +0100

ActionController::RoutingError (No route matches [GET] "/srv/www/myapp/shared/tmp/directory/file.zip"):

该文件确实存在并且可读,但 nginx 似乎无法访问它。有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails nginx x-accel-redirect


    【解决方案1】:

    问题出在两个X-Accel-Mapping 的设置方式上。 Rack 确实能够处理自 this PR #1187 合并以来的多个映射。

    不过,截止到今天,这个PR已经合并到master上但还没有发布(2.0.6目前是最新版本)

    唯一的一点是,设置多个映射的正确方法是使用单个proxy_set_header 规则,并用逗号分隔每个映射,如下所示:

    proxy_set_header X-Accel-Mapping, /var/lib/myapp/=/__working_file/,/srv/www/myapp/shared/tmp/directory/=/__new_files/
    

    【讨论】:

      【解决方案2】:

      在路由时它没有得到 .您必须提供正确的上班路线。

      【讨论】:

        猜你喜欢
        • 2013-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 2016-02-18
        • 2017-09-05
        • 1970-01-01
        • 2016-06-30
        相关资源
        最近更新 更多