Add cache headers to static files served through Rails (#24120)

This commit is contained in:
Eugen Rochko 2023-03-16 02:55:54 +01:00 committed by GitHub
parent be488adf71
commit f0e727f958
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 21 deletions

View file

@ -35,6 +35,7 @@ require_relative '../lib/terrapin/multi_pipe_extensions'
require_relative '../lib/mastodon/snowflake'
require_relative '../lib/mastodon/version'
require_relative '../lib/mastodon/rack_middleware'
require_relative '../lib/public_file_server_middleware'
require_relative '../lib/devise/two_factor_ldap_authenticatable'
require_relative '../lib/devise/two_factor_pam_authenticatable'
require_relative '../lib/chewy/strategy/mastodon'
@ -181,6 +182,10 @@ module Mastodon
config.active_job.queue_adapter = :sidekiq
config.action_mailer.deliver_later_queue_name = 'mailers'
# We use our own middleware for this
config.public_file_server.enabled = false
config.middleware.use PublicFileServerMiddleware if Rails.env.development? || ENV['RAILS_SERVE_STATIC_FILES'] == 'true'
config.middleware.use Rack::Attack
config.middleware.use Mastodon::RackMiddleware

View file

@ -16,12 +16,7 @@ Rails.application.configure do
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp/caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}",
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store

View file

@ -19,24 +19,14 @@ Rails.application.configure do
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
ActiveSupport::Logger.new(STDOUT).tap do |logger|
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Compress JavaScripts and CSS.
# config.assets.js_compressor = Uglifier.new(mangle: false)
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Specifies the header that your server uses for sending files.
config.action_dispatch.x_sendfile_header = ENV['SENDFILE_HEADER'] if ENV['SENDFILE_HEADER'].present?
@ -66,7 +56,7 @@ Rails.application.configure do
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# English when a translation cannot be found).
config.i18n.fallbacks = [:en]
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify

View file

@ -12,11 +12,6 @@ Rails.application.configure do
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
}
config.assets.digest = false
# Show full error reports and disable caching.

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
require 'action_dispatch/middleware/static'
class PublicFileServerMiddleware
SERVICE_WORKER_TTL = 7.days.to_i
CACHE_TTL = 28.days.to_i
def initialize(app)
@app = app
@file_handler = ActionDispatch::FileHandler.new(Rails.application.paths['public'].first)
end
def call(env)
file = @file_handler.attempt(env)
# If the request is not a static file, move on!
return @app.call(env) if file.nil?
status, headers, response = file
# Set cache headers on static files. Some paths require different cache headers
headers['Cache-Control'] = begin
request_path = env['REQUEST_PATH']
if request_path.start_with?('/sw.js')
"public, max-age=#{SERVICE_WORKER_TTL}, must-revalidate"
elsif request_path.start_with?(paperclip_root_url)
"public, max-age=#{CACHE_TTL}, immutable"
else
"public, max-age=#{CACHE_TTL}, must-revalidate"
end
end
[status, headers, response]
end
private
def paperclip_root_url
ENV.fetch('PAPERCLIP_ROOT_URL', '/system')
end
end