Skip to content

Commit 6d126e0

Browse files
authored
Merge pull request rails#51288 from JoeDupuis/stop-caching-on-failure-activestorage-proxy-controller
Expire caching when a download fail while proxying in ActiveStorage
2 parents 5ef7f73 + f7ecde8 commit 6d126e0

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

activestorage/app/controllers/concerns/active_storage/streaming.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ def send_blob_stream(blob, disposition: nil) # :doc:
6161
blob.download do |chunk|
6262
stream.write chunk
6363
end
64+
rescue ActiveStorage::FileNotFoundError
65+
expires_now
66+
head :not_found
67+
rescue
68+
# Status and caching headers are already set, but not commited.
69+
# Change the status to 500 manually.
70+
expires_now
71+
head :internal_server_error
72+
raise
6473
end
6574
end
6675
end

activestorage/test/controllers/blobs/proxy_controller_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,32 @@ class ActiveStorage::Blobs::ProxyControllerTest < ActionDispatch::IntegrationTes
1616
assert_equal "max-age=3155695200, public", response.headers["Cache-Control"]
1717
end
1818

19+
test "invalidates cache and returns a 404 if the file is not found on download" do
20+
blob = create_file_blob(filename: "racecar.jpg")
21+
mock_download = lambda do |_|
22+
raise ActiveStorage::FileNotFoundError.new "File still uploading!"
23+
end
24+
blob.service.stub(:download, mock_download) do
25+
get rails_storage_proxy_url(blob)
26+
end
27+
assert_response :not_found
28+
assert_equal "no-cache", response.headers["Cache-Control"]
29+
end
30+
31+
32+
test "invalidates cache and returns a 500 if an error is raised on download" do
33+
blob = create_file_blob(filename: "racecar.jpg")
34+
mock_download = lambda do |_|
35+
raise StandardError.new "Something is not cool!"
36+
end
37+
blob.service.stub(:download, mock_download) do
38+
get rails_storage_proxy_url(blob)
39+
end
40+
assert_response :internal_server_error
41+
assert_equal "no-cache", response.headers["Cache-Control"]
42+
end
43+
44+
1945
test "forcing Content-Type to binary" do
2046
get rails_storage_proxy_url(create_blob(content_type: "text/html"))
2147
assert_equal "application/octet-stream", response.headers["Content-Type"]

activestorage/test/controllers/representations/proxy_controller_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require "test_helper"
44
require "database/setup"
5+
require "minitest/mock"
56

67
class ActiveStorage::Representations::ProxyControllerWithVariantsTest < ActionDispatch::IntegrationTest
78
setup do
@@ -84,6 +85,39 @@ class ActiveStorage::Representations::ProxyControllerWithVariantsWithStrictLoadi
8485
assert_match(/^inline/, response.headers["Content-Disposition"])
8586
assert_equal @blob.variant(@transformations).download, response.body
8687
end
88+
89+
90+
test "invalidates cache and returns a 404 if the file is not found on download" do
91+
# This mock requires a pre-processed variant as processing the variant will call to download
92+
mock_download = lambda do |_|
93+
raise ActiveStorage::FileNotFoundError.new "File still uploading!"
94+
end
95+
96+
@blob.service.stub(:download, mock_download) do
97+
get rails_blob_representation_proxy_url(
98+
filename: @blob.filename,
99+
signed_blob_id: @blob.signed_id,
100+
variation_key: ActiveStorage::Variation.encode(@transformations))
101+
end
102+
assert_response :not_found
103+
assert_equal "no-cache", response.headers["Cache-Control"]
104+
end
105+
106+
test "invalidates cache and returns a 500 if the an error is raised on download" do
107+
# This mock requires a pre-processed variant as processing the variant will call to download
108+
mock_download = lambda do |_|
109+
raise StandardError.new "Something is not cool!"
110+
end
111+
112+
@blob.service.stub(:download, mock_download) do
113+
get rails_blob_representation_proxy_url(
114+
filename: @blob.filename,
115+
signed_blob_id: @blob.signed_id,
116+
variation_key: ActiveStorage::Variation.encode(@transformations))
117+
end
118+
assert_response :internal_server_error
119+
assert_equal "no-cache", response.headers["Cache-Control"]
120+
end
87121
end
88122

89123
class ActiveStorage::Representations::ProxyControllerWithPreviewsTest < ActionDispatch::IntegrationTest

0 commit comments

Comments
 (0)