翻译 Rails 5 允许对静态资源文件设置 HTTP 头

dothide · 2016年08月03日 · 最后由 moliliang 回复于 2016年09月20日 · 8092 次阅读
本帖已被管理员设置为精华贴

这篇博客是我们 《Rails 5 系列文章》 中的一篇

让我们先来看看 Rails 4.2.4 应用默认的响应头是如何的:

Img

现在,假设我们要设置一个自定义的相应头。很容易,我们只需要在 controller 中添加以下代码:

response.headers['X-Tracking-ID'] = '123456'

于是我们看到了自定义的头:

Img

为静态资源文件设置自定义响应头

现在我们需要不仅能对标准 Web 请求设置自定义响应头,而且对静态资源也需要设置。举例来说被本地 Rails 服务跑着的 application.js 文件。这里该如何设置呢?

实际上在 Rails 4 中是不可能的,它唯一可以为静态资源的响应头做的设置项只有:Cache-Control ,如下:

# 在 config/environments/production.rb 加入如下代码行
config.static_cache_control = 'public, max-age=1000'

这时我们就为资源文件设置了 Cache-Control 的值:

Img

除此以外的任何响应头都不行,那是一个限制。

Rails 应用带着这样的限制活了这么久

Rails 跑静态资源文件并非强项。那是 Apache 和 Nginx 的拿手好戏。因此,在实际生产环境中,几乎所有人都会在 Rails Server 之前架一道 Apache 或 Nginx 以至于无需用 Rails 来跑静态资源。

Havig 说,Rails 应用跑在 Heroku 上是个异常。跑在 Heroku 上的 Rails 应用的资源文件其实被 Rails 应用自己在跑着。

我们遇到的问题

我们的 网站 是跑在 Heroku 上的。当我们用 Google page speed insights 跑一遍网站,就被警告说我们没有为资源文件设置 Expires 头。

Img

下图显示了 application.js 的头

Img

现在你就了解了我们遇到的问题。

  • 我们的应用跑在 Heroku 上
  • Heroku 让 Rails 来跑静态文件
  • Google page speed insights 需要我们设置 Expires
  • Rails 应用只允许为静态文件设置 Cache-Control

一种方案就是将网站放到 Digital Ocean 上在使用 Apache 或者 Nginx。

Rails 5 拯救了今日

如今 Rails 整合了头访问控制的基础支持 并且加入了自定义 HTTP 头的能力。

场景背后,Rails 使用 ActionDispatch::Static 中间件来运行静态文件。例如,一个取图片的请求,在请求周期中通过 ActionDispatch::StaticActionDispatch::Static 从响应中带有适当头的服务中运行 Rack:File 对象。被运行的图片就能拥有类似 Content-TypeCache-Control 等头。

开始使用最新的 Rails

为了修复该问题,我们使用了最新的 Rails

gem 'rails', github: 'rails/rails'
gem 'rack', github: 'rack/rack' # Rails depends on Rack 2
gem 'arel', github: 'rails/arel' # Rails master works alongside of arel master.

接着,我们修改配置来提供缺失的 Expires

# production.rb

config.public_file_server.headers = {
  'Cache-Control' => 'public, s-maxage=31536000, maxage=15552000',
  'Expires' => "#{1.year.from_now.to_formatted_s(:rfc822)}"
}

这里,我们先设置了 Cache-Control 头来使用公共缓存,maxages-maxage 均设为一年(31536000 秒)。

然后设置缺失的 Expires 值,之后我们再次测试就能看到新的头,再没有收到头缺失的警告。

Img

这是改变后的静态文件响应头:

Img

补充阅读

为更好地使用和了解关于不同头对静态文件的使用细节,敬请参考 RFC2616

作者 Vipul 于 2015.10.31

huacnlee 将本帖设为了精华贴。 08月03日 12:18

还可以用 cdn

用 Rails 来处理静态文件性能岂不是很低?

可以自己写个中间件插进去啊。 https://gist.github.com/ryanb/4157256

很棒的文章,但是我觉得更好的方式应该是配置 CDN,把主站和静态资源分离开。

👍 bigbinary 有好多高质量又实用的文章

还是用七牛、upyun 之类的镜像静态文件比较靠谱,自己少操心~~

需要 登录 后方可回复, 如果你还没有账号请 注册新账号