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,并在互斥体内包装应用程序。

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

  • 为请求设置cookie。

ActionDispatch::Session::CookieStore

  • 负责将会话存储在cookie中。

ActionDispatch::Flash

ActionDispatch::ContentSecurityPolicy::Middleware

  • 提供用于配置Content-Security-Policy标头的DSL。

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 文档的任何问题。