fix stylesheet cache to recover if file is on disk
This commit is contained in:
parent
17d843a0ad
commit
96dbeb8608
|
@ -4,43 +4,53 @@ class StylesheetsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
|
|
||||||
target,digest = params[:name].split("_")
|
target,digest = params[:name].split("_")
|
||||||
digest_orig = digest
|
|
||||||
digest = "_" + digest if digest
|
|
||||||
|
|
||||||
cache_time = request.env["HTTP_IF_MODIFIED_SINCE"]
|
cache_time = request.env["HTTP_IF_MODIFIED_SINCE"]
|
||||||
cache_time = Time.rfc2822(cache_time) rescue nil if cache_time
|
cache_time = Time.rfc2822(cache_time) rescue nil if cache_time
|
||||||
|
|
||||||
query = StylesheetCache.where(target: target)
|
query = StylesheetCache.where(target: target)
|
||||||
if digest
|
if digest
|
||||||
query = query.where(digest: digest_orig)
|
query = query.where(digest: digest)
|
||||||
else
|
else
|
||||||
query = query.order('id desc')
|
query = query.order('id desc')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Security note, safe due to route constraint
|
||||||
|
underscore_digest = digest ? "_" + digest : ""
|
||||||
|
location = "#{Rails.root}/#{DiscourseStylesheets::CACHE_PATH}/#{target}#{underscore_digest}.css"
|
||||||
|
|
||||||
stylesheet_time = query.pluck(:created_at).first
|
stylesheet_time = query.pluck(:created_at).first
|
||||||
|
|
||||||
if !stylesheet_time
|
if !stylesheet_time
|
||||||
return render nothing: true, status: 404
|
handle_missing_cache(location, target, digest)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cache_time && stylesheet_time && stylesheet_time <= cache_time
|
if cache_time && stylesheet_time && stylesheet_time <= cache_time
|
||||||
return render nothing: true, status: 304
|
return render nothing: true, status: 304
|
||||||
end
|
end
|
||||||
|
|
||||||
# Security note, safe due to route constraint
|
|
||||||
location = "#{Rails.root}/#{DiscourseStylesheets::CACHE_PATH}/#{target}#{digest}.css"
|
|
||||||
|
|
||||||
unless File.exist?(location)
|
unless File.exist?(location)
|
||||||
if current = query.first
|
if current = query.first
|
||||||
File.write(location, current.content)
|
File.write(location, current.content)
|
||||||
else
|
else
|
||||||
return render nothing: true, status: 404
|
raise Discourse::NotFound
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
response.headers['Last-Modified'] = stylesheet_time.httpdate
|
response.headers['Last-Modified'] = stylesheet_time.httpdate if stylesheet_time
|
||||||
expires_in 1.year, public: true unless Rails.env == "development"
|
expires_in 1.year, public: true unless Rails.env == "development"
|
||||||
send_file(location, disposition: :inline)
|
send_file(location, disposition: :inline)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def handle_missing_cache(location, name, digest)
|
||||||
|
existing = File.read(location) rescue nil
|
||||||
|
if existing && digest
|
||||||
|
StylesheetCache.add(name, digest, existing)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class StylesheetCache < ActiveRecord::Base
|
class StylesheetCache < ActiveRecord::Base
|
||||||
self.table_name = 'stylesheet_cache'
|
self.table_name = 'stylesheet_cache'
|
||||||
|
|
||||||
MAX_TO_KEEP = 10
|
MAX_TO_KEEP = 50
|
||||||
|
|
||||||
def self.add(target,digest,content)
|
def self.add(target,digest,content)
|
||||||
|
|
||||||
|
|
|
@ -118,10 +118,14 @@ class DiscourseStylesheets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_fullpath
|
def self.cache_fullpath
|
||||||
"#{Rails.root}/#{CACHE_PATH}"
|
"#{Rails.root}/#{CACHE_PATH}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cache_fullpath
|
||||||
|
self.class.cache_fullpath
|
||||||
|
end
|
||||||
|
|
||||||
def stylesheet_fullpath
|
def stylesheet_fullpath
|
||||||
"#{cache_fullpath}/#{stylesheet_filename}"
|
"#{cache_fullpath}/#{stylesheet_filename}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe StylesheetsController do
|
||||||
|
|
||||||
|
it 'can survive cache miss' do
|
||||||
|
DiscourseStylesheets.cache.clear
|
||||||
|
DiscourseStylesheets.stylesheet_link_tag('desktop_rtl')
|
||||||
|
|
||||||
|
StylesheetCache.destroy_all
|
||||||
|
|
||||||
|
# digestless
|
||||||
|
get :show, name: 'desktop_rtl'
|
||||||
|
expect(response).to be_success
|
||||||
|
|
||||||
|
# tmp folder destruction and cached
|
||||||
|
`rm #{DiscourseStylesheets.cache_fullpath}/*`
|
||||||
|
|
||||||
|
get :show, name: 'desktop_rtl'
|
||||||
|
expect(response).to be_success
|
||||||
|
|
||||||
|
# there is an edge case which is ... disk and db cache is nuked, very unlikely to happen
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue