From 51a9311b2d31c77a70b2acc7c03fcd561184ff0d Mon Sep 17 00:00:00 2001
From: Matthew Draper <matthew@trebex.net>
Date: Tue, 20 Dec 2016 05:01:42 +1030
Subject: Only default the response charset when it is first set

If it is explicitly cleared (e.g., response.sending_file = true), then
we should not try to set it again.
---
 actionpack/lib/action_controller/metal/data_streaming.rb | 6 +++---
 actionpack/lib/action_dispatch/http/response.rb          | 4 +++-
 actionpack/test/controller/send_file_test.rb             | 9 ++++++++-
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index f089c8423b..ec4b5cec5e 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -70,7 +70,6 @@ module ActionController #:nodoc:
         send_file_headers! options
 
         self.status = options[:status] || 200
-        self.content_type = options[:type] if options.key?(:type)
         self.content_type = options[:content_type] if options.key?(:content_type)
         response.send_file path
       end
@@ -113,6 +112,9 @@ module ActionController #:nodoc:
       def send_file_headers!(options)
         type_provided = options.has_key?(:type)
 
+        self.content_type = DEFAULT_SEND_FILE_TYPE
+        response.sending_file = true
+
         content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
         raise ArgumentError, ":type option required" if content_type.nil?
 
@@ -137,8 +139,6 @@ module ActionController #:nodoc:
 
         headers["Content-Transfer-Encoding"] = "binary"
 
-        response.sending_file = true
-
         # Fix a problem with IE 6.0 on opening downloaded files:
         # If Cache-Control: no-cache is set (which Rails does by default),
         # IE removes the file it just downloaded from its cache immediately
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index f71c6afd6c..516a2af69a 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -227,7 +227,9 @@ module ActionDispatch # :nodoc:
       return unless content_type
       new_header_info = parse_content_type(content_type.to_s)
       prev_header_info = parsed_content_type_header
-      set_content_type new_header_info.mime_type, new_header_info.charset || prev_header_info.charset || self.class.default_charset
+      charset = new_header_info.charset || prev_header_info.charset
+      charset ||= self.class.default_charset unless prev_header_info.mime_type
+      set_content_type new_header_info.mime_type, charset
     end
 
     # Sets the HTTP response's content MIME type. For example, in the controller
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index a28283f4d6..9e6b975fe2 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -241,10 +241,17 @@ class SendFileTest < ActionController::TestCase
     assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"]
   end
 
+  def test_send_file_charset_with_type_options_key_without_charset
+    @controller = SendFileWithActionControllerLive.new
+    @controller.options = { type: "image/png" }
+    response = process("file")
+    assert_equal "image/png", response.headers["Content-Type"]
+  end
+
   def test_send_file_charset_with_content_type_options_key
     @controller = SendFileWithActionControllerLive.new
     @controller.options = { content_type: "text/calendar" }
     response = process("file")
-    assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"]
+    assert_equal "text/calendar", response.headers["Content-Type"]
   end
 end
-- 
cgit v1.2.3