Простая настройка сервера Ruby с использованием Thin в качестве простого rhtml-сервера (например, Webrick) - PullRequest
0 голосов
/ 02 марта 2019

мой простой сервер Webrick обслуживает статические html и rhtml внедренные файлы ruby.Как мне добиться того же с многопоточным или многопроцессорным сервером Ruby, таким как Thin?

Настройка Webrick:

#!/usr/bin/ruby
# simple_servlet_server.rb
require 'webrick'
include WEBrick
s = HTTPServer.new(:Port => 8000)

# Add a mime type for *.rhtml files
HTTPUtils::DefaultMimeTypes.store('rhtml', 'text/html')

s.mount('/', HTTPServlet::FileHandler, './public_html')

['TERM', 'INT'].each do |signal|
 trap(signal){ s.shutdown }
end

s.start

Я установил Thin and Rack, мой config.ru читает HTML, но не рендеритrhtml документы?:

  use Rack::Static,
  :urls => ["/images", "/js", "/css"],
  :root => "public"

run lambda { |env|
  [
    200,
    {
      'Content-Type'  => 'text/html',
      'Cache-Control' => 'public, max-age=86400'
    },
    File.open('./public_html', File::RDONLY)
  ]

  HTTPUtils::DefaultMimeTypes.store('rhtml', 'text/html')      
}

1 Ответ

0 голосов
/ 22 марта 2019

TL; DR; - Динамический рубиновый контент (т. Е. .rhtml файлы) должен отображаться механизмом шаблонов;Встроенный движок, используемый WebRick - это движок Ruby ERB;Рендеринг динамических файлов перед отправкой ответа Rack.


  1. Я бы порекомендовал отделить статические файлы от динамических файлов.

    Это позволит оптимизироватьстатическая файловая служба, использующая либо обратный прокси-сервер (т. е. nginx), либо статический файловый сервер Ruby (т. е. йод).

    Общий подход заключается в следующем:

    • Поместите статические файлы в ./public.

    • Поместите динамические файлы в ./app/views.

  2. Ваше приложение Rackнужно будет обрабатывать динамические файлы, используя соответствующий процессор шаблонизатора.

    Для ваших .rhtml файлов я бы предположил , что это будет встроенный шаблонизатор ERB (естьхороший пост об этом здесь ).

Предполагая, что вы разместили свои динамические и статические файлы, как уже упоминалось, вы можете начать с файла config.ru, который выглядиткак это:

require 'erb'
require 'pathname'

ROOT ||= Pathname.new(File.dirname(__FILE__)).expand_path

module APP
  VIEWS = ROOT.join('app', 'views')
  def self.call(env)
    # prevent folder trasversal (security) and extract file name
    return [403, {}, ["Not Allowed!"]] if env['PATH_INFO'].index("..") || env['PATH_INFO'].index("//")
    filename = VIEWS.join(env['PATH_INFO'][1..-1])
    # make sure file exists
    return [404, {}, ["Not Found"]] unless File.exists?(filename)
    # process dynamic content
    template = IO.binread filename
    data = ERB.new(template).result(binding)
    return [200, {}, [data]]
  end
end

run APP

Далее вы можете запустить приложениеih iodine, который будет обрабатывать статическую файловую сервисную часть (в данном примере - однопоточный рабочий на ядро):

iodine -w -1 -t 1 -www public

Конечно, вы можете использовать промежуточное ПО Rack::Static, но оно должно бытьбыть значительно медленнее (отметьте это сами или протестируйте на предмет Thin) ...

... Я автор йода, так что я могу быть предвзятым.

EDIT

PS (примечание о безопасности и производительности)

Я бы пересмотрел механизм шаблонов.

ERB быстр и эффективен, однако он также позволяет выполнять код внутри шаблона.

Это может привести к сложному обслуживанию проекта, так как код просачивается в шаблон, делая код менее читаемым и сложным в обслуживании.

Я бы рассмотрел переход на шаблоны Mustache, которые препятствуют выполнению кода внутри шаблона..

Изменение механизма шаблонов также может повысить производительность.Рассмотрим следующий тест с использованием шаблонов усов со вкусом йода (которые предлагают агрессивный выход из HTML):

require 'iodine'
require 'erb'
require 'benchmark'

module Base
  ERB_ENG = ERB.new("<%= data %> <%= Time.now %>")
  MUS_ENG = Iodine::Mustache.new(nil, "{{ data }} {{ date }}")
  def self.render_erb(data)
    ERB_ENG.result(binding)
  end
  def self.render_mus(data)
    h = {data: data, date: Time.now.to_s }
    MUS_ENG.render(h)
  end
end

puts "#{Base.render_mus("hello")} == #{Base.render_erb("hello")} : #{(Base.render_mus("hello") == Base.render_erb("hello"))}"

TIMES = 100_000
Benchmark.bm do |bm|
  bm.report("Ruby ERB") { TIMES.times { Base.render_erb("hello") } }
  bm.report("Iodine  ") { TIMES.times { Base.render_mus("hello") } }
end

Результаты на моем компьютере были (чем ниже, тем лучше):

            user     system      total        real
Ruby ERB  1.701363   0.006301   1.707664 (  1.709132)
Iodine    0.256918   0.000750   0.257668 (  0.258190)

Опять же, поскольку я автор йода, я предвзят.Поиграйте и найдите то, что лучше для вас.

...