Как монтировать статические файлы для Rack

Я хочу обслуживать статические файлы, а также динамическое содержимое через Rack. Раньше я использовал WEBrick без использования Rack с таким кодом, и это работало:

    @s = WEBrick::HTTPServer.new(
        Port: 3000,
        BindAddress: "localhost",
        Logger: WEBrick::Log.new(File::NULL),
        AccessLog: [nil, nil]
    )
    %w[INT TERM].each{|signal| trap(signal){@s.shutdown}}
    @s.mount("/", self)
    @s.mount("/resource/", WEBrick::HTTPServlet::FileHandler, "/")
    @s.start

В приведенном выше примере на запросы к localhost:3000 будет отвечать динамическое содержимое, а на запросы к localhost:3000/resource/path_to_file будет отвечать статический файл, расположенный в /path_to_file на моем компьютере.

Теперь я хочу переключиться на систему, использующую стойку с тонким сервером. Я написал следующее, но не смог получить статические файлы. Как его изменить, чтобы он работал?

    Rack::Handler::Thin.run(->env{
        h = Rack::Utils.parse_nested_query(env["QUERY_STRING"])
        # I tried the following three lines one at a time, but neither worked.
        use(Rack::Static, urls: "/resource/", root: "/") # First try
        Rack::File.new("/resource").call(env) # Second try
        Rack::Directory.new("/resource").call(env) # Third try
        [200, {}, [some_dyamically_generated_content]]
    }, Port: 3000)

Я знаю, что есть похожий вопрос: Как обслуживать статические файлы через Rack?, но я не смог заставить его работать. Я не знаю, как использовать Rack::Static, Rack::File или Rack::Directory. Пожалуйста, научите меня.


person sawa    schedule 10.01.2012    source источник


Ответы (2)


Вам нужно использовать Rack::Builder, чтобы использовать синтаксис use SomeMiddleware в обычном сценарии Ruby. (обычно используется в файле config.ru). Вам также потребуется run для вашего приложения. Обратите внимание, что ключ urls для Rack::Static принимает массив, а не одну строку:

require 'rack'
Rack::Handler::Thin.run(Rack::Builder.new {
    use(Rack::Static, urls: ["/resource/"], root: "/")
    run ->env{[200, {}, [some_dyamically_generated_content]]}
}, Port: 3000)

Здесь Rack::Builder берет ваше приложение ->env{[200, {}, [some_dyamically_generated_content]]}, добавляет к нему промежуточное ПО Rack::Static и создает новое комбинированное приложение, которое затем передается в Thin для запуска.

Rack::Static — это компонент промежуточного программного обеспечения, который можно добавить к существующим стоечным приложениям. Rack::File и Rack::Directory сами являются стоечными приложениями, а не промежуточным программным обеспечением (Rack::Static использует Rack::File внутри, как и Rack::Directory по умолчанию). Вы можете добиться того же эффекта, что и выше, используя Rack::File и команду map:

require 'rack'
Rack::Handler::Thin.run(Rack::Builder.new {
    map "/resource/" do
      run Rack::File.new "/"
    end
    map "/" do
      run ->env{[200, {}, [some_dyamically_generated_content]]}
    end
}, Port: 3000)

Более распространенный способ сделать это — поместить содержимое блока, переданного в Rack::Bundler.new, в файл config.ru:

use(Rack::Static, urls: ["/resource/"], root: "/") 
run ->env{[200, {}, [some_dyamically_generated_content]]}

Затем вы можете запустить это с thin start, который должен найти config.ru, если запустить из того же каталога, или вы можете использовать параметр -R, чтобы указать файл. Также можно использовать команду rackup, rackup -s thin, если вы хотите указать Thin в качестве сервера.

person matt    schedule 10.01.2012

Если вам не требуется аутентификация/авторизация перед обслуживанием файлов, вы должны иметь возможность добавлять файлы в /public и обслуживать их базовым сервером. Итак, если макет вашего приложения выглядит так

my_app/
  - app.rb
  - config.ru
  - public/
    - a_static_file.png
    - another_static_file.png

Как только вы запустите свое приложение (используя тонкий, webrick или apache или любой другой базовый сервер), вы можете получить доступ к статическим файлам из http://localhost:4567/a_static_file.png

person jacobsimeon    schedule 10.01.2012
comment
Я мог бы изучить это, но сейчас мне нужен доступ к определенным местам, не перемещая их все в /public. Спасибо за помощь. - person sawa; 11.01.2012