📝
RailsでリクエストがControllerにたどり着くまで
なに?
Railsを雰囲気で使っているので、どういった処理がなされているのかを見てみようと思ったのがきっかけ。
まずは、PumaなどのApplication Serverにリクエストが送られたとき、そこからどうやってControllerにたどり着いているのかを調べてみた。
ばーじょん
- Ruby ruby 2.7.2p137
- Rails 6.1.2
rails new
で作成しただけのplainなプロジェクトを使っている。
また、gemやenvironmentによって差し込まれるmiddlewareが変わってくる可能性がある。
ながれ
- Rails::Engine#call
- Rack::Proxy#call
- Webpacker::DevServerProxy#perform_request
- webpack-dev-server周りの設定
- refs: https://github.com/rails/webpacker
- Rack::MiniProfiler#call
- Profile系の処理
- refs: https://github.com/MiniProfiler/rack-mini-profiler
- ActionDispatch::HostAuthorization#call
- config.host_authorizationのチェック
- see: https://api.rubyonrails.org/classes/ActionDispatch/HostAuthorization.html
- Rack::Sendfile#call
- ActionDispatch::Static#call
- 該当する静的ファイルを探索し、あれば返す
- ActionDispatch::Executor#call
- ActiveSupport::Cache::Strategy::LocalCache::Middleware#call
- local cacheの設定
- see: https://api.rubyonrails.org/classes/ActiveSupport/Cache/Strategy/LocalCache.html
- Rack::Runtime#call
- "X-Runtime"ヘッダの設定
- 以降の処理の前後のclock_timeを取ってヘッダーにつける
- Rack::MethodOverride#call
- PUTやDELETEの場合は、HTTP Methodは"POST"で、"_method"の中に実態が入っている
- なので、実態にあったHTTP Methodをrequest.envに詰める
- override前のHTTP Methodは"rack.methodoverride.original_method"に格納される
- ActionDispatch::RequestId#call
- "X-Request-Id"ヘッダの設定
- "X-Request-Id"があれば(ほぼ)そのまま使い、なければ発行(SecureRandom.uuid)する
- ActionDispatch::RemoteIp#call
- HTTPヘッダから接続元IPを取得し、IpSpoofAttackErrorをチェック
- see: https://api.rubyonrails.org/classes/ActionDispatch/RemoteIp.html
Sprockets::Rails::QuietAssets#call - assetsへのリクエストの場合、Rails::loggerを抑制
- Rails::Rack::Logger#call
- ↓のようなタグ付きのロガーが設定されている場合、タグを設定する
- https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html
- ActionDispatch::ShowExceptions#call
- エラーが起きたときに、以下の処理を行う
- !(env["action_dispatch.show_exceptions"] == false)だったら、エラー画面を表示する
- Rails.config.exceptions_appで設定されたClassで表示処理を行う
- デフォルトではActionDispatch::PublicExceptions
- public直下のHTTP Status Codeに沿ったhtmlをrenderするだけ
- (env["action_dispatch.exception"] == false)だったら、例外をそのままraise
- WebConsole::Middleware#call
- web-consoleの設定
- refs: https://github.com/rails/web-console
- ActionDispatch::DebugExceptions#call
- エラーが起きたときに、デバッグ用のエラー情報の制御
- (env["action_dispatch.show_exceptions"] == false)だったら、例外をそのままraise
- ActionDispatch::ActionableExceptions#call
- ActionDispatch::Executor#call
- ActionDispatch::Callbacks#call
- ActiveRecord::Migration::CheckPending#call
- Migrationバージョンのチェック
- ActionDispatch::Cookies#call
- レスポンス時のcookieの更新
- Rack::Session::Abstract::Persisted#call
- session情報の生成、更新
- ActionDispatch::ContentSecurityPolicy::Middleware#call
- ContentSecurityPolicyの設定
- ActionDispatch::PermissionsPolicy::Middleware#call
- PermissionsPolicy(Feature-Policyヘッダ)の設定
- Rack::Head#call
- HEADリクエストの場合は空を返す
- Rack::ConditionalGet#call
- "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE"まわりの制御
- Rack::ETag#call
- ETagの設定
- Rack::TempfileReaper#call
- Tempfileのお掃除
- ActionDispath:Routing::RouteSet#call
- pathをNormalize
- ActionDispatch::Journey::Router#serve
pathからroute(controller, action)を特定して処理を移譲する - ActionDispath:Routing::RouteSet::Dispatcher#serve
- controllerへdispatch
- ActionController::Metal.dispatch
- ActionController::Metal#dispatch
- ActionView::Rendering#process
- AbstractController::Base#process
- actionを呼び出し
- ActiveRecord::Railties::ControllerRuntime#process_action
- ActiveRecord::LogSubscriberをreset
- ActionController::ParamsWrapper#process_action
- ActionController::Instrumentation#process_action
- ActionController::Rescue#process_action
- ActionController::Callbacks#process_action
- ActionController::Rendering#process_action
- AbstractController::Base#process_action
- ActionController::BasicImplicitRender#send_action
- ここでようやく対応するControllerのActionにたどり着く
こんご
大量のmiddlewareたちによって、Requestが作られてControllerにたどり着くことが分かった。
今後は、configの設定がどのように対応しているかであったり、Viewのレンダリングなど、基本的な部分を追っていこうと思う。
Discussion