Это руководство раскрывает интеграцию Rails и Rack и взаимодействие с другими компонентами Rack.
После прочтения этого руководства, вы узнаете:
Это руководство предполагает практические знания протокола Rack и такие концепции Rack, как промежуточные программы (middlewares), карты (maps) URL и Rack::Builder
.
Rack представляет собой минимальный, модульный и адаптивный интерфейс для разработки веб-приложений на Ruby. Оборачивая запросы и отклики HTTP как можно более простым образом, он объединил и очистил API для веб-серверов, веб-фреймворков и промежуточных программ (так называемых middleware) до единственного метода call.
Объяснение того, как работает Rack, на самом деле не является темой этого руководства. Если вы не знакомы с основами Rack, обратитесь к разделу Источники.
Rails.application
это основной объект приложения Rack в приложении Rails. Любой совместимый с Rack веб-сервер должен использовать объект Rails.application
для обслуживания приложения Rails. Rails.application
ссылается на тот же объект приложения.
bin/rails server
bin/rails server
выполняет основную задачу по созданию объекта Rack::Server
и запуску веб-сервера.
Вот как bin/rails server
создает экземпляр Rack::Server
Rails::Server.new.tap do |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
end
Rails::Server
унаследован от Rack::Server
и вызывает метод Rack::Server#start
следующим образом:
class Server < ::Rack::Server
def start
# ...
super
end
end
rackup
Для использования rackup
вместо рельсового bin/rails server
, следует поместить следующее в config.ru
в корневой директории приложения Rails:
# Rails.root/config.ru
require_relative "config/environment"
run Rails.application
И запустить сервер:
$ rackup config.ru
Чтобы узнать больше о различных опциях rackup
, вы можете выполнить:
$ rackup --help
Промежуточные программы загружаются один раз и не отслеживаются на предмет изменений. Необходимо перезагрузить сервер, чтобы отразить изменения в запущенном приложении.
Многие внутренние компоненты Action Dispatcher реализованы как промежуточные программы Rack. Rails::Application
использует ActionDispatch::MiddlewareStack
для объединения различных внутренних и внешних промежуточных программ для формирования полноценного приложения Rails Rack.
ActionDispatch::MiddlewareStack
это эквивалент Rack::Builder
в Rails, сделанный с большей гибкостью и приспособленностью к требованиям Rails.
В Rails имеется удобная команда для просмотра используемого стека промежуточных программ:
$ bin/rails middleware
Для свежесгенерированного приложения Rails он может выдать что-то наподобие:
use ActionDispatch::HostAuthorization
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActionDispatch::ServerTiming
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Sprockets::Rails::QuietAssets
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::ActionableExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
run MyApp::Application.routes
Промежуточные программы по умолчанию, показанные здесь (и некоторые другие) описываются в разделе Внутренние промежуточные программы ниже.
Rails предоставляет простой конфигурационный интерфейс config.middleware
для добавления, удаления и модифицирования промежуточных программ в стеке промежуточных программ, из application.rb
или конфигурационного файла определенной среды environments/<environment>.rb
.
Добавить новую промежуточную программу в стек промежуточных программ можно с помощью следующих методов:
config.middleware.use(new_middleware, args)
- Добавляет новую промежуточную программу в конец стека.
config.middleware.insert_before(existing_middleware, new_middleware, args)
- Добавляет промежуточную программу до определенной существующей промежуточной программы в стеке.
config.middleware.insert_after(existing_middleware, new_middleware, args)
- Добавляет промежуточную программу после определенной существующей промежуточной программы в стеке.
# config/application.rb
# Добавить Rack::BounceFavicon в конец
config.middleware.use Rack::BounceFavicon
# Добавить Lifo::Cache после ActionDispatch::Executor.
# Передать аргумент { page_cache: false } в Lifo::Cache.
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
Поменять местами существующие промежуточные программы в стеке можно с помощью config.middleware.swap
.
# config/application.rb
# Поменять местами ActionDispatch::ShowExceptions с Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
Можно переместить существующую промежуточную программу в стеке промежуточных программ с помощью config.middleware.move_before
и config.middleware.move_after
.
# config/application.rb
# Перемещаем ActionDispatch::ShowExceptions перед Lifo::ShowExceptions
config.middleware.move_before Lifo::ShowExceptions, ActionDispatch::ShowExceptions
# config/application.rb
# Перемещаем ActionDispatch::ShowExceptions после Lifo::ShowExceptions
config.middleware.move_after Lifo::ShowExceptions, ActionDispatch::ShowExceptions
Добавьте следующие строчки в конфигурацию вашего приложения:
# config/application.rb
config.middleware.delete "Rack::Runtime"
Теперь, при просмотре стека промежуточных программ, вы увидите, что Rack::Runtime
больше не является его частью.
$ bin/rails middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
...
run Rails.application.routes
Если хотите убрать промежуточные программы, относящиеся к сессии, сделайте следующее:
# config/application.rb
config.middleware.delete ActionDispatch::Cookies
config.middleware.delete ActionDispatch::Session::CookieStore
config.middleware.delete ActionDispatch::Flash
Чтобы убрать промежуточные программы, относящиеся к браузеру,
# config/application.rb
config.middleware.delete Rack::MethodOverride
Если хотите, чтобы была вызвана ошибка, когда пытаетесь удалить несуществующий элемент, используйте delete!
.
# config/application.rb
config.middleware.delete! ActionDispatch::Executor
Значительная часть функциональности Action Controller реализована как промежуточные программы. Следующий перечень объясняет назначение каждой из них:
ActionDispatch::HostAuthorization
Rack::Sendfile
config.action_dispatch.x_sendfile_header
.
ActionDispatch::Static
config.public_file_server.enabled
является false.
Rack::Lock
env["rack.multithread"]
в false
и оборачивает приложение в мьютекс.
ActionDispatch::Executor
ActionDispatch::ServerTiming
Server-Timing
, содержащий метрики быстродействия для запроса.
ActiveSupport::Cache::Strategy::LocalCache::Middleware
Rack::Runtime
Rack::MethodOverride
params[:_method]
. Эта промежуточная программа поддерживает типы HTTP методов PUT и DELETE.
ActionDispatch::RequestId
X-Request-Id
и включает метод ActionDispatch::Request#request_id
.
ActionDispatch::RemoteIp
Sprockets::Rails::QuietAssets
Rails::Rack::Logger
ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
ActionDispatch::ActionableExceptions
ActionDispatch::Reloader
ActionDispatch::Callbacks
ActiveRecord::Migration::CheckPending
ActiveRecord::PendingMigrationError
, если какие-то миграции отложены.
ActionDispatch::Cookies
ActionDispatch::Session::CookieStore
ActionDispatch::Flash
config.session_store
присвоено значение.
ActionDispatch::ContentSecurityPolicy::Middleware
Rack::Head
GET
и обслуживает их соответствующим образом.
Rack::ConditionalGet
GET
", чтобы сервер ничего не отвечал, если страница не изменилась.
Rack::ETag
Rack::TempfileReaper
Можете использовать любые из этих промежуточных программ в своем стеке Rack.