-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
[Heartbeat] Read entire body before closing connection #8660
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,6 @@ func (t *SimpleTransport) RoundTrip(req *http.Request) (*http.Response, error) { | |
if err != nil { | ||
return nil, err | ||
} | ||
defer conn.Close() | ||
|
||
requestedGzip := false | ||
if t.DisableCompression && | ||
|
@@ -147,13 +146,30 @@ func (t *SimpleTransport) writeRequest(conn net.Conn, req *http.Request) error { | |
return err | ||
} | ||
|
||
// comboConnReadCloser wraps a ReadCloser that is backed by | ||
// on a net.Conn. It will close the net.Conn when the ReadCloser is closed. | ||
type comboConnReadCloser struct { | ||
conn net.Conn | ||
rc io.ReadCloser | ||
} | ||
|
||
func (c comboConnReadCloser) Read(p []byte) (n int, err error) { | ||
return c.rc.Read(p) | ||
} | ||
|
||
func (c comboConnReadCloser) Close() error { | ||
defer c.conn.Close() | ||
return c.rc.Close() | ||
} | ||
|
||
func (t *SimpleTransport) readResponse( | ||
conn net.Conn, | ||
req *http.Request, | ||
requestedGzip bool, | ||
) (*http.Response, error) { | ||
reader := bufio.NewReader(conn) | ||
resp, err := http.ReadResponse(reader, req) | ||
resp.Body = comboConnReadCloser{conn, resp.Body} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When exactly is the Body now closed? I see below that the body is closed on error, but what about the standard case? If I understand it right the connection is closed as soon as the body is closed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Body MUST always be closed once processing has finished. From http docs:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, @urso has it right. It's up to the user of the HTTP client to always close the body. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To add some clarity, it's a bit weird in terms of design. You'd think that you would call Normally the connection lifecycle is decoupled from the body lifecycle to enable things like keepalive and connection pooling. In our case we want them 100% coupled, so we have this awkward dance we do with the combination closer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When exactly is the Body now closed? I see below that the body is closed on error, but what about the standard case? If I understand it right the connection is closed as soon as the body is closed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above comment. |
||
if err != nil { | ||
return nil, err | ||
} | ||
|
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.
exported function LargeResponseHandler should have comment or be unexported