Skip to content

Commit

Permalink
Merge pull request #26317 from maclover7/jm-fix-26298
Browse files Browse the repository at this point in the history
Allow `send_file` to declare a charset
  • Loading branch information
tenderlove committed Aug 29, 2016
2 parents 3fc414a + 92f8b99 commit 6949f8e
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 8 deletions.
1 change: 1 addition & 0 deletions actionpack/lib/action_controller/metal/data_streaming.rb
Expand Up @@ -70,6 +70,7 @@ def send_file(path, options = {}) #:doc:
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
Expand Down
23 changes: 15 additions & 8 deletions actionpack/lib/action_dispatch/http/response.rb
Expand Up @@ -224,8 +224,10 @@ def status=(status)

# Sets the HTTP content type.
def content_type=(content_type)
header_info = parse_content_type
set_content_type content_type.to_s, header_info.charset || self.class.default_charset
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
end

# Sets the HTTP response's content MIME type. For example, in the controller
Expand All @@ -238,7 +240,7 @@ def content_type=(content_type)
# information.

def content_type
parse_content_type.mime_type
parsed_content_type_header.mime_type
end

def sending_file=(v)
Expand All @@ -253,7 +255,7 @@ def sending_file=(v)
# response.charset = 'utf-16' # => 'utf-16'
# response.charset = nil # => 'utf-8'
def charset=(charset)
header_info = parse_content_type
header_info = parsed_content_type_header
if false == charset
set_header CONTENT_TYPE, header_info.mime_type
else
Expand All @@ -265,7 +267,7 @@ def charset=(charset)
# The charset of the response. HTML wants to know the encoding of the
# content you're giving them, so we need to send that along.
def charset
header_info = parse_content_type
header_info = parsed_content_type_header
header_info.charset || self.class.default_charset
end

Expand Down Expand Up @@ -403,8 +405,7 @@ def cookies
ContentTypeHeader = Struct.new :mime_type, :charset
NullContentTypeHeader = ContentTypeHeader.new nil, nil

def parse_content_type
content_type = get_header CONTENT_TYPE
def parse_content_type(content_type)
if content_type
type, charset = content_type.split(/;\s*charset=/)
type = nil if type.empty?
Expand All @@ -414,6 +415,12 @@ def parse_content_type
end
end

# Small internal convenience method to get the parsed version of the current
# content type header.
def parsed_content_type_header
parse_content_type(get_header(CONTENT_TYPE))
end

def set_content_type(content_type, charset)
type = (content_type || "").dup
type << "; charset=#{charset}" if charset
Expand Down Expand Up @@ -450,7 +457,7 @@ def munge_body_object(body)
def assign_default_content_type_and_charset!
return if content_type

ct = parse_content_type
ct = parsed_content_type_header
set_content_type(ct.mime_type || Mime[:html].to_s,
ct.charset || self.class.default_charset)
end
Expand Down
14 changes: 14 additions & 0 deletions actionpack/test/controller/send_file_test.rb
Expand Up @@ -233,4 +233,18 @@ def test_send_file_with_action_controller_live
response = process("file")
assert_equal 200, response.status
end

def test_send_file_charset_with_type_options_key
@controller = SendFileWithActionControllerLive.new
@controller.options = { type: "text/calendar; charset=utf-8" }
response = process("file")
assert_equal "text/calendar; charset=utf-8", 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"]
end
end

0 comments on commit 6949f8e

Please sign in to comment.