Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Active storage add proxying #34477

Merged
Show file tree
Hide file tree
Changes from 113 commits
Commits
Show all changes
170 commits
Select commit Hold shift + click to select a range
d0b1280
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Nov 3, 2018
177574f
Basic redirects and proxying is working on the model level.
fleck Nov 5, 2018
31a2d2a
Proxying variants is working.
fleck Nov 8, 2018
09f37c3
Fix preview.
fleck Nov 8, 2018
39eb31a
Working on previews.
fleck Nov 8, 2018
71b499e
Should fix errors with previews not streaming.
fleck Nov 14, 2018
7c00122
Move delivery logic to method.
fleck Nov 15, 2018
96b54a7
change delivery method default and add support for direct.
fleck Nov 17, 2018
0b488cc
Fix blob route.
fleck Nov 17, 2018
5281255
Accidentally removed blob resolver, re add it.
fleck Nov 17, 2018
4dd0e2f
Basic redirects and proxying is working on the model level.
fleck Nov 5, 2018
0db8f77
Proxying variants is working.
fleck Nov 8, 2018
813b8e0
Fix preview.
fleck Nov 8, 2018
ca72a7e
Working on previews.
fleck Nov 8, 2018
73f2202
Should fix errors with previews not streaming.
fleck Nov 14, 2018
8ee4bfb
Move delivery logic to method.
fleck Nov 15, 2018
3a1bc1d
change delivery method default and add support for direct.
fleck Nov 17, 2018
61d228d
Fix blob route.
fleck Nov 17, 2018
c82b288
Accidentally removed blob resolver, re add it.
fleck Nov 17, 2018
0f621c8
Merge branch 'active-storage-add-proxying-and-direct-downloads' of gi…
fleck Nov 17, 2018
9e34b40
Remove extra comment.
fleck Nov 17, 2018
25429de
Explain variant and preview.
fleck Nov 17, 2018
a55f88f
don't use 'its'
fleck Nov 17, 2018
f5586e2
Fix disposition and content type.
fleck Nov 17, 2018
f016113
Add delivery method to has_many_attached.
fleck Nov 17, 2018
46f110e
Get service_url from processed not blob.
fleck Nov 17, 2018
3ae4936
Fix code climate issues.
fleck Nov 17, 2018
464ed95
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Dec 4, 2018
2d2fb66
Add model instance method overrides.
fleck Dec 4, 2018
f0c7723
Fix code climate issues and give blob method path option.
fleck Dec 4, 2018
331ed77
Merge branch 'master' of https://github.com/rails/rails
fleck Dec 9, 2018
c271ee6
Merge branch 'master' of https://github.com/rails/rails
fleck Dec 16, 2018
9aed641
Merge branch 'master' of https://github.com/rails/rails
fleck Dec 24, 2018
e83edfb
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Dec 24, 2018
da1df76
Make proxied assets public.
fleck Dec 25, 2018
fe0ff8f
Add documentation.
fleck Dec 29, 2018
9676f88
Merge branch 'master' of https://github.com/rails/rails
fleck Dec 30, 2018
b31bb85
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Dec 30, 2018
97ebfaf
Added test for blobs controller to verify correct caching.
fleck Jan 1, 2019
969a1ed
Test representation proxy cache control headers.
fleck Jan 1, 2019
ec254dd
Test global proxying option.
fleck Jan 12, 2019
017e8ae
Add test for deliver method on blob.
fleck Jan 13, 2019
b932f1b
Test delivery on variants.
fleck Jan 13, 2019
80db667
Change range for comparison.
fleck Jan 13, 2019
7bfb8b2
Fixed bug with model delivery setting.
fleck Jan 14, 2019
3d76291
Update configuration test.
fleck Jan 14, 2019
66a4a20
Update routes test.
fleck Jan 14, 2019
93fbf27
Dry up routes.
fleck Jan 15, 2019
13ac0f4
Change parameter name.
fleck Jan 15, 2019
1483c17
Add tests for delivery method on model.
fleck Jan 15, 2019
6ef2c7e
Test preview methods.
fleck Jan 15, 2019
18deb51
Clean up delivery method test.
fleck Jan 15, 2019
24244d7
Add test for preview.
fleck Jan 15, 2019
0cea5a0
Merge branch 'master' of https://github.com/rails/rails
fleck Jan 15, 2019
ba02d81
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Jan 15, 2019
da0084c
Fix code climate issues.
fleck Jan 15, 2019
7056d6a
Fix routes_prefix railtie test.
fleck Jan 16, 2019
cec9b0d
Fixed rake routes railtie test.
fleck Jan 16, 2019
72edc1c
Redo backticks in test name.
fleck Jan 16, 2019
93808b7
Updating another routes test.
fleck Jan 16, 2019
ddbe958
Update last rails routes test.
fleck Jan 16, 2019
8ddfa55
Merge branch 'master' of https://github.com/rails/rails
fleck Mar 31, 2019
3d34726
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Mar 31, 2019
16e1641
Merge branch 'master' of https://github.com/rails/rails
fleck Mar 31, 2019
aa6cdf0
Merge branch 'master' of https://github.com/rails/rails
fleck Apr 7, 2019
69fa76a
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Apr 7, 2019
c53b4e6
Remove direct delivery method.
fleck Apr 7, 2019
7fb06f1
Remove tests for direct delivery.
fleck Apr 7, 2019
d6e69e9
Update attachments reflection test.
fleck Apr 7, 2019
a9b249a
Remove dependent reflection.
fleck Apr 7, 2019
a3c2882
Merge branch 'master' of https://github.com/rails/rails
fleck Apr 7, 2019
a335e3b
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Apr 7, 2019
e7979b6
Remove direct from overview.
fleck Apr 8, 2019
290453a
Merge branch 'master' of https://github.com/rails/rails
fleck Apr 27, 2019
4faafc0
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Apr 27, 2019
22645e7
Add support for changing host.
fleck May 13, 2019
1e758f3
Merge branch 'master' of https://github.com/rails/rails
fleck May 13, 2019
1abfd9a
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck May 13, 2019
1dc2188
Refactor logic out of routes and into class
fleck May 29, 2019
cc8d0c3
Fix code climate issues.
fleck May 29, 2019
486b0bc
Merge branch 'master' of https://github.com/rails/rails
fleck Jun 1, 2019
f84e086
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Jun 1, 2019
06693d4
Clean up some edge cases and add test.
fleck Jun 1, 2019
baa1929
Update docs.
fleck Jun 1, 2019
6ce1f1b
Clean up extra curly braces
fleck Jun 1, 2019
73639b8
Proxy delivery method is working
fleck Jul 27, 2019
64d6a28
Move url options method.
fleck Jul 29, 2019
86131e3
Merge branch 'master' of https://github.com/rails/rails
fleck Jul 29, 2019
7c23631
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Jul 29, 2019
7660a4f
code climate fixes.
fleck Jul 29, 2019
6c1d003
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Aug 3, 2019
21b29bc
Move URL options to each class.
fleck Aug 5, 2019
521244f
simply registering delivery method.
fleck Aug 19, 2019
eacde0f
Variants are working for has_one
fleck Aug 20, 2019
e772d75
Less nils
fleck Aug 20, 2019
d117ab9
Fix model level setting.
fleck Aug 22, 2019
302923a
Cleaning up tests to use .url
fleck Aug 22, 2019
fb397b2
Can't set cache control per instance
fleck Aug 22, 2019
acf951a
Fix expire time
fleck Aug 22, 2019
9b7ca2c
Merge branch 'master' into active-storage-add-proxying-and-direct-dow…
fleck Aug 30, 2019
71d8a2c
Split up config
fleck Oct 1, 2019
32d604c
Add docs for cdn.
fleck Oct 1, 2019
2f15573
Remove cloudflare from docs.
fleck Oct 1, 2019
f35423b
Clean up host docs.
fleck Oct 1, 2019
cc545d6
Updating overview.
fleck Oct 1, 2019
bcb5ffe
Update configuration.
fleck Oct 1, 2019
bdd0f80
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Oct 1, 2019
eb64ff0
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Oct 2, 2019
d09134c
Update docs and engine.
fleck Oct 16, 2019
c8c67ba
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Oct 16, 2019
68a36ad
Fix method name.
fleck Oct 16, 2019
5930a22
Fix config test.
fleck Oct 16, 2019
1938c82
Update to new method in tests.
fleck Oct 16, 2019
fbaaca9
days is more readable.
fleck Oct 21, 2019
68f9816
simplifying
fleck Nov 6, 2019
e717e69
Use days for proxy_urls_expire_in
fleck Nov 6, 2019
bd19891
Moving header logic to concern, removing extra delivery_methods
fleck Nov 6, 2019
1207c3c
Remove dup routes_prefix
fleck Nov 6, 2019
ba1f16f
Remove model delivery_method from test.
fleck Nov 6, 2019
7819297
set headers in concern.
fleck Nov 6, 2019
4accc9d
Cleanup routes.
fleck Nov 19, 2019
2003663
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Nov 19, 2019
f4044b8
Fix typo.
fleck Nov 28, 2019
f67a4bc
use same convention for routes.
fleck Nov 28, 2019
4bd8f5f
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Dec 16, 2019
1927754
move url call to the model.
fleck Dec 28, 2019
99386a3
Cleanup old implementation
fleck Dec 28, 2019
366ab0b
Remove extra settings.
fleck Dec 28, 2019
975571e
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Mar 11, 2020
2817a38
Remove methods from model.
fleck Mar 11, 2020
c07d9ad
Add direct route for proxy
fleck Mar 14, 2020
c9342c7
same API for blobs and representations
fleck Mar 15, 2020
dc84bdd
split routes
fleck Apr 1, 2020
a147010
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Apr 1, 2020
e698761
Set expire in controller.
fleck Apr 1, 2020
387baf3
Start cleaning up tests.
fleck Apr 1, 2020
c08951d
Allow custom resolve name
fleck Apr 8, 2020
293553d
Update docs.
fleck Apr 8, 2020
c8fc088
tweak
fleck Apr 8, 2020
108e344
Update config readme.
fleck Apr 8, 2020
e4eba43
typo
fleck Apr 8, 2020
491b4d5
Revert model test.
fleck Apr 8, 2020
b7cc8c7
Revert old test changes.
fleck Apr 8, 2020
6d732d2
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Apr 8, 2020
176edc7
Update expanded routes.
fleck Apr 8, 2020
3e79f37
Fix routes -g show
fleck Apr 8, 2020
69260a8
Fix another route test.
fleck Apr 8, 2020
7d2ad32
Update config test.
fleck Apr 8, 2020
b09f350
fix rake route test.
fleck Apr 8, 2020
ea0bda8
change config name
fleck Apr 9, 2020
9ff39ac
Update routes in test.
fleck Apr 9, 2020
2885507
Update form helper test.
fleck Apr 9, 2020
dec20c4
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck Apr 9, 2020
517d984
Fix bug with proxying previews, add tests
fleck Apr 20, 2020
3d681a9
Fix spacing in engine.
fleck Apr 20, 2020
6d99bd7
Merge branch 'master' of https://github.com/rails/rails into active-s…
fleck May 10, 2020
824c703
Update readme
fleck May 10, 2020
a84d081
Use cache forever method.
fleck May 10, 2020
b787c96
Rename method.
fleck May 10, 2020
aea29e9
Update key methods
fleck May 10, 2020
d375962
extract stream method
fleck May 10, 2020
395e0b3
Document controllers.
fleck May 10, 2020
a7dc7dd
appease rubocop
fleck May 10, 2020
d3a6ba7
Use the block form of http_cache_forever
georgeclaghorn May 11, 2020
178260c
Split tests by controller
georgeclaghorn May 11, 2020
4d14661
Tweak controller names: redirection → redirect
georgeclaghorn May 11, 2020
49027c6
Add CHANGELOG entry
georgeclaghorn May 11, 2020
7558486
Tweak README [ci skip]
georgeclaghorn May 11, 2020
3ee6b44
Update Railties tests for new controller names
georgeclaghorn May 11, 2020
ed22fd4
Update configuring guide [ci skip]
georgeclaghorn May 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions activestorage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,38 @@ Variation of image attachment:
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %>
```

## Delivery methods
You can change the delivery method to best suit the needs of your application.

### Redirect (default)
Requests for files will redirect to a temporary service URL.

### Proxy
Files are proxied through the application server so they appear as though they're being served from your server. Useful for serving images from a CDN or HTML caching.

### Changing delivery method
globally
```ruby
config.active_storage.default_delivery_method = :proxy
```
model
```ruby
has_one_attached :avatar, delivery_method: :proxy
```
view
```ruby
user.avatar.variant(resize: "100x100").deliver(:proxy)
```

### Changing the host of proxied urls
When using the proxy option to deliver assets you can set the host. This is useful if your CDN is setup to operate on a different domain.

```ruby
config.active_storage.delivery_methods = {
proxy: ActiveStorage::DeliveryMethod::Proxy.new(host: 'cdn.domain.com')
}
fleck marked this conversation as resolved.
Show resolved Hide resolved
fleck marked this conversation as resolved.
Show resolved Hide resolved
```

## Direct uploads

Active Storage, with its included JavaScript library, supports uploading directly from the client to the cloud.
Expand Down
13 changes: 13 additions & 0 deletions activestorage/app/controllers/active_storage/blobs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,17 @@ def show
expires_in ActiveStorage.service_urls_expire_in
redirect_to @blob.url(disposition: params[:disposition])
end

def proxy
fleck marked this conversation as resolved.
Show resolved Hide resolved
expires_in ActiveStorage.proxy_urls_expire_in, public: true

response.headers["Content-Type"] = @blob.content_type
response.headers["Content-Disposition"] = @blob.disposition(params[:disposition])

@blob.download do |chunk|
response.stream.write(chunk)
end
fleck marked this conversation as resolved.
Show resolved Hide resolved
ensure
response.stream.close
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,19 @@ def show
expires_in ActiveStorage.service_urls_expire_in
redirect_to @blob.representation(params[:variation_key]).processed.service_url(disposition: params[:disposition])
end

def proxy
fleck marked this conversation as resolved.
Show resolved Hide resolved
expires_in params[:proxy_urls_expire_in], public: params[:proxy_urls_public]

representation = @blob.representation(params[:variation_key]).processed

response.headers["Content-Disposition"] = representation.image.blob.disposition(params[:disposition])
response.headers["Content-Type"] = representation.image.content_type

@blob.service.download(representation.key) do |chunk|
response.stream.write(chunk)
end
ensure
response.stream.close
end
end
12 changes: 12 additions & 0 deletions activestorage/app/models/active_storage/attachment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ def purge_later
blob&.purge_later
end

def url(override_delivery_method = record.public_send("#{name}_delivery_method"))
blob.delivery_method_url(override_delivery_method)
end

def variant(transformations)
blob.variant(transformations, record.public_send("#{name}_delivery_method"))
end

def preview(transformations)
blob.preview(transformations, record.public_send("#{name}_delivery_method"))
end
fleck marked this conversation as resolved.
Show resolved Hide resolved

private
def identify_blob
blob.identify
Expand Down
11 changes: 11 additions & 0 deletions activestorage/app/models/active_storage/blob.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ def key
self[:key] ||= self.class.generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
end

def delivery_method_url(method = ActiveStorage.default_delivery_method)
ActiveStorage.delivery_methods.fetch(method).blob_url(signed_id, filename)
end

# Returns an ActiveStorage::Filename instance of the filename that can be
# queried for basename, extension, and a sanitized version of the filename
# that's safe to use in URLs.
Expand Down Expand Up @@ -157,6 +161,13 @@ def text?
content_type.start_with?("text")
end

def disposition(disposition_override = nil)
ActionDispatch::Http::ContentDisposition.format(
disposition: disposition_override || "inline",
filename: filename.sanitized
)
end
fleck marked this conversation as resolved.
Show resolved Hide resolved

# Returns the URL of the blob on the service. This returns a permanent URL for public files, and returns a
# short-lived URL for private files. Private files are for security and not used directly with users, instead,
# the URL should only be exposed as a redirect from a stable, possibly authenticated URL. Hiding the
Expand Down
8 changes: 4 additions & 4 deletions activestorage/app/models/active_storage/blob/representable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ module ActiveStorage::Blob::Representable
#
# Raises ActiveStorage::InvariableError if ImageMagick cannot transform the blob. To determine whether a blob is
# variable, call ActiveStorage::Blob#variable?.
def variant(transformations)
def variant(transformations, delivery_method = nil)
fleck marked this conversation as resolved.
Show resolved Hide resolved
if variable?
ActiveStorage::Variant.new(self, transformations)
ActiveStorage::Variant.new(self, transformations, delivery_method)
else
raise ActiveStorage::InvariableError
end
Expand All @@ -53,9 +53,9 @@ def variable?
#
# This method raises ActiveStorage::UnpreviewableError if no previewer accepts the receiving blob. To determine
# whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.
def preview(transformations)
def preview(transformations, delivery_method = nil)
if previewable?
ActiveStorage::Preview.new(self, transformations)
ActiveStorage::Preview.new(self, transformations, delivery_method)
else
raise ActiveStorage::UnpreviewableError
end
Expand Down
16 changes: 13 additions & 3 deletions activestorage/app/models/active_storage/preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
class ActiveStorage::Preview
class UnprocessedError < StandardError; end

attr_reader :blob, :variation
attr_reader :blob, :variation, :delivery_method

def initialize(blob, variation_or_variation_key)
@blob, @variation = blob, ActiveStorage::Variation.wrap(variation_or_variation_key)
def initialize(blob, variation_or_variation_key, delivery_method = nil)
@blob, @variation, @delivery_method = blob, ActiveStorage::Variation.wrap(variation_or_variation_key), delivery_method
end

# Processes the preview if it has not been processed yet. Returns the receiving Preview instance for convenience:
Expand Down Expand Up @@ -65,6 +65,16 @@ def service_url(**options)
end
end

# Returns a combination key of the blob and the variation that together identifies a specific variant.
def key
"variants/#{image.key}/#{Digest::SHA256.hexdigest(variation.key)}"
end
fleck marked this conversation as resolved.
Show resolved Hide resolved

# Proxies the url method to the variation.
def url(method = delivery_method)
variation.url(method, self)
end

private
def processed?
image.attached?
Expand Down
10 changes: 7 additions & 3 deletions activestorage/app/models/active_storage/variant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@
class ActiveStorage::Variant
WEB_IMAGE_CONTENT_TYPES = %w[ image/png image/jpeg image/jpg image/gif ]

attr_reader :blob, :variation
attr_reader :blob, :variation, :delivery_method
delegate :service, to: :blob

def initialize(blob, variation_or_variation_key)
@blob, @variation = blob, ActiveStorage::Variation.wrap(variation_or_variation_key)
def initialize(blob, variation_or_variation_key, delivery_method = nil)
@blob, @variation, @delivery_method = blob, ActiveStorage::Variation.wrap(variation_or_variation_key), delivery_method
end

# Returns the variant instance itself after it's been processed or an existing processing has been found on the service.
Expand All @@ -73,6 +73,10 @@ def key
"variants/#{blob.key}/#{Digest::SHA256.hexdigest(variation.key)}"
end

def url(method = delivery_method)
variation.url(method, self)
end

# Returns the URL of the variant on the service. This URL is intended to be short-lived for security and not used directly
# with users. Instead, the +service_url+ should only be exposed as a redirect from a stable, possibly authenticated URL.
# Hiding the +service_url+ behind a redirect also gives you the power to change services without updating all URLs. And
Expand Down
4 changes: 4 additions & 0 deletions activestorage/app/models/active_storage/variation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def encode(transformations)
end
end

def url(method, representation)
ActiveStorage.delivery_methods.fetch(method).representation_url(representation)
end

def initialize(transformations)
@transformations = transformations.deep_symbolize_keys
end
Expand Down
2 changes: 2 additions & 0 deletions activestorage/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
Rails.application.routes.draw do
scope ActiveStorage.routes_prefix do
get "/blobs/:signed_id/*filename" => "active_storage/blobs#show", as: :rails_service_blob
get "/blobs_proxy/:signed_id/*filename" => "active_storage/blobs#proxy", as: :rails_blob_proxy
fleck marked this conversation as resolved.
Show resolved Hide resolved

get "/representations/:signed_blob_id/:variation_key/*filename" => "active_storage/representations#show", as: :rails_blob_representation
get "/representations_proxy/:signed_blob_id/:variation_key/*filename" => "active_storage/representations#proxy", as: :rails_blob_representation_proxy
fleck marked this conversation as resolved.
Show resolved Hide resolved

get "/disk/public/:key/*filename" => "active_storage/public_disk#show", as: :rails_disk_service_public
get "/disk/:encoded_key/*filename" => "active_storage/disk#show", as: :rails_disk_service
Expand Down
8 changes: 8 additions & 0 deletions activestorage/lib/active_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module ActiveStorage
autoload :ServiceRegistry
autoload :Previewer
autoload :Analyzer
autoload :DeliveryMethod

mattr_accessor :logger
mattr_accessor :verifier
Expand All @@ -65,6 +66,13 @@ module ActiveStorage

mattr_accessor :replace_on_assign_to_many, default: false

mattr_accessor :delivery_methods, default: {}
mattr_accessor :default_delivery_method, default: :redirect

mattr_accessor :proxy_urls_expire_in, default: 525600.minutes
fleck marked this conversation as resolved.
Show resolved Hide resolved

mattr_accessor :routes_prefix, default: "/rails/active_storage"

module Transformers
extend ActiveSupport::Autoload

Expand Down
12 changes: 10 additions & 2 deletions activestorage/lib/active_storage/attached/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@ module Attached::Model
# has_one_attached :avatar, service: :s3
# end
#
def has_one_attached(name, dependent: :purge_later, service: nil)
def has_one_attached(name, dependent: :purge_later, service: nil, delivery_method: ActiveStorage.default_delivery_method)
fleck marked this conversation as resolved.
Show resolved Hide resolved
validate_service_configuration(name, service)

generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
def #{name}
@active_storage_attached_#{name} ||= ActiveStorage::Attached::One.new("#{name}", self)
end

def #{name}_delivery_method
fleck marked this conversation as resolved.
Show resolved Hide resolved
:#{delivery_method}
end

def #{name}=(attachable)
attachment_changes["#{name}"] =
if attachable.nil?
Expand Down Expand Up @@ -109,14 +113,18 @@ def #{name}=(attachable)
# has_many_attached :photos, service: :s3
# end
#
def has_many_attached(name, dependent: :purge_later, service: nil)
def has_many_attached(name, dependent: :purge_later, service: nil, delivery_method: ActiveStorage.default_delivery_method)
fleck marked this conversation as resolved.
Show resolved Hide resolved
validate_service_configuration(name, service)

generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
def #{name}
@active_storage_attached_#{name} ||= ActiveStorage::Attached::Many.new("#{name}", self)
end

def #{name}_delivery_method
:#{delivery_method}
end

def #{name}=(attachables)
if ActiveStorage.replace_on_assign_to_many
attachment_changes["#{name}"] =
Expand Down
1 change: 1 addition & 0 deletions activestorage/lib/active_storage/attached/one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module ActiveStorage
# Representation of a single attachment to a model.
class Attached::One < Attached
delegate_missing_to :attachment, allow_nil: true
attr_accessor :delivery_method

# Returns the associated attachment record.
#
Expand Down
13 changes: 13 additions & 0 deletions activestorage/lib/active_storage/delivery_method.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module ActiveStorage
class DeliveryMethod
def representation_url(representation, url_options: nil, delivery_method: nil)
raise NotImplementedError
end

def blob_url(signed_id, filename, url_options: nil, delivery_method: nil)
raise NotImplementedError
end
end
end
31 changes: 31 additions & 0 deletions activestorage/lib/active_storage/delivery_method/proxy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

module ActiveStorage
class DeliveryMethod::Proxy < DeliveryMethod
# * :host - Specifies the host the link should be targeted at.
def initialize(options = {})
@options = options

@options[:only_path] = true unless options[:host]
end

def representation_url(representation, url_options: {})
Rails.application.routes.url_helpers.route_for(
:rails_blob_representation_proxy,
representation.blob.signed_id,
representation.variation.key,
representation.blob.filename,
@options.merge(url_options)
)
end

def blob_url(signed_id, filename, url_options: {})
Rails.application.routes.url_helpers.route_for(
:rails_blob_proxy,
signed_id,
filename,
@options.merge(url_options)
)
end
end
end
28 changes: 28 additions & 0 deletions activestorage/lib/active_storage/delivery_method/redirect.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

module ActiveStorage
class DeliveryMethod::Redirect < DeliveryMethod
def initialize(options = {})
@options = { only_path: true }.merge(options)
end

def representation_url(representation, url_options: {})
Rails.application.routes.url_helpers.route_for(
:rails_blob_representation,
representation.blob.signed_id,
representation.variation.key,
representation.blob.filename,
@options.merge(url_options)
)
end

def blob_url(signed_id, filename, url_options: {})
Rails.application.routes.url_helpers.route_for(
:rails_service_blob,
signed_id,
filename,
@options.merge(url_options)
)
end
end
end
13 changes: 13 additions & 0 deletions activestorage/lib/active_storage/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

require "active_storage/reflection"

require "active_storage/delivery_method/redirect"
require "active_storage/delivery_method/proxy"

module ActiveStorage
class Engine < Rails::Engine # :nodoc:
isolate_namespace ActiveStorage
Expand Down Expand Up @@ -78,10 +81,20 @@ class Engine < Rails::Engine # :nodoc:
ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
ActiveStorage.service_urls_expire_in = app.config.active_storage.service_urls_expire_in || 5.minutes

ActiveStorage.content_types_allowed_inline = app.config.active_storage.content_types_allowed_inline || []
ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"

ActiveStorage.replace_on_assign_to_many = app.config.active_storage.replace_on_assign_to_many || false

ActiveStorage.delivery_methods = {
redirect: ActiveStorage::DeliveryMethod::Redirect.new,
proxy: ActiveStorage::DeliveryMethod::Proxy.new
}.merge(app.config.active_storage.delivery_methods || {})

ActiveStorage.default_delivery_method = app.config.active_storage.default_delivery_method || :redirect

ActiveStorage.proxy_urls_expire_in = app.config.active_storage.proxy_urls_expire_in || 525600.minutes
end
end

Expand Down