📝

RailsでリクエストがControllerにたどり着くまで

2021/02/11に公開

なに?

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
  • Rack::MiniProfiler#call
  • ActionDispatch::HostAuthorization#call
  • Rack::Sendfile#call
  • ActionDispatch::Static#call
    • 該当する静的ファイルを探索し、あれば返す
  • ActionDispatch::Executor#call
  • ActiveSupport::Cache::Strategy::LocalCache::Middleware#call
  • 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
  • Rails::Rack::Logger#call
  • 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
  • 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