Sinatra - 通过 config.ru 设置缓存控制标头



我目前正在Heroku的Cedar堆栈上运行一个Octopress(基于Jekyll(站点 - 代码在这里:https://github.com/elithrar/octopress

我想根据文件类型有选择地应用 Cache-Control 标头:

  • .html文件获得的值为 public, max-age=3600
  • .css|.js|.png|.ico(等(获得的值为 public, max-age=604800 - 或者,我想将此规则应用于从/stylesheets', '/javascripts', '/imgs'目录中提供的任何内容。

既用了set :static_cache_control , [:public, :max_age => 3600],也只用了香草cache_control :public, :max_age => 3600语句,没有运气。

我已经设法对文章本身设置了public, max-age=3600(例如 /2012/lazy-sundays/ (,但无法将标头应用于 CSS/JS(例如 /stylesheets/screen.css (

我的config.ru目前如下所示(更新(:

require 'bundler/setup'
require 'sinatra/base'
# The project root directory
$root = ::File.dirname(__FILE__)
class SinatraStaticServer < Sinatra::Base
  get(/.+/) do
    cache_control :public, :max_age => 7200
    send_sinatra_file(request.path) {404}
  end
  not_found do
    send_sinatra_file('404.html') {"Sorry, I cannot find #{request.path}"}
    cache_control :no_cache, :max_age => 0
  end
  def send_sinatra_file(path, &missing_file_block)
    file_path = File.join(File.dirname(__FILE__), 'public',  path)
    file_path = File.join(file_path, 'index.html') unless file_path =~ /.[a-z]+$/i  
    File.exist?(file_path) ? send_file(file_path) : missing_file_block.call
  end
end
use Rack::Deflater
run SinatraStaticServer
以下是为

静态资产设置长到期标头的方法,以及 Heroku 上主要内容的任意到期标头:

宝石文件:

gem 'rack-contrib'

config.ru:

require 'rack/contrib'
get '*.html' do |page|
  # whatever code you need to serve up your main pages
  # goes here... use Rack::File I guess.
  page
end

# Set content headers for that content...
before do
  expires 5001, :public, :must_revalidate
end

# Assets in /static/stylesheets (domain.com/stylesheets) 
# are served by Rack StaticCache, with a default 2 year expiry.
use Rack::StaticCache, :urls => ["/stylesheets"], :root => Dir.pwd + '/static'
run Sinatra::Application

默认情况下,对于 url 数组(静态/样式表、静态/图像等(中列出的内容,这将给您 2 年的有效期。

你必须从/public 移动到/static,否则你就不必要地与 Heroku 的 nginx 配置作斗争(真的是应用这些设置的正确位置......

我知道你说你试图不使用Rack Contrib,但这毫无意义。使用一个微小的 90 行库来做这个 https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/static_cache.rb 没有坏处。

"正确"的方法是在可以配置 nginx 的环境中托管静态内容,第二种最佳方法是重命名静态文件路径,以便 heroku 忽略它,并使用机架静态来提供带有所需标头的静态文件。

--

另外需要明确的是,只需将公用文件夹重命名为其他名称即可允许您通过路由执行此操作,并且正常的Sinatra过期功能。但是我会使用StaticCache,因为它不那么冗长。(真正的问题是 Heroku 不允许 nginx 与您的应用程序对话以请求公众/,我相信。

我对Sinatra不太熟悉,但我认为这样的事情可以解决问题:

class SinatraStaticServer < Sinatra::Base
  before '*.html' do
    response.headers['Cache-Control'] = 'public, max-age=3600'
  end
  before %r{.(css)|(js)|(png)|(ico)} do
    response.headers['Cache-Control'] = 'public, max-age=604800'
  end
  # ...
end

更新:当您说上述内容未成功添加标题时,我进一步研究了它。 我确定问题是Sinatra自动提供文件public/而不是通过应用程序,因此没有添加标题。 我的解决方案是将静态文件从public/移动到public/public/并相应地调整send_sinatra_file

class SinatraStaticServer < Sinatra::Base
  # ...
  def send_sinatra_file(path, &missing_file_block)
    file_path = File.join(File.dirname(__FILE__), 'public/public',  path)
    file_path = File.join(file_path, 'index.html') unless file_path =~ /.[a-z]+$/i
    File.exist?(file_path) ? send_file(file_path) : missing_file_block.call
  end
  # ...
end

我确认这在我的机器上有效。 请注意,我在回答的第一部分中使用了response.headers['Cache-Control'],而不是您尝试过的set :static_cache_control,但我认为只在configure do块中运行一次。

另请注意,使用此当前设置,与上述匹配的 404,例如 nonexistant.png将提供 404 状态,而缓存控制标头仍然存在。 我可以看到几种解决方法,但我认为你这样做了,所以我只是指出它,并认为你会随心所欲地处理它。

最新更新