ActiveStorage:旧的url仍然请求已弃用:variation_key中的combine_options.&l



最近我从Rails 6.0.3.4升级到6.1.3。ActiveStorage弃用的combine_options,我从我的应用程序中清除。所有新请求都按预期工作。互联网机器人(Facebook, Google,…)会缓存网站(比如我的)上的图片的url。根据我的Rollbar记录,他们每天会请求几次。

应该加载ActiveStorage附件的缓存URL在URL中包含旧的variation_key。当blob想要使用解码的variation_key加载时,我看到combine_options仍然存在。这会抛出一个500 Internal Server Error with ArgumentError (Active Storage's ImageProcessing transformer doesn't support :combine_options, as it always generates a single ImageMagick command.):.

有什么方法可以阻止这些错误的出现吗?

Rails版本:6.1.3。Ruby版本:2.7.2p137

我已经使用一些中间件解决了这个问题。这将拦截所有传入的请求,如果他们是ActiveStorage的url扫描,找到那些与弃用的combine_options,只是返回404未找到。如果当前环境正在开发,此代码也会引发错误,这样我就不会不小心再次引入不推荐的代码。

对于那些可能遇到同样问题的人,下面是代码。

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

我认为塞子是一个很好的解决方案,但最终我想摆脱它。不幸的是,几个月后,我们的大多数旧请求仍然出现,没有人尊重404。所以我决定在之前rails版本的基础上做一个猴子补丁。这是我做的。

配置/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

最新更新