Skip to content

Commit 550d728

Browse files
committed
Active Storage: incorrect defaults
rails#42225 identified that some of the content types used as defaults by Active Storage aren't recognized by `mini_mime`. This means that in practice code like [this](https://github.com/rails/rails/pull/42225/files#diff-7a3ec24c556b138abdbd67066ab5125b73528e45891d83142e417d3944194128R116) will crash or not function correctly. In [this](https://github.com/rails/rails/pull/42225/files#diff-c2010824d2d2e8d841ff4fc058c264c12d870e893025b153e6de571fba6b6c6cR194) example, a file with content_type `image/jpg` is treated as a PNG by the representer, since `image/jpg` isn't a valid content type according to `mini_mime`. I don't think the default content_types should include formats that have never actually worked, so I'm proposing we remove them from the defaults.
1 parent 4e35354 commit 550d728

File tree

8 files changed

+113
-5
lines changed

8 files changed

+113
-5
lines changed

activestorage/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
* Invalid default content types are deprecated
2+
3+
Blobs created with content_type `image/jpg`, `image/pjpeg`, `image/bmp`, `text/javascript` will now produce
4+
a deprecation warning, since these are not valid content types.
5+
6+
These content types will be removed from the defaults in Rails 7.1.
7+
8+
You can set `config.active_storage.silence_invalid_content_types_warning = true` to dismiss the warning.
9+
10+
*Alex Ghiculescu*
11+
112
## Rails 7.0.0.alpha2 (September 15, 2021) ##
213

314
* No changes.

activestorage/app/models/active_storage/blob.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,31 @@ def service
308308
services.fetch(service_name)
309309
end
310310

311+
def content_type=(value)
312+
unless ActiveStorage.silence_invalid_content_types_warning
313+
if INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7.include?(value)
314+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
315+
#{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
316+
If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.variable_content_types`.
317+
Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
318+
MSG
319+
end
320+
321+
if INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7.include?(value)
322+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
323+
#{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
324+
If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.content_types_to_serve_as_binary`.
325+
Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
326+
MSG
327+
end
328+
end
329+
330+
super
331+
end
332+
333+
INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7 = ["image/jpg", "image/pjpeg", "image/bmp"]
334+
INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7 = ["text/javascript"]
335+
311336
private
312337
def compute_checksum_in_chunks(io)
313338
OpenSSL::Digest::MD5.new.tap do |checksum|

activestorage/lib/active_storage.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ module ActiveStorage
7171

7272
mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
7373

74+
mattr_accessor :silence_invalid_content_types_warning, default: false
75+
7476
module Transformers
7577
extend ActiveSupport::Autoload
7678

activestorage/lib/active_storage/engine.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ class Engine < Rails::Engine # :nodoc:
101101
ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
102102
ActiveStorage.video_preview_arguments = app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
103103

104+
ActiveStorage.silence_invalid_content_types_warning = app.config.active_storage.silence_invalid_content_types_warning || false
105+
104106
ActiveStorage.replace_on_assign_to_many = app.config.active_storage.replace_on_assign_to_many || false
105107
ActiveStorage.track_variants = app.config.active_storage.track_variants || false
106108
end

activestorage/test/engine_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
require "database/setup"
5+
6+
class ActiveStorage::EngineTest < ActiveSupport::TestCase
7+
test "all default content types are recognized by mini_mime" do
8+
exceptions = ActiveStorage::Blob::INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7 + ActiveStorage::Blob::INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7
9+
10+
ActiveStorage.variable_content_types.each do |content_type|
11+
next if exceptions.include?(content_type) # remove this line in Rails 7.1
12+
13+
assert_equal content_type, MiniMime.lookup_by_content_type(content_type).content_type
14+
end
15+
16+
ActiveStorage.web_image_content_types.each do |content_type|
17+
next if exceptions.include?(content_type) # remove this line in Rails 7.1
18+
19+
assert_equal content_type, MiniMime.lookup_by_content_type(content_type).content_type
20+
end
21+
22+
ActiveStorage.content_types_to_serve_as_binary.each do |content_type|
23+
next if exceptions.include?(content_type) # remove this line in Rails 7.1
24+
25+
assert_equal content_type, MiniMime.lookup_by_content_type(content_type).content_type
26+
end
27+
28+
ActiveStorage.content_types_allowed_inline.each do |content_type|
29+
next if exceptions.include?(content_type) # remove this line in Rails 7.1
30+
31+
assert_equal content_type, MiniMime.lookup_by_content_type(content_type).content_type
32+
end
33+
end
34+
end

activestorage/test/models/blob_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,32 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase
293293
end
294294
end
295295

296+
test "warning if blob is created with invalid mime type" do
297+
assert_deprecated do
298+
create_blob(filename: "funky.jpg", content_type: "image/jpg")
299+
end
300+
301+
assert_not_deprecated do
302+
create_blob(filename: "funky.jpg", content_type: "image/jpeg")
303+
end
304+
end
305+
306+
test "warning if blob is created with invalid mime type can be disabled" do
307+
warning_was = ActiveStorage.silence_invalid_content_types_warning
308+
ActiveStorage.silence_invalid_content_types_warning = true
309+
310+
assert_not_deprecated do
311+
create_blob(filename: "funky.jpg", content_type: "image/jpg")
312+
end
313+
314+
assert_not_deprecated do
315+
create_blob(filename: "funky.jpg", content_type: "image/jpeg")
316+
end
317+
318+
ensure
319+
ActiveStorage.silence_invalid_content_types_warning = warning_was
320+
end
321+
296322
private
297323
def expected_url_for(blob, disposition: :attachment, filename: nil, content_type: nil, service_name: :local)
298324
filename ||= blob.filename

activestorage/test/models/variant_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
104104
end
105105

106106
test "resized variation of BMP blob" do
107-
blob = create_file_blob(filename: "colors.bmp", content_type: "image/bmp")
107+
blob = create_file_blob(filename: "colors.bmp", content_type: "image/x-bmp")
108108
variant = blob.variant(resize_to_limit: [15, 15]).processed
109109
assert_match(/colors\.png/, variant.url)
110110

guides/source/configuring.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ can transform through ImageMagick.
15451545
By default, this is defined as:
15461546

15471547
```ruby
1548-
config.active_storage.variable_content_types = %w(image/png image/gif image/jpg image/jpeg image/pjpeg image/tiff image/bmp image/vnd.adobe.photoshop image/vnd.microsoft.icon image/webp image/avif image/heic image/heif)
1548+
config.active_storage.variable_content_types = %w(image/png image/gif image/jpeg image/tiff image/vnd.adobe.photoshop image/vnd.microsoft.icon image/webp image/avif image/heic image/heif)
15491549
```
15501550

15511551
#### `config.active_storage.web_image_content_types`
@@ -1557,7 +1557,7 @@ If you want to use `WebP` or `AVIF` variants in your application you can add
15571557
By default, this is defined as:
15581558

15591559
```ruby
1560-
config.active_storage.web_image_content_types = %w(image/png image/jpeg image/jpg image/gif)
1560+
config.active_storage.web_image_content_types = %w(image/png image/jpeg image/gif)
15611561
```
15621562

15631563
#### `config.active_storage.content_types_to_serve_as_binary`
@@ -1566,7 +1566,7 @@ Accepts an array of strings indicating the content types that Active Storage wil
15661566
By default, this is defined as:
15671567

15681568
```ruby
1569-
config.active_storage.content_types_to_serve_as_binary = %w(text/html text/javascript image/svg+xml application/postscript application/x-shockwave-flash text/xml application/xml application/xhtml+xml application/mathml+xml text/cache-manifest)
1569+
config.active_storage.content_types_to_serve_as_binary = %w(text/html image/svg+xml application/postscript application/x-shockwave-flash text/xml application/xml application/xhtml+xml application/mathml+xml text/cache-manifest)
15701570
```
15711571

15721572
#### `config.active_storage.content_types_allowed_inline`
@@ -1575,7 +1575,15 @@ Accepts an array of strings indicating the content types that Active Storage all
15751575
By default, this is defined as:
15761576

15771577
```ruby
1578-
config.active_storage.content_types_allowed_inline` = %w(image/png image/gif image/jpg image/jpeg image/tiff image/bmp image/vnd.adobe.photoshop image/vnd.microsoft.icon application/pdf)
1578+
config.active_storage.content_types_allowed_inline` = %w(image/png image/gif image/jpeg image/tiff image/vnd.adobe.photoshop image/vnd.microsoft.icon application/pdf)
1579+
```
1580+
1581+
#### `config.active_storage.silence_invalid_content_types_warning`
1582+
1583+
Since Rails 7, Active Storage will warn if you use an invalid content type that was incorrectly supported in Rails 6. You can use this config to turn the warning off.
1584+
1585+
```ruby
1586+
config.active_storage.silence_invalid_content_types_warning = false
15791587
```
15801588

15811589
#### `config.active_storage.queues.analysis`

0 commit comments

Comments
 (0)