Reputation: 803
Recently I upgraded from Rails 6.0.3.4 to 6.1.3. ActiveStorage deprecated combine_options
, which I cleared from my app. All fresh request work as expected.
Internet Bots (Facebook, Google, ...) cache urls to images hosted on a website (like mine). According to my Rollbar records they request these a couple of times a day.
The cached URL's that should load ActiveStorage attachments include an old variation_key
in the URL. When the blob wants to load using the decoded variation_key
, I see that combine_options
is still present. This throws a 500 Internal Server Error with ArgumentError (Active Storage's ImageProcessing transformer doesn't support :combine_options, as it always generates a single ImageMagick command.):
.
Is there any way I can stop these errors from showing up?
Rails version: 6.1.3. Ruby version: 2.7.2p137
Upvotes: 2
Views: 685
Reputation: 3899
I thought the stopper was a great solution but eventually I wanted to get rid of it. Unforunately most of our old requests were stilling coming through months later and no one was honoring the 404s. So I decided to monkey patch based off the previous rails versions. This is was I did.
config/initalizers/active_storage.rb
Rails.application.config.after_initialize do
require 'active_storage'
ActiveStorage::Transformers::ImageProcessingTransformer.class_eval do
private
def operations
transformations.each_with_object([]) do |(name, argument), list|
if name.to_s == "combine_options"
list.concat argument.keep_if { |key, value| value.present? and key.to_s != "host" }.to_a
elsif argument.present?
list << [ name, argument ]
end
end
end
end
end
Upvotes: 1
Reputation: 803
I have resolved this issue using some middleware. This will intercept all incoming requests, scan if they are ActiveStorage
urls, find the ones with the deprecated combine_options
and just return 404 not found. This code will also raise an error is the current environment is development, this way I don't accidentally introduce the deprecated code again.
For those of you who might have the same problem, here's the code.
application.rb
require_relative '../lib/stopper'
config.middleware.use ::Stopper
lib/stopper.rb
class Stopper
def initialize(app)
@app = app
end
def call(env)
req = Rack::Request.new(env)
path = req.path
if problematic_active_storage_url?(path)
if ENV["RACK_ENV"] == 'development'
raise "Problematic route, includes deprecated combine_options"
end
[404, {}, ['not found']]
else
@app.call(env)
end
end
def problematic_active_storage_url?(path)
if active_storage_path?(path) && !valid_variation_key?(variation_key_from_path(path))
return true
end
false
end
def active_storage_path?(path)
path.start_with?("/rails/active_storage/representations/")
end
def variation_key_from_path(path)
if path.start_with?("/rails/active_storage/representations/redirect/")
path.split('/')[6]
elsif path.start_with?("/rails/active_storage/representations/")
path.split('/')[5]
end
end
def valid_variation_key?(var_key)
if decoded_variation = ActiveStorage::Variation.decode(var_key)
if transformations = decoded_variation.transformations
if transformations[:combine_options].present?
return false
end
end
end
true
end
end
Upvotes: 1