Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions api/metrics/client.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this client behavior update in this file? This is only used in e2e tests so I feel like this is over-kill for an environment that is just a smoke test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes a difference either way practically speaking, but I think applying best practices everywhere is better than not, particularly now that we're just uniformly deferring the call to the helper everywhere (which I realize is a change from when this comment was left). Thoughts?

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/url"

Expand Down Expand Up @@ -52,6 +53,10 @@ func (c *Client) GetMetrics(ctx context.Context) (map[string]*dto.MetricFamily,

// Return an error for any non successful status code
if resp.StatusCode < 200 || resp.StatusCode > 299 {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)

// Drop any error during close to report the original error
_ = resp.Body.Close()
return nil, fmt.Errorf("received status code: %d", resp.StatusCode)
Expand All @@ -60,9 +65,17 @@ func (c *Client) GetMetrics(ctx context.Context) (map[string]*dto.MetricFamily,
var parser expfmt.TextParser
metrics, err := parser.TextToMetricFamilies(resp.Body)
if err != nil {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)

// Drop any error during close to report the original error
_ = resp.Body.Close()
return nil, err
}

// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
return metrics, resp.Body.Close()
}
7 changes: 6 additions & 1 deletion tests/fixture/tmpnet/check_monitoring.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment in this diff in this package w.r.t io.ReadAll

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, now that we have the CleanlyCloseBody helper, I think it's most defensive to use it uniformly across the board rather than depending on the fact that the body is always fully read otherwise.

Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,12 @@ func queryLoki(
if err != nil {
return 0, stacktrace.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
defer func() {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}()

// Read and parse response
body, err := io.ReadAll(resp.Body)
Expand Down
7 changes: 6 additions & 1 deletion tests/fixture/tmpnet/monitor_processes.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,12 @@ func checkReadiness(ctx context.Context, url string) (bool, string, error) {
if err != nil {
return false, "", stacktrace.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
defer func() {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}()

body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion tests/fixture/tmpnet/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,12 @@ func (n *Node) SaveMetricsSnapshot(ctx context.Context) error {
if err != nil {
return stacktrace.Wrap(err)
}
defer resp.Body.Close()
defer func() {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
if err != nil {
return stacktrace.Wrap(err)
Expand Down
7 changes: 6 additions & 1 deletion utils/dynamicip/ifconfig_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ func (r *ifConfigResolver) Resolve(ctx context.Context) (netip.Addr, error) {
if err != nil {
return netip.Addr{}, err
}
defer resp.Body.Close()
defer func() {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}()

ipBytes, err := io.ReadAll(resp.Body)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already read until EOF here - do we still need to drain the response body?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have the CleanlyCloseBody helper, I think it's most defensive to use it uniformly across the board rather than depending on the fact that the body is always fully read otherwise.

if err != nil {
Expand Down
13 changes: 13 additions & 0 deletions utils/rpc/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/url"

Expand Down Expand Up @@ -49,15 +50,27 @@ func SendJSONRequest(

// Return an error for any non successful status code
if resp.StatusCode < 200 || resp.StatusCode > 299 {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)

// Drop any error during close to report the original error
_ = resp.Body.Close()
return fmt.Errorf("received status code: %d", resp.StatusCode)
}

if err := rpc.DecodeClientResponse(resp.Body, reply); err != nil {
// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)

// Drop any error during close to report the original error
_ = resp.Body.Close()
return fmt.Errorf("failed to decode client response: %w", err)
}

// Avoid sending unnecessary RST_STREAM and PING frames by ensuring the whole body is read.
// See https://blog.cloudflare.com/go-and-enhance-your-calm/#reading-bodies-in-go-can-be-unintuitive
_, _ = io.Copy(io.Discard, resp.Body)
return resp.Body.Close()
}