Support handling Enumerator for non-buffered responses

The downside to this is that we cannot generate ETags for these types of responses, but are assuming that by using an enumerator they don't expect a buffered response to be cacheable. This means you cannot use Enumerator to generate streaming responses.

Fixes #49588

See also: #47092

Co-authored-by: Samuel Williams <samuel.williams@oriontransfer.co.nz>
This commit is contained in:
zzak 2023-10-13 11:12:16 +09:00
parent ab3b206e58
commit 6635543d51
No known key found for this signature in database
GPG Key ID: 213927DFCF4FF102
2 changed files with 39 additions and 1 deletions

@ -104,7 +104,9 @@ def initialize(response, buf)
end
def to_ary
@buf.to_ary
@buf.respond_to?(:to_ary) ?
@buf.to_ary :
@buf.each
end
def body

@ -617,4 +617,40 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest
assert_equal("text/csv; header=present", @response.media_type)
assert_equal("utf-16", @response.charset)
end
test "response body with enumerator" do
@app = lambda { |env|
[
200,
{ "Content-Type" => "text/plain" },
Enumerator.new { |enumerator| 10.times { |n| enumerator << n.to_s } }
]
}
get "/"
assert_response :success
assert_equal("text/plain", @response.headers["Content-Type"])
assert_equal("text/plain", @response.content_type)
assert_equal("text/plain", @response.media_type)
assert_equal("utf-8", @response.charset)
assert_equal("0123456789", @response.body)
end
test "response body with lazy enumerator" do
@app = lambda { |env|
[
200,
{ "Content-Type" => "text/plain" },
(0..10).lazy
]
}
get "/"
assert_response :success
assert_equal("text/plain", @response.headers["Content-Type"])
assert_equal("text/plain", @response.content_type)
assert_equal("text/plain", @response.media_type)
assert_equal("utf-8", @response.charset)
assert_equal("012345678910", @response.body)
end
end