Skip to content

Commit 7b46a68

Browse files
rpc: Avoid unnecessary RST_STREAM and PING frames causing GOAWAYs
1 parent 982235f commit 7b46a68

File tree

10 files changed

+30
-16
lines changed

10 files changed

+30
-16
lines changed

beacon/light/api/light_api.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/ethereum/go-ethereum/common"
3636
"github.com/ethereum/go-ethereum/common/hexutil"
3737
"github.com/ethereum/go-ethereum/log"
38+
"github.com/ethereum/go-ethereum/rpc"
3839
)
3940

4041
var (
@@ -137,7 +138,7 @@ func (api *BeaconLightApi) httpGet(path string, params url.Values) ([]byte, erro
137138
if err != nil {
138139
return nil, err
139140
}
140-
defer resp.Body.Close()
141+
defer rpc.CleanlyCloseBody(resp.Body)
141142
switch resp.StatusCode {
142143
case 200:
143144
return io.ReadAll(resp.Body)

cmd/geth/version_check.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"strings"
2828

2929
"github.com/ethereum/go-ethereum/log"
30+
"github.com/ethereum/go-ethereum/rpc"
3031
"github.com/jedisct1/go-minisign"
3132
"github.com/urfave/cli/v2"
3233
)
@@ -119,7 +120,7 @@ func fetch(url string) ([]byte, error) {
119120
if err != nil {
120121
return nil, err
121122
}
122-
defer res.Body.Close()
123+
defer rpc.CleanlyCloseBody(res.Body)
123124
body, err := io.ReadAll(res.Body)
124125
if err != nil {
125126
return nil, err

graphql/graphql_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"github.com/ethereum/go-ethereum/eth/filters"
4141
"github.com/ethereum/go-ethereum/node"
4242
"github.com/ethereum/go-ethereum/params"
43+
"github.com/ethereum/go-ethereum/rpc"
4344

4445
"github.com/stretchr/testify/assert"
4546
)
@@ -159,7 +160,7 @@ func TestGraphQLBlockSerialization(t *testing.T) {
159160
t.Fatalf("could not post: %v", err)
160161
}
161162
bodyBytes, err := io.ReadAll(resp.Body)
162-
resp.Body.Close()
163+
rpc.CleanlyCloseBody(resp.Body)
163164
if err != nil {
164165
t.Fatalf("could not read from response body: %v", err)
165166
}
@@ -246,7 +247,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
246247
t.Fatalf("could not post: %v", err)
247248
}
248249
bodyBytes, err := io.ReadAll(resp.Body)
249-
resp.Body.Close()
250+
rpc.CleanlyCloseBody(resp.Body)
250251
if err != nil {
251252
t.Fatalf("could not read from response body: %v", err)
252253
}
@@ -271,7 +272,7 @@ func TestGraphQLHTTPOnSamePort_GQLRequest_Unsuccessful(t *testing.T) {
271272
if err != nil {
272273
t.Fatalf("could not post: %v", err)
273274
}
274-
resp.Body.Close()
275+
rpc.CleanlyCloseBody(resp.Body)
275276
// make sure the request is not handled successfully
276277
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
277278
}

internal/download/download.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
"os"
3131
"path/filepath"
3232
"strings"
33+
34+
"github.com/ethereum/go-ethereum/rpc"
3335
)
3436

3537
// ChecksumDB keeps file checksums and tool versions.
@@ -191,7 +193,7 @@ func (db *ChecksumDB) DownloadFile(url, dstPath string) error {
191193
if err != nil {
192194
return fmt.Errorf("download error: %v", err)
193195
}
194-
defer resp.Body.Close()
196+
defer rpc.CleanlyCloseBody(resp.Body)
195197
if resp.StatusCode != http.StatusOK {
196198
return fmt.Errorf("download error: status %d", resp.StatusCode)
197199
}

metrics/influxdb/influxdb_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

3030
"github.com/ethereum/go-ethereum/metrics"
3131
"github.com/ethereum/go-ethereum/metrics/internal"
32+
"github.com/ethereum/go-ethereum/rpc"
3233
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
3334
)
3435

@@ -47,7 +48,7 @@ func TestExampleV1(t *testing.T) {
4748
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
4849
haveB, _ := io.ReadAll(r.Body)
4950
have = string(haveB)
50-
r.Body.Close()
51+
rpc.CleanlyCloseBody(r.Body)
5152
}))
5253
defer ts.Close()
5354
u, _ := url.Parse(ts.URL)
@@ -83,7 +84,7 @@ func TestExampleV2(t *testing.T) {
8384
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
8485
haveB, _ := io.ReadAll(r.Body)
8586
have = string(haveB)
86-
r.Body.Close()
87+
rpc.CleanlyCloseBody(r.Body)
8788
}))
8889
defer ts.Close()
8990

node/api_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ func checkBodyOK(url string) bool {
318318
if err != nil {
319319
return false
320320
}
321-
defer resp.Body.Close()
321+
rpc.CleanlyCloseBody(resp.Body)
322322

323323
if resp.StatusCode != 200 {
324324
return false

node/node_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ func doHTTPRequest(t *testing.T, req *http.Request) *http.Response {
600600
if err != nil {
601601
t.Fatalf("could not issue a GET request to the given endpoint: %v", err)
602602
}
603-
t.Cleanup(func() { resp.Body.Close() })
603+
t.Cleanup(func() { rpc.CleanlyCloseBody(resp.Body) })
604604
return resp
605605
}
606606

node/rpcstack_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ func baseRpcRequest(t *testing.T, url, bodyStr string, extraHeaders ...string) *
320320
if err != nil {
321321
t.Fatal(err)
322322
}
323-
t.Cleanup(func() { resp.Body.Close() })
323+
t.Cleanup(func() { rpc.CleanlyCloseBody(resp.Body) })
324324
return resp
325325
}
326326

@@ -530,7 +530,7 @@ func TestGzipHandler(t *testing.T) {
530530
if err != nil {
531531
t.Fatal(err)
532532
}
533-
defer resp.Body.Close()
533+
defer rpc.CleanlyCloseBody(resp.Body)
534534

535535
content, err := io.ReadAll(resp.Body)
536536
if err != nil {

rpc/http.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,21 @@ func newClientTransportHTTP(endpoint string, cfg *clientConfig) reconnectFunc {
168168
}
169169
}
170170

171+
// CleanlyCloseBody avoids sending unnecessary RST_STREAM and PING frames by ensuring
172+
// the whole body is read before being closed.
173+
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
174+
func CleanlyCloseBody(body io.ReadCloser) error {
175+
io.Copy(io.Discard, body)
176+
return body.Close()
177+
}
178+
171179
func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error {
172180
hc := c.writeConn.(*httpConn)
173181
respBody, err := hc.doRequest(ctx, msg)
174182
if err != nil {
175183
return err
176184
}
177-
defer respBody.Close()
185+
defer CleanlyCloseBody(respBody)
178186

179187
var resp jsonrpcMessage
180188
batch := [1]*jsonrpcMessage{&resp}
@@ -191,7 +199,7 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr
191199
if err != nil {
192200
return err
193201
}
194-
defer respBody.Close()
202+
defer CleanlyCloseBody(respBody)
195203

196204
var respmsgs []*jsonrpcMessage
197205
if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
@@ -236,7 +244,7 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos
236244
if _, err := buf.ReadFrom(resp.Body); err == nil {
237245
body = buf.Bytes()
238246
}
239-
resp.Body.Close()
247+
CleanlyCloseBody(resp.Body)
240248
return nil, HTTPError{
241249
Status: resp.Status,
242250
StatusCode: resp.StatusCode,

rpc/http_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func confirmHTTPRequestYieldsStatusCode(t *testing.T, method, contentType, body
106106
if err != nil {
107107
t.Fatalf("request failed: %v", err)
108108
}
109-
resp.Body.Close()
109+
CleanlyCloseBody(resp.Body)
110110
confirmStatusCode(t, resp.StatusCode, expectedStatusCode)
111111
}
112112

0 commit comments

Comments
 (0)