M config/application.rb => config/application.rb +5 -0
@@ 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
M config/environments/development.rb => config/environments/development.rb +0 -5
@@ 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
M config/environments/production.rb => config/environments/production.rb +1 -11
@@ 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
M config/environments/test.rb => config/environments/test.rb +0 -5
@@ 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.
A lib/public_file_server_middleware.rb => lib/public_file_server_middleware.rb +43 -0
@@ 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