We would like to do direct uploads from a different HTTP origin (a browser extension) to a Rails server using an Active Storage Disk service. These uploads require CORS to be configured but unlike other services (S3, GCP, etc.) there is no way to configure them for the Disk service.
I have found a workaround, by monkey patching the controller in an initializer
# We need to do direct uploads from a different HTTP origin (a browser extension) to a Rails server using an
# Active Storage Disk service. These uploads require CORS to be configured but unlike other services (S3, GCP, etc.)
# there is no way to configure them for the Disk service.
#
# As a workaround, route `OPTIONS` request to the same controller's action, and then monkey patch this action to
# add the required header and:
# - call original method for `PUT`
# - render 204 for `OPTIONS`
module MyActiveStorageDiskControllerExtension
def update
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = '*'
response.headers['Access-Control-Allow-Headers'] = '*'
response.headers['Access-Control-Max-Age'] = '86400'
if request.method == 'OPTIONS'
head :no_content
else
super
end
end
end
Rails.application.config.to_prepare do
class ActiveStorage::DiskController # rubocop:disable Lint/ConstantDefinitionInBlock
prepend MyActiveStorageDiskControllerExtension
end
end
Rails.application.routes.append do
options '/rails/active_storage/disk/:encoded_token' => 'active_storage/disk#update'
end
But it feels really shady. Do you think it could be worth to do ask Rails maintainers if they would be interested by a PR to support it properly out of the box?
My guess is that most people are only using disk storage for local development, so it doesn’t come up a lot. Having had to fight CORS myself, I would say that anything that helps with CORS issues and good configuration would be greatly appreciated.