diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 30ade14c266903146dae2bf9f26b4589381c2d38..842dfa5827a89e0c8d85a9edaebcb96751b5fb2c 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -91,7 +91,7 @@ def etag?; etag; end DATE = 'Date'.freeze LAST_MODIFIED = "Last-Modified".freeze - SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public must-revalidate]) + SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate]) def cache_control_segments if cache_control = _cache_control diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 9b11111a6780ae6d6ed4f7e8ea60a459986d9127..b426d272f23a98bc87056ae9f8b8ad200d5fc87e 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -412,6 +412,13 @@ def before_committed end def before_sending + # Normally we've already committed by now, but it's possible + # (e.g., if the controller action tries to read back its own + # response) to get here before that. In that case, we must force + # an "early" commit: we're about to freeze the headers, so this is + # our last chance. + commit! unless committed? + headers.freeze request.commit_cookie_jar! unless committed? end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index c37679bc5f3a181f046cf19195f37e0e4f494248..43ee2efd9f762471936af281e8d99aceb5c7c878 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -37,6 +37,27 @@ def test_write_after_close assert_equal "closed stream", e.message end + def test_read_body_during_action + @response.body = "Hello, World!" + + # even though there's no explicitly set content-type, + assert_equal nil, @response.content_type + + # after the action reads back @response.body, + assert_equal "Hello, World!", @response.body + + # the response can be built. + status, headers, body = @response.to_a + assert_equal 200, status + assert_equal({ + "Content-Type" => "text/html; charset=utf-8" + }, headers) + + parts = [] + body.each { |part| parts << part } + assert_equal ["Hello, World!"], parts + end + def test_response_body_encoding body = ["hello".encode(Encoding::UTF_8)] response = ActionDispatch::Response.new 200, {}, body