-
Notifications
You must be signed in to change notification settings - Fork 321
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
HTTP::Client overwrites body if it isn't read before another request is performed #371
Comments
An empty string is definitely unexpected and undesirable in this case, however I don't think it makes sense to eagerly read bodies clients aren't interested in. I think it would make sense to raise an exception in this case. |
@tarcieri Ok so the issue in my case was that we have an integration test like this: # creating the resource
response1 = client.post(...)
# getting the resource
response2 = client.get(response1.headers['Content-Location'])
expect(response1.body.to_s).to eql(response2.body.to_s) Are you saying that this shouldn't be allowed behavior or should raise an exception? |
I think if you make a request, do not consume the body, make another request with the same client, and then try to consume the body for the original request, it should raise an exception. If you would like to consume the body for the original request, it should happen before you make a subsequent request, IMO. Otherwise the client needs to both consume and hang onto any response bodies simply because you might consume them at some point in the future. Users uninterested in the response bodies would probably file a bug for that, calling it a "memory leak", and I would agree with them. |
@tarcieri I think that sounds surprising to me because my impression of HTTP.rb was that it aimed to provide an immutable and chainable interface for performing requests. While I agree that raising an error would be better than what I've reported it seems like a bandaid. My impression was that the chaining methods were providing me new instances without shared mutable state. Basically, just like how these two return values ( client = HTTP.accept('application/blah')
ret1 = client.accept("application/json")
ret2 = client.basic_auth(user: 'foo', password: 'bar') it seems like these two return values should not be allowed to mutate each other: client = HTTP.accept('application/blah')
ret1 = client.get("https://google.com")
ret2 = client.get("https://github.com") The usage of either of these two response objects should not alter the behavior/state of the other. |
At the very least it would be nice if I could have something like |
Calling Yes, I will admit this behavior is a little bit surprising even to me. |
there's helper for that too: client = HTTP.accept('application/blah')
ret1 = client.get("https://google.com").flush
ret2 = client.get("https://github.com").flush
ret1.to_s[0..42]
# => "<HTML><HEAD><meta http-equiv=\"content-type\""
ret2.to_s[0..42]
# => " " |
|
Would it introduce performance implications and/or breaking changes if each response object had a separate connection object? |
Also thank you @ixti that is helpful |
It will be (probably) a breaking change. And yeah, I guess it will make it easier to shoot the foot for one. But in general I think it's pretty doable and might become a pretty good improvement. |
I think holding on to the last pending response in The connection already tracks if a response is pending (i.e. the body is not read yet) and has enough information to release its reference to the response to avoid a memory leak ( If |
If I use
HTTP
to perform two requests in a row and I don't doresponse.body.to_s
on the first then the body string for the first response will be overwritten with""
.Here is a script that demonstrates the bug:
Output when I run the script:
The text was updated successfully, but these errors were encountered: