本指南假設您已具備 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 開發和自動重新載入
中介軟體只會載入一次,並且不會監控變更。您必須重新啟動伺服器,變更才會反映在執行中的應用程式中。
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
# Push Rack::BounceFavicon at the bottom
config.middleware.use Rack::BounceFavicon
# Add Lifo::Cache after ActionDispatch::Executor.
# Pass { page_cache: false } argument to Lifo::Cache.
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
3.2.2 交換中介軟體
您可以使用 config.middleware.swap
來交換中介軟體堆疊中的現有中介軟體。
# config/application.rb
# Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
3.2.3 移動中介軟體
您可以使用 config.middleware.move_before
和 config.middleware.move_after
來移動中介軟體堆疊中的現有中介軟體。
# config/application.rb
# Move ActionDispatch::ShowExceptions to before Lifo::ShowExceptions
config.middleware.move_before Lifo::ShowExceptions, ActionDispatch::ShowExceptions
# config/application.rb
# Move ActionDispatch::ShowExceptions to after 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
- 設定伺服器特定的 X-Sendfile 標頭。透過
config.action_dispatch.x_sendfile_header
選項設定此項。
ActionDispatch::Static
- 用於從 public 目錄服務靜態檔案。如果
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
- 設定 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
- 為請求設定 Cookie。
ActionDispatch::Session::CookieStore
- 負責將會話儲存在 Cookie 中。
ActionDispatch::Flash
- 設定快閃鍵。只有在
config.session_store
設定為值時才可用。
ActionDispatch::ContentSecurityPolicy::Middleware
- 提供一個 DSL 來設定 Content-Security-Policy 標頭。
Rack::Head
- 為所有 HEAD 請求傳回空主體。它會保持所有其他請求不變。
Rack::ConditionalGet
- 新增對「條件式
GET
」的支援,以便在頁面未變更時,伺服器不回應任何內容。
Rack::ETag
- 在所有 String 主體上新增 ETag 標頭。ETag 用於驗證快取。
Rack::TempfileReaper
- 清除用於緩衝多部分請求的暫存檔。
可以在您的自訂 Rack 堆疊中使用上述任何中介軟體。