このガイドでは、RailsとRackの関係、Railsと他のRackコンポーネントとの関係について説明します。
このガイドの内容:
このガイドはRackのミドルウェア、urlマップ、Rack::Builder
といったRackのプロトコルや概念に関する実用的な知識を身につけていることを前提にしています。
Rackは、RubyのWebアプリケーションに対して、モジュール化された最小限のインターフェイスを提供して、インターフェイスを広範囲に使えるようにします。RackはHTTPリクエストとレスポンスを可能なかぎり簡単な方法でラッピングすることで、Webサーバー、Webフレームワーク、その間に位置するソフトウェア(ミドルウェアと呼ばれています)のAPIを1つのメソッド呼び出しの形にまとめます。
Rackに関する解説はこのガイドの範疇を超えてしまいます。Rackに関する基本的な知識が不足している場合は、下記のリソース を参照してください。
Rails.application
は、Railsアプリケーションにおける主要なRackアプリケーションです。Rackに準拠したWebサーバーで、Railsアプリケーションを提供するには、Rails.application
オブジェクトを使う必要があります。
bin/rails server
コマンドbin/rails server
コマンドは、Rack::Server
のオブジェクトを作成し、Webサーバーを起動します。
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
一度読み込まれたミドルウェアは、変更が発生しても検出されません。現在実行中のアプリケーションでミドルウェアの変更を反映するには、サーバーの再起動が必要です。
Action Dispatcher内部のコンポーネントの多くは、「Rackミドルウェア」として実装されています。Rails::Application
は、ActionDispatch::MiddlewareStack
を用いて内部ミドルウェアや外部ミドルウェアを組み合わせることで、完全なRailsのRackアプリケーションを構築します。
RailsのActionDispatch::MiddlewareStack
クラスはRack::Builder
クラスと同等ですが、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/<環境名>.rb
設定ファイルで行うこともできます。
次のメソッドを使うと、ミドルウェアスタックに新しいミドルウェアを追加できます。
config.middleware.use(new_middleware, args)
: ミドルウェアスタックの末尾に新しいミドルウェアを追加します。
config.middleware.insert_before(existing_middleware, new_middleware, args)
: 新しいミドルウェアを、(第1引数で)指定された既存のミドルウェアの直前に追加します。
config.middleware.insert_after(existing_middleware, new_middleware, args)
: 新しいミドルウェアを、(第1引数で)指定された既存のミドルウェアの直後に追加します。
# config/application.rb # Rack::BounceFaviconを末尾に追加する config.middleware.use Rack::BounceFavicon # ActionDispatch::Executorの直後にLifo::Cacheを追加する # Lifo::Cacheに引数{ page_cache: false }を渡す 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
に設定し、アプリケーションをMutexでラップします。ActionDispatch::Executor
ActionDispatch::ServerTiming
Server-Timing
ヘッダーを設定します。ActiveSupport::Cache::Strategy::LocalCache::Middleware
Rack::Runtime
Rack::MethodOverride
params[:_method]
が設定されている場合に(HTTP)メソッドが上書きされるようになります。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::Reloader
ActionDispatch::Callbacks
ActiveRecord::Migration::CheckPending
ActiveRecord::PendingMigrationError
を発生させます。ActionDispatch::Cookies
ActionDispatch::Session::CookieStore
ActionDispatch::Flash
config.session_store
に値が設定されている場合にのみ有効です。ActionDispatch::ContentSecurityPolicy::Middleware
Rack::Head
HEAD
リクエストに対して空のbodyを返します。その他のリクエストは変更しません。Rack::ConditionalGet
GET
(Conditional GET
)」機能を提供します。"条件付き GET
"が有効になっていると、リクエストされたページで変更が発生していない場合に空のbodyを返します。Rack::ETag
Rack::TempfileReaper
これらのミドルウェアはいずれも、独自のRackスタックで利用することも可能です。
Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。
原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨
本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。
Railsガイド運営チーム (@RailsGuidesJP)
Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。