discourse/app/controllers/theme_javascripts_controlle...

91 lines
2.4 KiB
Ruby

# frozen_string_literal: true
class ThemeJavascriptsController < ApplicationController
DISK_CACHE_PATH = "#{Rails.root}/tmp/javascript-cache"
skip_before_action(
:check_xhr,
:handle_theme,
:preload_json,
:redirect_to_login_if_required,
:verify_authenticity_token,
only: [:show, :show_tests]
)
before_action :is_asset_path, :no_cookies, :apply_cdn_headers, only: [:show]
def show
raise Discourse::NotFound unless last_modified.present?
return render body: nil, status: 304 if not_modified?
# Security: safe due to route constraint
cache_file = "#{DISK_CACHE_PATH}/#{params[:digest]}.js"
unless File.exist?(cache_file)
content = query.pluck_first(:content)
raise Discourse::NotFound if content.nil?
FileUtils.mkdir_p(DISK_CACHE_PATH)
File.write(cache_file, content)
end
# this is only required for NGINX X-SendFile it seems
response.headers["Content-Length"] = File.size(cache_file).to_s
set_cache_control_headers
send_file(cache_file, disposition: :inline)
end
def show_tests
raise Discourse::NotFound if Rails.env.production?
theme_id = params.require(:theme_id)
theme = Theme.find(theme_id)
content = ThemeField
.where(
theme_id: theme_id,
target_id: Theme.targets[:tests_js]
)
.each(&:ensure_baked!)
.map(&:value_baked)
.join("\n")
ThemeJavascriptCompiler.force_default_settings(content, theme)
response.headers["Content-Length"] = content.size.to_s
response.headers["Last-Modified"] = Time.zone.now.httpdate
immutable_for(1.second)
send_data content, filename: "js-tests-theme-#{theme_id}.js", disposition: :inline
end
private
def query
@query ||= JavascriptCache.where(digest: params[:digest]).limit(1)
end
def last_modified
@last_modified ||= query.pluck_first(:updated_at)
end
def not_modified?
cache_time =
begin
Time.rfc2822(request.env["HTTP_IF_MODIFIED_SINCE"])
rescue ArgumentError
nil
end
cache_time && last_modified && last_modified <= cache_time
end
def set_cache_control_headers
if Rails.env.development?
response.headers['Last-Modified'] = Time.zone.now.httpdate
immutable_for(1.second)
else
response.headers['Last-Modified'] = last_modified.httpdate if last_modified
immutable_for(1.year)
end
end
end