How ActionDispatch::Response#content_type Changed between Rails 5.2 to 6.1

How ActionDispatch::Response#content_type Changed between Rails 5.2 to 6.1

If you have ever upgraded Rails from 5.2 to 6.0 opens a new window , you might have run into issues with changes that had been made to the value of ActionDispatch::Response#content_type between the two versions.

If you have been lucky, you might not have even noticed there was a problem until Rails 6.0, after coming across this deprecation message:

Rails 6.1 will return Content-Type header without modification. If you want just the MIME type, please use `#media_type` instead.

What happened with ActionDispatch::Response#content_type between Rails 5.2 to 6.1? In this article, we will go into some background to learn what this method does, look at the differences in ActionDispatch::Response#content_type’s return value between the several Rails versions, and how you can fix the problem if you come across it in your codebase.

Background

First, what is ActionDispatch::Response#content_type? According to the Rails documentation, ActionDispatch::Response is the class that represents an HTTP response generated by a controller action opens a new window . ActionDispatch::Response#content_type returns the content type of the response. The value of ActionDispatch::Response#content_type has changed from Rails 5.2 to 6.1.

Before we go into the details of why and how ActionDispatch::Response#content_type changed, let’s first go over what the Content-Type header and MIME type are and how they relate to each other.

A Content-Type is a header field in the HTTP protocol that specifies the type of data that is being sent in the message body of an HTTP request or response. It tells the recipient of the message how to interpret the data in the message body. Web browsers and other applications use the Content-Type header to determine how to display or process the data received in a response. If the Content-Type header is missing or incorrect, the recipient may not be able to interpret the data correctly.

A MIME type is a string used to identify the type of data in a file, based on its nature and format. It is used to indicate to the browser or other receiving software how to handle the content of a file or a data stream. They are often represented as a combination of a type and subtype, separated by a slash (/), and a series of optional parameters that provide additional information about the content. For example, some commonly used MIME types are:

  • text/html for HTML documents
  • image/jpeg for JPEG image files
  • application/pdf for PDF documents
  • audio/mp3 for MP3 audio files

When a web server sends a response to a client, it typically includes a Content-Type header that specifies the MIME type of the data being sent. The client uses this information to determine how to handle the data, such as whether to display it in a web page, play it as audio or video, or download it as a file.

Differences between ActionDispatch::Response#content_type and ActionDispatch::Response#media_type

We now have a better understanding of the differences between a Content-Type and a MIME type. Let’s compare the values of ActionDispatch::Response#content_type and ActionDispatch::Response#media_type depending on the Rails version.

Rails 5.2

In Rails 5.2, content_type opens a new window returned only the MIME type of the response:

resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present"
resp.media_type #=> "text/csv"

Rails 6.0

In Rails 6.0, content_type opens a new window was changed to have two possible behaviors depending on the return_only_media_type_on_content_type configuration opens a new window .

If the setting is false, which is the default since Rails 6.0, this method returns the unmodified header containing both the MIME type and character set:

# when Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false in config/application.rb
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present; charset=utf-16"
resp.media_type #=> "text/csv; header=present"

Note: the response of media_type also changes, it also returns header=present along with the MIME type.

If return_only_media_type_on_content_type is true, content_type returns only the MIME type, matching the behavior of Rails 5.2. But there’s one important caveat: content_type also triggers a deprecation warning suggesting to use the media_type method which has the old content_type code opens a new window :

# when Rails.application.config.action_dispatch.return_only_media_type_on_content_type = true in config/application.rb
resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type
#DEPRECATION WARNING: Rails 6.1 will return Content-Type header without modification. If you want just the MIME type, please use `#media_type` instead.
#=> "text/csv; header=present"
resp.media_type #=> "text/csv; header=present"

Rails 6.1

In Rails 6.1, the return_only_media_type_on_content_type framework default setting is deprecated opens a new window and has no effect, so content_type opens a new window will always return the full header, thus matching the behavior of 6.0 when the setting is false.

resp = ActionDispatch::Response.new(200, "Content-Type" => "text/csv; header=present; charset=utf-16")
resp.content_type #=> "text/csv; header=present; charset=utf-16"
resp.media_type #=> "text/csv; header=present"

By now, you might be wondering, like I was, why Rails.application.config.action_dispatch.return_only_media_type_on_content_type was introduced as a framework default in 6.0? Why was the deprecation message introduced only then when this change really affects the upgrade from Rails 5.2 to 6.0?

If we look at the Rails 6.0 release notes opens a new window , we do see that ActionDispatch::Response#content_type was changed in that version. Here is the PR opens a new window that introduces the change. Since it was a breaking change, this commit opens a new window in 6.0 was added to restore the old behavior, and added a config to allow users to gradually move to that change before changing the behavior again completely in Rails 6.1.

Fixing this issue is fairly straightforward. Unless you are on Rails 6.0 and have some use case where changing the Rails.application.config.action_dispatch.return_only_media_type_on_content_type is justified, it’s best to replace the uses of content_type with media_type if you want just the MIME type.

Conclusion

In conclusion, the evolution of ActionDispatch::Response#content_type from Rails 5.2 to Rails 6.1 highlights the importance of understanding HTTP headers, Content-Type, and MIME types. This seemingly minor change had a notable impact on how developers interact with response headers.

Interested in getting an action plan to see what other actions will be required to upgrade your Ruby or Rails application? Send us a message! opens a new window

Get the book