Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix content-type header with send_stream #46327

Merged
merged 1 commit into from Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/metal/live.rb
Expand Up @@ -321,7 +321,7 @@ def response_body=(body)
def send_stream(filename:, disposition: "attachment", type: nil)
response.headers["Content-Type"] =
(type.is_a?(Symbol) ? Mime[type].to_s : type) ||
Mime::Type.lookup_by_extension(File.extname(filename).downcase.delete(".")) ||
Mime::Type.lookup_by_extension(File.extname(filename).downcase.delete("."))&.to_s ||
"application/octet-stream"

response.headers["Content-Disposition"] =
Expand Down
51 changes: 51 additions & 0 deletions actionpack/test/controller/live_stream_test.rb
Expand Up @@ -168,6 +168,27 @@ def send_stream_with_options
end
end

def send_stream_with_inferred_content_type
send_stream(filename: "sample.csv") do |stream|
stream.writeln "fruit,quantity"
stream.writeln "apple,5"
end
end

def send_stream_with_implicit_content_type
send_stream(filename: "sample.csv", type: :csv) do |stream|
stream.writeln "fruit,quantity"
stream.writeln "apple,5"
end
end

def send_stream_with_explicit_content_type
send_stream(filename: "sample.csv", type: "text/csv") do |stream|
stream.writeln "fruit,quantity"
stream.writeln "apple,5"
end
end

def blocking_stream
response.headers["Content-Type"] = "text/event-stream"
%w{ hello world }.each do |word|
Expand Down Expand Up @@ -360,6 +381,36 @@ def test_send_stream_with_options
assert_match "export", @response.headers["Content-Disposition"]
end

def test_send_stream_with_explicit_content_type
get :send_stream_with_explicit_content_type

assert_equal "fruit,quantity\napple,5\n", @response.body

content_type = @response.headers.fetch("Content-Type")
assert_equal String, content_type.class
assert_equal "text/csv", content_type
end

def test_send_stream_with_implicit_content_type
get :send_stream_with_implicit_content_type

assert_equal "fruit,quantity\napple,5\n", @response.body

content_type = @response.headers.fetch("Content-Type")
assert_equal String, content_type.class
assert_equal "text/csv", content_type
end

def test_send_stream_with_inferred_content_type
get :send_stream_with_inferred_content_type

assert_equal "fruit,quantity\napple,5\n", @response.body

content_type = @response.headers.fetch("Content-Type")
assert_equal String, content_type.class
assert_equal "text/csv", content_type
end

def test_delayed_autoload_after_write_within_interlock_hook
# Simulate InterlockHook
ActiveSupport::Dependencies.interlock.start_running
Expand Down