edge
更多資訊請參考 rubyonrails.org: 更多 Ruby on Rails

Rails on Rack

本指南介紹了Rails與Rack的整合以及與其他Rack組件的接口。

閱讀完本指南後,您將了解:

警告:本指南假設您已經熟悉Rack協議和Rack概念,例如中間件、URL映射和Rack::Builder

1 Rack簡介

Rack提供了一個最小、模塊化和可適應的接口,用於在Ruby中開發Web應用程序。通過以最簡單的方式封裝HTTP請求和響應,它將Web服務器、Web框架和中間件(所謂的中間件)之間的API統一並提煉成一個方法調用。

解釋Rack的工作原理不在本指南的範圍內。如果您對Rack的基礎不熟悉,請查看下面的資源部分。

2 Rails on Rack

2.1 Rails應用程序的Rack對象

Rails.application是Rails應用程序的主要Rack應用程序對象。任何符合Rack標準的Web服務器都應該使用Rails.application對象來提供Rails應用程序。

2.2 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

2.3 rackup

如果要使用rackup而不是Rails的bin/rails server,可以將以下內容放在Rails應用程序根目錄的config.ru中:

# Rails.root/config.ru
require_relative "config/environment"
run Rails.application

然後啟動服務器:

$ rackup config.ru

要了解有關不同的rackup選項的更多信息,可以運行:

$ rackup --help

2.4 開發和自動重新加載

中間件只加載一次,不會監視更改。您需要重新啟動服務器才能使更改在運行中的應用程序中生效。

3 Action Dispatcher中間件堆棧

Action Dispatcher的許多內部組件都是作為Rack中間件實現的。Rails::Application使用ActionDispatch::MiddlewareStack將各種內部和外部中間件組合成一個完整的Rails Rack應用程序。

注意:ActionDispatch::MiddlewareStack是Rails的等效物Rack::Builder,但為了更好的靈活性和更多功能,它被構建用於滿足Rails的要求。

3.1 檢查中間件堆棧

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

這裡顯示的默認中間件(以及其他一些中間件)在下面的內部中間件部分中有簡要介紹。

3.2 配置中間件堆棧

Rails提供了一個簡單的配置接口config.middleware,用於通過application.rb或環境特定的配置文件environments/<environment>.rb添加、刪除和修改中間件堆棧中的中間件。

3.2.1 添加中間件

您可以使用以下任何方法將新的中間件添加到中間件堆棧中:

  • 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

# 在ActionDispatch::Executor之後添加Lifo::Cache。
# 將{ page_cache: false }參數傳遞給Lifo::Cache。
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false

3.2.2 替換中間件

您可以使用config.middleware.swap將中間件堆棧中的現有中間件替換為新的中間件。

# config/application.rb

# 將ActionDispatch::ShowExceptions替換為Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions

3.2.3 移動中間件

您可以使用config.middleware.move_beforeconfig.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

3.2.4 刪除中間件

將以下行添加到應用程式配置中:

# 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

3.3 內部中介軟體堆疊

Action Controller 的許多功能都是以中介軟體的形式實現的。以下列表解釋了每個中介軟體的目的:

ActionDispatch::HostAuthorization

  • 通過明確允許請求可以發送到的主機,防止 DNS 重綁定攻擊。有關配置說明,請參閱配置指南

Rack::Sendfile

ActionDispatch::Static

Rack::Lock

  • env["rack.multithread"] 標誌設置為 false,並在 Mutex 內包裹應用程式。

ActionDispatch::Executor

  • 用於開發期間的線程安全代碼重新加載。

ActionDispatch::ServerTiming

ActiveSupport::Cache::Strategy::LocalCache::Middleware

  • 用於記憶體緩存。此緩存不是線程安全的。

Rack::Runtime

  • 設置包含執行請求所需時間(以秒為單位)的 X-Runtime 標頭。

Rack::MethodOverride

  • 如果設置了 params[:_method],則允許覆蓋方法。這是支援 PUT 和 DELETE HTTP 方法類型的中介軟體。

ActionDispatch::RequestId

  • 使唯一的 X-Request-Id 標頭可用於回應,並啟用 ActionDispatch::Request#request_id 方法。

ActionDispatch::RemoteIp

  • 檢查 IP 欺騙攻擊。

Sprockets::Rails::QuietAssets

  • 抑制資源請求的日誌輸出。

Rails::Rack::Logger

  • 通知日誌請求已開始。請求完成後,刷新所有日誌。

ActionDispatch::ShowExceptions

  • 捕獲應用程式返回的任何異常,並調用一個異常應用程式,將其包裝成用於最終使用者的格式。

ActionDispatch::DebugExceptions

  • 負責記錄異常並在請求為本地時顯示調試頁面。

ActionDispatch::ActionableExceptions

  • 提供從 Rails 錯誤頁面調度操作的方法。

ActionDispatch::Reloader

  • 提供準備和清理回調,用於開發期間的代碼重新加載。

ActionDispatch::Callbacks

  • 提供在調度請求之前和之後執行的回調。

ActiveRecord::Migration::CheckPending

  • 檢查待處理的遷移,如果有任何待處理的遷移,則引發 ActiveRecord::PendingMigrationError

ActionDispatch::Cookies

  • 為請求設置 cookies。

ActionDispatch::Session::CookieStore

  • 負責將會話存儲在 cookies 中。

ActionDispatch::Flash

ActionDispatch::ContentSecurityPolicy::Middleware

  • 提供 DSL 以配置 Content-Security-Policy 標頭。

Rack::Head

  • 將 HEAD 請求轉換為 GET 請求並作為 GET 請求提供。

Rack::ConditionalGet

  • 添加對「條件 GET」的支援,以便如果頁面未更改,伺服器不會回應任何內容。

Rack::ETag

  • 在所有字符串主體上添加 ETag 標頭。ETag 用於驗證快取。

Rack::TempfileReaper

  • 清理用於緩衝多部分請求的臨時文件。

提示:可以在自定義 Rack 堆疊中使用上述任何中介軟體。

4 資源

4.1 學習 Rack

4.2 理解中介軟體

回饋

歡迎協助提升本指南的品質。

如果您發現任何錯別字或事實錯誤,請貢獻您的力量。 開始之前,您可以閱讀我們的 文件貢獻 部分。

您也可能會發現不完整的內容或過時的資訊。 請為主要的文件補充任何遺漏的內容。請先檢查 Edge 指南,以確認問題是否已經修復或尚未在主分支上修復。 請參考 Ruby on Rails 指南指引 以了解風格和慣例。

如果您發現需要修復但無法自行修補的問題,請 開啟一個問題

最後但同樣重要的是,關於 Ruby on Rails 文件的任何討論都非常歡迎在 官方 Ruby on Rails 論壇 上進行。