Use a current model to provide the host for service urls

Trying to pass the current request down to the service so that it can
create full urls instead of paths makes the API messy so use a model
based on ActiveSupport::CurrentAttributes to provide the current host
to services that need it (primarily the disk service).
This commit is contained in:
Andrew White 2018-03-26 14:36:39 +01:00
parent 03bd370c02
commit 9436c22e2a
No known key found for this signature in database
GPG Key ID: 7E83729F16B086CF
6 changed files with 26 additions and 6 deletions

View File

@ -3,4 +3,8 @@
# The base controller for all ActiveStorage controllers. # The base controller for all ActiveStorage controllers.
class ActiveStorage::BaseController < ActionController::Base class ActiveStorage::BaseController < ActionController::Base
protect_from_forgery with: :exception protect_from_forgery with: :exception
before_action do
ActiveStorage::Current.host = request.base_url
end
end end

View File

@ -0,0 +1,5 @@
# frozen_string_literal: true
class ActiveStorage::Current < ActiveSupport::CurrentAttributes #:nodoc:
attribute :host
end

View File

@ -78,8 +78,9 @@ module ActiveStorage
verified_key_with_expiration = ActiveStorage.verifier.generate(key, expires_in: expires_in, purpose: :blob_key) verified_key_with_expiration = ActiveStorage.verifier.generate(key, expires_in: expires_in, purpose: :blob_key)
generated_url = generated_url =
url_helpers.rails_disk_service_path( url_helpers.rails_disk_service_url(
verified_key_with_expiration, verified_key_with_expiration,
host: current_host,
filename: filename, filename: filename,
disposition: content_disposition_with(type: disposition, filename: filename), disposition: content_disposition_with(type: disposition, filename: filename),
content_type: content_type content_type: content_type
@ -104,7 +105,7 @@ module ActiveStorage
purpose: :blob_token } purpose: :blob_token }
) )
generated_url = url_helpers.update_rails_disk_service_path(verified_token_with_expiration) generated_url = url_helpers.update_rails_disk_service_url(verified_token_with_expiration, host: current_host)
payload[:url] = generated_url payload[:url] = generated_url
@ -129,7 +130,6 @@ module ActiveStorage
path_for(key).tap { |path| FileUtils.mkdir_p File.dirname(path) } path_for(key).tap { |path| FileUtils.mkdir_p File.dirname(path) }
end end
def ensure_integrity_of(key, checksum) def ensure_integrity_of(key, checksum)
unless Digest::MD5.file(path_for(key)).base64digest == checksum unless Digest::MD5.file(path_for(key)).base64digest == checksum
delete key delete key
@ -137,9 +137,12 @@ module ActiveStorage
end end
end end
def url_helpers def url_helpers
@url_helpers ||= Rails.application.routes.url_helpers @url_helpers ||= Rails.application.routes.url_helpers
end end
def current_host
ActiveStorage::Current.host
end
end end
end end

View File

@ -140,6 +140,6 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase
def expected_url_for(blob, disposition: :inline, filename: nil) def expected_url_for(blob, disposition: :inline, filename: nil)
filename ||= blob.filename filename ||= blob.filename
query_string = { content_type: blob.content_type, disposition: "#{disposition}; #{filename.parameters}" }.to_param query_string = { content_type: blob.content_type, disposition: "#{disposition}; #{filename.parameters}" }.to_param
"/rails/active_storage/disk/#{ActiveStorage.verifier.generate(blob.key, expires_in: 5.minutes, purpose: :blob_key)}/#{filename}?#{query_string}" "https://example.com/rails/active_storage/disk/#{ActiveStorage.verifier.generate(blob.key, expires_in: 5.minutes, purpose: :blob_key)}/#{filename}?#{query_string}"
end end
end end

View File

@ -8,7 +8,7 @@ class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
include ActiveStorage::Service::SharedServiceTests include ActiveStorage::Service::SharedServiceTests
test "url generation" do test "url generation" do
assert_match(/rails\/active_storage\/disk\/.*\/avatar\.png\?content_type=image%2Fpng&disposition=inline/, assert_match(/^https:\/\/example.com\/rails\/active_storage\/disk\/.*\/avatar\.png\?content_type=image%2Fpng&disposition=inline/,
@service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: ActiveStorage::Filename.new("avatar.png"), content_type: "image/png")) @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: ActiveStorage::Filename.new("avatar.png"), content_type: "image/png"))
end end
end end

View File

@ -41,6 +41,14 @@ ActiveStorage.verifier = ActiveSupport::MessageVerifier.new("Testing")
class ActiveSupport::TestCase class ActiveSupport::TestCase
self.file_fixture_path = File.expand_path("fixtures/files", __dir__) self.file_fixture_path = File.expand_path("fixtures/files", __dir__)
setup do
ActiveStorage::Current.host = "https://example.com"
end
teardown do
ActiveStorage::Current.reset
end
private private
def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain") def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
ActiveStorage::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type ActiveStorage::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type