Если вы программист на Ruby, который занимался любой веб-разработкой, вы почти наверняка использовали Rack , знаете ли вы это или нет, так как это основа, на которой строится большинство веб-фреймворков Ruby (Rails, Sinatra и т. Д.). на. Давайте углубимся в некоторые основные концепции Rack и даже создадим небольшое приложение или два.
Что такое стойка, точно?
Стойка это несколько вещей, на самом деле:
- интерфейс веб-сервера
- протокол для создания и создания веб-приложений
- коллекция утилит промежуточного программного обеспечения
Интерфейс веб-сервера
Что приятно в Rack, так это то, что он предоставляет стандартизированный способ для приложений Ruby общаться с веб-серверами, абстрагировать работу сервера (прослушивание порта, принятие соединений, анализ HTTP-запросов и ответов и т. Д.), Чтобы вы могли сосредоточиться на том, что делает ваше приложение.
Протокол
Протокол Rack очень прост: приложение Rack — это просто объект Ruby с методом call
. Этот метод должен принимать хеш среды, описывающий входящий запрос, и возвращать массив из трех элементов в виде: [status, headers, body]
, где:
-
status
— это код статуса HTTP. -
headers
— это хеш HTTP-заголовка для ответа. -
body
— это фактическое тело ответа (например, HTML, который вы хотите
дисплей). Тело также должно отвечатьeach
.
Самый простой способ понять протокол Rack — взглянуть на некоторый код.
Во-первых, получите гем стойки и создайте каталог:
1
2
3
|
$ gem install rack
$ mkdir hellorack
$ cd hellorack
|
Теперь создайте файл с именем config.ru
и заполните его следующим config.ru
:
01
02
03
04
05
06
07
08
09
10
11
12
|
class Hello
def self.call(env)
[ 200, # 200 indicates success
{«Content-Type» => «text/plain»}, # the hash of headers
[«Hello from Rack!»] # we wrap the body in an Array so
# that it responds to `each`
]
end
end
# Tell Rack what to run our app
run Hello
|
Сохраните файл, откройте свой терминал и выполните команду rackup
:
1
2
3
4
|
$ rackup
[2012-12-21 17:48:38] INFO WEBrick 1.3.1
[2012-12-21 17:48:38] INFO ruby 1.9.2 (2011-07-09) [x86_64-darwin11.0.1]
[2012-12-21 17:48:38] INFO WEBrick::HTTPServer#start: pid=1597 port=9292
|
Несколько нижних строк вывода в приведенном выше коде сообщают, что Rack запускает ваше приложение на порту 9292, используя встроенный веб-сервер Ruby WEBrick. В браузере укажите http: // localhost: 9292, чтобы увидеть приветственное сообщение от Rack.
Убейте приложение (ctrl-c) и давайте поговорим о том, что здесь происходит.
Когда вы запускаете команду rackup
, Rack ищет rackup
конфигурации rackup
(условно называемый config.ru
, но вы можете называть его как угодно). Затем он запускает веб-сервер (по умолчанию WEBrick) и запускает ваше приложение.
Этот протокол является основой, на которой строятся популярные фреймворки, такие как Rails и Sinatra. Они выполняют функциональность слоя, такую как рендеринг шаблонов, диспетчеризация маршрутов, управление соединениями с базой данных, согласование контента и т. Д. Поверх этой основной абстракции.
Как они это делают, это то, что подводит нас к концепции промежуточного программного обеспечения.
Промежуточное
Промежуточное ПО дает вам возможность создавать приложения Rack вместе.
Промежуточное программное обеспечение (да, оно единственное и множественное число) — это просто приложение Rack, которое инициализируется с другим приложением Rack. Вы можете определить различное промежуточное программное обеспечение для выполнения разных заданий, а затем объединить их вместе для выполнения полезных задач.
Например, если у вас есть приложение на Rails (скорее всего, если вы разработчик на Ruby), вы можете cd
в приложение и запустить rake middleware
команды rake middleware
чтобы увидеть, какое промежуточное программное обеспечение использует Rails:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
$ cd my-rails-app
$ rake middleware
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fcc4481ae08>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
run MyRailsApp::Application.routes
|
Каждый запрос, поступающий в это приложение, начинается сверху этого стека, пузырится вниз, попадает в маршрутизатор внизу, который отправляет контроллеру, который генерирует какой-то ответ (обычно некоторый HTML), который затем пузырится обратно через стек перед отправкой обратно в браузер.
Пример промежуточного программного обеспечения
Ничто так не способствует пониманию новой концепции, как кодирование, поэтому давайте создадим очень простое промежуточное ПО, которое просто преобразует тело ответа в верхний регистр. Откройте наш файл config.ru
и добавьте следующее:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class ToUpper
# Our class will be initialize with another Rack app
def initialize(app)
@app = app
end
def call(env)
# First, call `@app`
status, headers, body = @app.call(env)
# Iterate through the body, upcasing each chunk
upcased_body = body.map { |chunk|
# Pass our new body on through
[status, headers, upcased_body]
end
end
# This is the same Hello app from before, just without all the comments
class Hello
def self.call(env)
[ 200, {«Content-Type» => «text/plain»}, [«Hello from Rack!»] ]
end
end
use ToUpper # Tell Rack to use our newly-minted middleware
run Hello
|
rackup
команду rackup
и посетите http: // localhost: 9292, чтобы увидеть наше новое промежуточное ПО в действии.
Здесь Rack создал приложение Rack, составленное из приложений ToUpper
и Hello
. Внутри Rack существует класс Builder
который эффективно создает новое приложение, выполняя эквивалент:
1
2
|
app = ToUpper.new(Hello)
run app
|
Если бы присутствовало больше промежуточного программного обеспечения (как в стеке Rails), оно просто вложило бы их до конца:
1
2
3
4
5
6
|
use Middleware1
use Middleware2
use Middleware3
run MyApp
#=> Boils down to Middleware1.new(Middleware2.new(Middleware3.new(MyApp)))
|
Классы запросов и ответов
Когда вы начинаете писать приложения и промежуточное ПО для Rack, управление массивом [status, headers, body]
быстро становится утомительным.
Rack предоставляет несколько удобных классов, Rack::Request
и Rack::Response
, чтобы сделать жизнь немного проще.
Rack::Request
оборачивает хэш env
и предоставляет вам удобные методы для извлечения информации, которая может вам понадобиться:
01
02
03
04
05
06
07
08
09
10
11
12
|
def call(env)
req = Rack::Request.new(env)
req.request_method #=> GET, POST, PUT, etc.
req.get?
req.path_info # the path this request came in on
req.session # access to the session object, if using the
# Rack::Session middleware
req.params # a hash of merged GET and POST params, useful for
# pulling values out of a query string
# … and many more
end
|
Rack::Response
дополняет Rack::Request
и предоставляет вам более удобный способ создания ответа. Например, наше приложение Hello
можно переписать следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
class Hello
def self.call(env)
res = Rack::Response.new
# This will automatically set the Content-Length header for you
res.write «Hello from Rack!»
# returns the standard [status, headers, body] array
res.finish
# You can get/set headers with square bracket syntax:
# res[«Content-Type»] = «text/plain»
# You can set and delete cookies
# res.set_cookie(«user_id», 1)
# res.delete_cookie(«user_id»)
end
end
|
Вывод
В этой статье мы рассмотрели основные концепции Rack, которых должно быть достаточно для того, чтобы вы лучше поняли, что скрыто под многими популярными фреймворками, а также, если вам это интересно, помогут вам промокнуть. в разработке напрямую с Rack.
Code является отличным учителем, и поэтому, если вы заинтересованы в Rack, я настоятельно рекомендую взглянуть на его источник . Он поставляется с множеством очень полезных встроенных утилит и промежуточного программного обеспечения (и еще с большим количеством на стеллажах ), которые вы можете использовать и учиться.