-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Do not allow BodyProxy to respond to to_ary or to_str #2062
Conversation
This methods could trigger different behavior in rack that is undesired when using BodyProxy. When using BodyProxy, you always want the caller to iterate through the body using each. See rack/rack-test#335 for an example where allowing BodyProxy to respond to to_str (when provided an invalid rack body) complicated debugging. BodyProxy already had a spec with a description "not respond to :to_ary". While you would assume that this checked whether the body actually responded to to_ary, it did not. This fixes that, making sure that respond_to?(:to_ary) is false, and calling to_ary raises a NoMethodError. It adds a similar spec for to_str.
703ba00
to
413989d
Compare
Why? First of all, I'll divide bodies into four categories: array, enum, call, and file. You feel that
So, a server should be able to optimize delivery if a body is known to be an Array, which should also respond to From what I've seen, the main use for BodyProxy is the callback. I'm not concerned about |
@MSP-Greg The original impetus for this PR was
I did some research, and this PR restores BodyProxy's historical behavior, introduced in 5b251a9. the I'm fine with updating the PR to support |
It seems more compatible and transparent to me. |
Isn't 'closing' the responsibility of the consumer of the In Puma, if we call JFYI, I think current behavior is just fine, as noted below:
|
@MSP-Greg this is what is in the spec:
Calling close a 2nd time shouldn't be an issue but also shouldn't be necessary. |
Call BodyProxy#close if BodyProxy#to_ary is called.
OK, I pushed a commit to support |
Thanks. Sorry, I've read the spec several times, but didn't recall that info. A link would be the spec's Enumerable Body section (sorry, a little promotion). For now, I think Puma should continue to call close. As I recall, there is some Rails response that responds to |
That would definitely be against the spec and I'd suggest emitting a warning. |
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! Thanks for your patience with my questions.
👋 Could we get a release for that? I got someone reporting this on Pitchfork: Shopify/pitchfork#117. This bug can be quite catastrophic (not with modern Rails fortunately I we always assume |
We are planning to discuss Rack 3.1 release at RubyKaigi, will you be there? |
@jeremyevans if this is a bug what about backporting it to 3.0? |
I will yes.
IMO it's a bug, can even be a security vulnerability in some case by causing state leak between requests if the application rely on |
I'm OK with backporting to 3.0. |
Sounds good, I openen #2176 for this |
* Do not allow BodyProxy to respond to to_str, make to_ary call close See rack/rack-test#335 for an example where allowing BodyProxy to respond to to_str (when provided an invalid rack body) complicated debugging. Call BodyProxy#close if BodyProxy#to_ary is called, as not doing so violates SPEC. * Changelog for #2062 --------- Co-authored-by: Jeremy Evans <code@jeremyevans.net>
Thanks for the backport, @Earlopain |
Hey folks, trying to upgrade to 3.0.11 but running into problems when trying to test our middleware that rescues We used to be able to test it like this: post '/endpoint.json', params: '{"malformed: *}}', headers: { 'CONTENT_TYPE' => 'application/json' } and our middleware: class RescueInvalidJson
class MalformedJson < StandardError; end
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
rescue ActionDispatch::Http::Parameters::ParseError => e
error = MalformedJson.new("[FILTERED]")
error.set_backtrace(e.backtrace)
Thingy::Exception.submit(error)
[400, { "Content-Type" => "application/json" }, "Invalid JSON params"]
end
end would allow us to assert the 400 response. This is the error we are getting now though:
Is there a better way now to test a malformed payload or a use case that was overlooked that will need changes for? (Feel free to direct me to an issue if this isn't an appropriate place to reach out) |
Are you able to show us your test app? It looks like it’s returnin a string rather than an array of strings for the body. |
This methods could trigger different behavior in rack that is undesired when using BodyProxy. When using BodyProxy, you always want the caller to iterate through the body using each.
See rack/rack-test#335 for an example where allowing BodyProxy to respond to to_str (when provided an invalid rack body) complicated debugging.
BodyProxy already had a spec with a description "not respond to :to_ary". While you would assume that this checked whether the body actually responded to to_ary, it did not. This fixes that, making sure that respond_to?(:to_ary) is false, and calling to_ary raises a NoMethodError. It adds a similar spec for to_str.