Skip to content

Commit 76694cc

Browse files
authored
Merge pull request rails#41391 from santib/fix-disk-storage-protocol
Fix rails#41388 by preserving protocol and port when generating routes
2 parents 97ff46c + e9accaf commit 76694cc

File tree

6 files changed

+61
-25
lines changed

6 files changed

+61
-25
lines changed

activestorage/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Deprecate `ActiveStorage::Current.host` in favor of `ActiveStorage::Current.url_options` which accepts
2+
a host, protocol and port.
3+
4+
*Santiago Bartesaghi*
5+
16
* Allow using [IAM](https://cloud.google.com/storage/docs/access-control/signed-urls) when signing URLs with GCS.
27

38
```yaml
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# frozen_string_literal: true
22

3-
# Sets the <tt>ActiveStorage::Current.host</tt> attribute, which the disk service uses to generate URLs.
3+
# Sets the <tt>ActiveStorage::Current.url_options</tt> attribute, which the disk service uses to generate URLs.
44
# Include this concern in custom controllers that call ActiveStorage::Blob#url,
55
# ActiveStorage::Variant#url, or ActiveStorage::Preview#url so the disk service can
6-
# generate URLs using the same host, protocol, and base path as the current request.
6+
# generate URLs using the same host, protocol, and port as the current request.
77
module ActiveStorage::SetCurrent
88
extend ActiveSupport::Concern
99

1010
included do
1111
before_action do
12-
ActiveStorage::Current.host = request.base_url
12+
ActiveStorage::Current.url_options = { protocol: request.protocol, host: request.host, port: request.port }
1313
end
1414
end
1515
end
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# frozen_string_literal: true
22

33
class ActiveStorage::Current < ActiveSupport::CurrentAttributes #:nodoc:
4-
attribute :host
4+
attribute :url_options
5+
6+
def host=(host)
7+
ActiveSupport::Deprecation.warn("ActiveStorage::Current.host= is deprecated, instead use ActiveStorage::Current.url_options=")
8+
self.url_options = { host: host }
9+
end
10+
11+
def host
12+
ActiveSupport::Deprecation.warn("ActiveStorage::Current.host is deprecated, instead use ActiveStorage::Current.url_options")
13+
self.url_options&.dig(:host)
14+
end
515
end

activestorage/lib/active_storage/service/disk_service.rb

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,9 @@ def url_for_direct_upload(key, expires_in:, content_type:, content_length:, chec
8686
purpose: :blob_token
8787
)
8888

89-
generated_url = url_helpers.update_rails_disk_service_url(verified_token_with_expiration, host: current_host)
90-
91-
payload[:url] = generated_url
92-
93-
generated_url
89+
url_helpers.update_rails_disk_service_url(verified_token_with_expiration, url_options).tap do |generated_url|
90+
payload[:url] = generated_url
91+
end
9492
end
9593
end
9694

@@ -124,18 +122,11 @@ def generate_url(key, expires_in:, filename:, content_type:, disposition:)
124122
purpose: :blob_key
125123
)
126124

127-
if current_host.blank?
128-
raise ArgumentError, "Cannot generate URL for #{filename} using Disk service, please set ActiveStorage::Current.host."
125+
if url_options.blank?
126+
raise ArgumentError, "Cannot generate URL for #{filename} using Disk service, please set ActiveStorage::Current.url_options."
129127
end
130128

131-
current_uri = URI.parse(current_host)
132-
133-
url_helpers.rails_disk_service_url(verified_key_with_expiration,
134-
protocol: current_uri.scheme,
135-
host: current_uri.host,
136-
port: current_uri.port,
137-
filename: filename
138-
)
129+
url_helpers.rails_disk_service_url(verified_key_with_expiration, filename: filename, **url_options)
139130
end
140131

141132

@@ -168,8 +159,8 @@ def url_helpers
168159
@url_helpers ||= Rails.application.routes.url_helpers
169160
end
170161

171-
def current_host
172-
ActiveStorage::Current.host
162+
def url_options
163+
ActiveStorage::Current.url_options
173164
end
174165
end
175166
end

activestorage/test/service/disk_service_test.rb

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
1212
assert_equal :tmp, @service.name
1313
end
1414

15+
test "url_for_direct_upload" do
16+
original_url_options = Rails.application.routes.default_url_options.dup
17+
Rails.application.routes.default_url_options.merge!(protocol: "http", host: "test.example.com", port: 3001)
18+
19+
key = SecureRandom.base58(24)
20+
data = "Something else entirely!"
21+
checksum = Digest::MD5.base64digest(data)
22+
23+
begin
24+
assert_match(/^https:\/\/example.com\/rails\/active_storage\/disk\/.*$/,
25+
@service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum))
26+
ensure
27+
Rails.application.routes.default_url_options = original_url_options
28+
end
29+
end
30+
1531
test "URL generation" do
1632
original_url_options = Rails.application.routes.default_url_options.dup
1733
Rails.application.routes.default_url_options.merge!(protocol: "http", host: "test.example.com", port: 3001)
@@ -23,14 +39,28 @@ class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
2339
end
2440
end
2541

26-
test "URL generation without ActiveStorage::Current.host set" do
27-
ActiveStorage::Current.host = nil
42+
test "URL generation without ActiveStorage::Current.url_options set" do
43+
ActiveStorage::Current.url_options = nil
2844

2945
error = assert_raises ArgumentError do
3046
@service.url(@key, expires_in: 5.minutes, disposition: :inline, filename: ActiveStorage::Filename.new("avatar.png"), content_type: "image/png")
3147
end
3248

33-
assert_equal("Cannot generate URL for avatar.png using Disk service, please set ActiveStorage::Current.host.", error.message)
49+
assert_equal("Cannot generate URL for avatar.png using Disk service, please set ActiveStorage::Current.url_options.", error.message)
50+
end
51+
52+
test "URL generation keeps working with ActiveStorage::Current.host set" do
53+
ActiveStorage::Current.url_options = nil
54+
ActiveStorage::Current.host = "https://example.com"
55+
56+
original_url_options = Rails.application.routes.default_url_options.dup
57+
Rails.application.routes.default_url_options.merge!(protocol: "http", host: "test.example.com", port: 3001)
58+
begin
59+
assert_match(/^http:\/\/example.com:3001\/rails\/active_storage\/disk\/.*\/avatar\.png$/,
60+
@service.url(@key, expires_in: 5.minutes, disposition: :inline, filename: ActiveStorage::Filename.new("avatar.png"), content_type: "image/png"))
61+
ensure
62+
Rails.application.routes.default_url_options = original_url_options
63+
end
3464
end
3565

3666
test "headers_for_direct_upload generation" do

activestorage/test/test_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class ActiveSupport::TestCase
5353
self.fixture_path = File.expand_path("fixtures", __dir__)
5454

5555
setup do
56-
ActiveStorage::Current.host = "https://example.com"
56+
ActiveStorage::Current.url_options = { protocol: "https://", host: "example.com", port: nil }
5757
end
5858

5959
teardown do

0 commit comments

Comments
 (0)