我目前正在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]
和只有vanilla 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
答案 0 :(得分:5)
以下是如何为静态资产设置长到期标头,以及为Heroku上的主要内容设置任意到期标头:
的Gemfile:
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
默认情况下,对于网址数组中列出的内容(静态/样式表,静态/图像等),您将获得2年到期日期。
你必须从/ public移动到/ static,否则你会不必要地使用Heroku的nginx配置(真正应用这些设置的正确位置......)。
我知道你说你试图不使用Rack Contrib,但这没有任何意义。使用一个小的90行库来完成这项工作没有任何害处https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/static_cache.rb。
“正确”的方式是在可以配置nginx的环境中托管静态内容,第二种最好的方法是重命名静态文件路径,以便heroku忽略它,并使用rack static来提供带头的静态文件你想要的。
-
另外要明确的是,只需将公共文件夹重命名为其他内容即可通过路由执行此操作,并且正常的Sinatra会过期。但我会使用StaticCache,因为它不那么冗长。 (真正的问题是Heroku不会让nginx与您的应用程序讨论公开请求/,我相信。)
答案 1 :(得分:1)
我对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状态,其中仍然存在Cache-Control标头。我可以通过几种方式看到这一点,但我想你会这样做,所以我只是指出它,并指出你会按照自己喜欢的方式处理它。