FEATURE: move stylesheet cache out of the uploads directory
This commit is contained in:
parent
8e372f3616
commit
f58d85edea
|
@ -0,0 +1,33 @@
|
||||||
|
class StylesheetsController < ApplicationController
|
||||||
|
skip_before_filter :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show]
|
||||||
|
|
||||||
|
def show
|
||||||
|
|
||||||
|
target,digest = params[:name].split("_")
|
||||||
|
|
||||||
|
digest = "_" + digest if digest
|
||||||
|
|
||||||
|
# Security note, safe due to route constraint
|
||||||
|
location = "#{DiscourseStylesheets::CACHE_PATH}/#{target}#{digest}.css"
|
||||||
|
|
||||||
|
unless File.exist?(location)
|
||||||
|
query = StylesheetCache.where(target: target)
|
||||||
|
if digest
|
||||||
|
query = query.where(digest: digest)
|
||||||
|
else
|
||||||
|
query = query.order('id desc')
|
||||||
|
end
|
||||||
|
|
||||||
|
if current = query.first
|
||||||
|
File.write(location, current.content)
|
||||||
|
else
|
||||||
|
return render nothing: true, status: 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
expires_in 1.year, public: true unless Rails.env == "development"
|
||||||
|
send_file(location, disposition: :inline)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
class StylesheetCache < ActiveRecord::Base
|
||||||
|
self.table_name = 'stylesheet_cache'
|
||||||
|
|
||||||
|
MAX_TO_KEEP = 10
|
||||||
|
|
||||||
|
def self.add(target,digest,content)
|
||||||
|
success = create(target: target, digest: digest, content: content)
|
||||||
|
|
||||||
|
count = StylesheetCache.count
|
||||||
|
if count > MAX_TO_KEEP
|
||||||
|
|
||||||
|
remove_lower = StylesheetCache.limit(MAX_TO_KEEP)
|
||||||
|
.order('id desc')
|
||||||
|
.pluck(:id)
|
||||||
|
.last
|
||||||
|
|
||||||
|
exec_sql("DELETE FROM stylesheet_cache where id < :id", id: remove_lower)
|
||||||
|
end
|
||||||
|
|
||||||
|
success
|
||||||
|
rescue ActiveRecord::RecordNotUnique
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -33,7 +33,8 @@ if defined?(Rack::MiniProfiler)
|
||||||
/^\/site_customizations/,
|
/^\/site_customizations/,
|
||||||
/^\/uploads/,
|
/^\/uploads/,
|
||||||
/^\/javascripts\//,
|
/^\/javascripts\//,
|
||||||
/^\/images\//
|
/^\/images\//,
|
||||||
|
/^\/stylesheets\//
|
||||||
]
|
]
|
||||||
|
|
||||||
# For our app, let's just show mini profiler always, polling is chatty so nuke that
|
# For our app, let's just show mini profiler always, polling is chatty so nuke that
|
||||||
|
|
|
@ -158,7 +158,7 @@ server {
|
||||||
# This big block is needed so we can selectively enable
|
# This big block is needed so we can selectively enable
|
||||||
# acceleration for backups and avatars
|
# acceleration for backups and avatars
|
||||||
# see note about repetition above
|
# see note about repetition above
|
||||||
location ~ ^/(letter_avatar|user_avatar|highlight-js) {
|
location ~ ^/(letter_avatar|user_avatar|highlight-js|stylesheets) {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
|
@ -287,6 +287,8 @@ Discourse::Application.routes.draw do
|
||||||
|
|
||||||
get "highlight-js/:hostname/:version.js" => "highlight_js#show", format: false, constraints: { hostname: /[\w\.-]+/ }
|
get "highlight-js/:hostname/:version.js" => "highlight_js#show", format: false, constraints: { hostname: /[\w\.-]+/ }
|
||||||
|
|
||||||
|
get "stylesheets/:name.css" => "stylesheets#show", constraints: {name: /[a-z0-9_]+/}
|
||||||
|
|
||||||
get "uploads/:site/:id/:sha.:extension" => "uploads#show", constraints: {site: /\w+/, id: /\d+/, sha: /[a-z0-9]{15,16}/i, extension: /\w{2,}/}
|
get "uploads/:site/:id/:sha.:extension" => "uploads#show", constraints: {site: /\w+/, id: /\d+/, sha: /[a-z0-9]{15,16}/i, extension: /\w{2,}/}
|
||||||
get "uploads/:site/:sha" => "uploads#show", constraints: { site: /\w+/, sha: /[a-z0-9]{40}/}
|
get "uploads/:site/:sha" => "uploads#show", constraints: { site: /\w+/, sha: /[a-z0-9]{40}/}
|
||||||
post "uploads" => "uploads#create"
|
post "uploads" => "uploads#create"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
class AddStylesheetCache < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :stylesheet_cache do |t|
|
||||||
|
t.string :target, null: false
|
||||||
|
t.string :digest, null: false
|
||||||
|
t.text :content, null: false
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :stylesheet_cache, [:target, :digest], unique: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@ require_dependency 'distributed_cache'
|
||||||
|
|
||||||
class DiscourseStylesheets
|
class DiscourseStylesheets
|
||||||
|
|
||||||
CACHE_PATH ||= 'uploads/stylesheet-cache'
|
CACHE_PATH ||= 'tmp/stylesheet-cache'
|
||||||
MANIFEST_DIR ||= "#{Rails.root}/tmp/cache/assets/#{Rails.env}"
|
MANIFEST_DIR ||= "#{Rails.root}/tmp/cache/assets/#{Rails.env}"
|
||||||
MANIFEST_FULL_PATH ||= "#{MANIFEST_DIR}/stylesheet-manifest"
|
MANIFEST_FULL_PATH ||= "#{MANIFEST_DIR}/stylesheet-manifest"
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ class DiscourseStylesheets
|
||||||
File.open(stylesheet_fullpath, "w") do |f|
|
File.open(stylesheet_fullpath, "w") do |f|
|
||||||
f.puts css
|
f.puts css
|
||||||
end
|
end
|
||||||
|
StylesheetCache.add(@target, digest, css)
|
||||||
css
|
css
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ class DiscourseStylesheets
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_fullpath
|
def cache_fullpath
|
||||||
"#{Rails.root}/public/#{CACHE_PATH}"
|
"#{Rails.root}/#{CACHE_PATH}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def stylesheet_fullpath
|
def stylesheet_fullpath
|
||||||
|
@ -118,12 +119,13 @@ class DiscourseStylesheets
|
||||||
"#{GlobalSetting.relative_url_root}/"
|
"#{GlobalSetting.relative_url_root}/"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# using uploads cause we already have all the routing in place
|
||||||
def stylesheet_relpath
|
def stylesheet_relpath
|
||||||
"#{root_path}#{CACHE_PATH}/#{stylesheet_filename}"
|
"#{root_path}stylesheets/#{stylesheet_filename}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def stylesheet_relpath_no_digest
|
def stylesheet_relpath_no_digest
|
||||||
"#{root_path}#{CACHE_PATH}/#{stylesheet_filename_no_digest}"
|
"#{root_path}stylesheets/#{stylesheet_filename_no_digest}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def stylesheet_filename
|
def stylesheet_filename
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe StylesheetCache do
|
||||||
|
|
||||||
|
describe "add" do
|
||||||
|
it "correctly cycles once MAX_TO_KEEP is hit" do
|
||||||
|
(StylesheetCache::MAX_TO_KEEP + 1).times do |i|
|
||||||
|
StylesheetCache.add(i.to_s, "d" + i.to_s, "c" + i.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(StylesheetCache.count).to eq StylesheetCache::MAX_TO_KEEP
|
||||||
|
expect(StylesheetCache.order(:id).first.content).to eq "c1"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does nothing if digest is set and already exists" do
|
||||||
|
StylesheetCache.add("a", "b", "c")
|
||||||
|
StylesheetCache.add("a", "b", "cc")
|
||||||
|
|
||||||
|
expect(StylesheetCache.count).to eq 1
|
||||||
|
expect(StylesheetCache.first.content).to eq "c"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue