mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
rpc: avoid unnecessary RST_STREAM, PING frames sent by client (#33122)
Context from Cloudflare blog: https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive We were able to reproduce the same issue discussed by Cloudflare in their recent blog post above using the `ethclient`.
This commit is contained in:
parent
7368b34a4b
commit
d8f9801305
2 changed files with 12 additions and 4 deletions
14
rpc/http.go
14
rpc/http.go
|
|
@ -168,13 +168,21 @@ func newClientTransportHTTP(endpoint string, cfg *clientConfig) reconnectFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// cleanlyCloseBody avoids sending unnecessary RST_STREAM and PING frames by
|
||||
// ensuring the whole body is read before being closed.
|
||||
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
|
||||
func cleanlyCloseBody(body io.ReadCloser) error {
|
||||
io.Copy(io.Discard, body)
|
||||
return body.Close()
|
||||
}
|
||||
|
||||
func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error {
|
||||
hc := c.writeConn.(*httpConn)
|
||||
respBody, err := hc.doRequest(ctx, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer respBody.Close()
|
||||
defer cleanlyCloseBody(respBody)
|
||||
|
||||
var resp jsonrpcMessage
|
||||
batch := [1]*jsonrpcMessage{&resp}
|
||||
|
|
@ -191,7 +199,7 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer respBody.Close()
|
||||
defer cleanlyCloseBody(respBody)
|
||||
|
||||
var respmsgs []*jsonrpcMessage
|
||||
if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
|
||||
|
|
@ -236,7 +244,7 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos
|
|||
if _, err := buf.ReadFrom(resp.Body); err == nil {
|
||||
body = buf.Bytes()
|
||||
}
|
||||
resp.Body.Close()
|
||||
cleanlyCloseBody(resp.Body)
|
||||
return nil, HTTPError{
|
||||
Status: resp.Status,
|
||||
StatusCode: resp.StatusCode,
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func confirmHTTPRequestYieldsStatusCode(t *testing.T, method, contentType, body
|
|||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
cleanlyCloseBody(resp.Body)
|
||||
confirmStatusCode(t, resp.StatusCode, expectedStatusCode)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue