request.rb - fix partial hijack precedence, refactor, add tests #3072
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This is a refactor of request.rb. I tried to make separate commits for each change, so it may be easier to follow. Commits:
request.rb - set content_length earlier -
Request#prepare_response
has quite a bit of code that looks at the body returned by the app, and swaps it for another object that is passed toRequest#fast_write_response
. It also may calculate the content_length. There were several places whereresp_info[:content_length]
was used. Movecontent_length = resp_info[:content_length]
to before all the code, so the code usescontent_length
instead of a hash value.request.rb - only compute content_length if res_body.respond_to? :each - The code mentioned above in
Request#prepare_response
usesres_body.respond_to?(:each)
in several places, but all of it can be guarded withif res_body.respond_to? :each
. This commit simply takes the whole outer most conditional, indents it, and adds anif res_body.respond_to? :each
conditional.Move response_hijack code into else clause - given the above, add an
else
clause and move the partial hijack related code that setsresponse_hijack
into it.Sprockets::Asset's @source is always a string - turn it into an array with a single value.
Fewer socket write with Enum chunked body - Socket writes take longer than string operations, so use the
IOBuffer
. Also, I believe some Rails responses are an Enum body with one iteration. This combines the first iteration with the headers.Add hijack comments - add comments clarifying things, partial, full, etc.
I believe this code doesn't change any behavior, except for one item. The following is current code:
Note that the resp_body is used if certain conditions are true. The Rack spec states "Servers must ignore the body part of the response tuple when the rack.hijack response header is present". The above code doesn't set the priority to
resp_info[:response_hijack]
. So, a small bug, fixed in this PR...Added another commit Rearrange partial hijack tests, add full hijack test - this commit adds a 'full hijack' test, which I couldn't find. It also adds a test
TestPumaServerHijack#test_partial_hijack_header_closes_body_correct_precedence
. This test fails in master, as it catches the bug mentioned above.Also, Issue #2999 mentioned an issue with 'full hijack' not closing bodies. The tests added at the time tested 'partial hijack' body closure, not 'full hijack'. Updated tests so both full and partial hijack body closure is tested.
Your checklist for this pull request
[ci skip]
to the title of the PR.#issue
" to the PR description or my commit messages.