-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Compute Content-Length header correctly when response body is an instance of Rack::BodyProxy #2892
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
Compute Content-Length header correctly when response body is an instance of Rack::BodyProxy #2892
Conversation
dentarg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
@guilleiguaran Thank you for the PR. Question, based of the code in Rack::ContentLength. If the body is an Array (responds to IOW, if body is an Array, we compute the Content-Length. If the body isn't an Array or an IO/File (responds to Thoughts? Making this change would require changing some tests, as many tests assume body arrays are chunked unless they contain one element. Using |
25dacfb to
83c2ac2
Compare
0ce9a53 to
1ab387b
Compare
…Array with single element
100a8ee to
7701664
Compare
|
@MSP-Greg sorry for the delay, I've been working back and forth with multiple implementations of this, the current one handles array bodies with more than one element, Rails' ActionDispatch::Response::RackBody (introduced 8 years ago in 4.2) responds There have been many discussions around how to decide if a body should be considered to have a knowable length or not in both Rack and Rails, see: rails/rails#16793 |
| str_headers(env, status, headers, res_info, lines, requests, client) | ||
|
|
||
| if !res_info[:content_length] && !res_info[:transfer_encoding] && status != 204 | ||
| if res_body.respond_to?(:to_ary) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: this condition can be merged with the previous one
| if res_body.respond_to?(:to_ary) | ||
| if array_body = res_body.to_ary | ||
| res_info[:content_length] = array_body.map(&:bytesize).inject(0, :+) | ||
| elsif res_body.respond_to?(:each) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This to_ary exists but returns nil is for handling objects like Rails' RackBody
No problem. Thanks for all the links. The 'returns I wonder why an app would not set Content-Length if the body had a knowable length. That aside, I wonder if something like the following would get around all the issues? Note, I need a refresh based on your above comments... if (app_body.respond_to?(:to_ary) && (body = app_body.to_ary)) ||
(app_body.is_a?(Array) && app_body.all? { |el| el.is_a? String } && body = app_body)
# compute length from body, use body to write response
end
|
|
Dumb Rails question: Would a normal Rails app ever return a body where |
|
@MSP-Greg no for anything handled through ActionDispatch (e.g Rails controllers), those are always wrapped in For the next version of Rails, I'll work in proper support for Rack 3.0 and Rack::ContentLength (supporting |
Description
Currently, Puma is not setting the Content-Length header when the Rack response body is an instance of Rack::BodyProxy due to the condition that is checking for an Array.
This PR takes an approach similar to Rack::ContentLength that checks if the body responds to
to_aryinstead of checking if the body is an Array.Additionally, I added a sanity check in
test_body_proxyjust to confirm that Puma handles correctly Rack::BodyProxy responses.Your checklist for this pull request
[ci skip]to the title of the PR.#issue" to the PR description or my commit messages.