Skip to content

Commit 1e0ff2b

Browse files
committed
Add fail_if_body_too_large http probe option
This can be used in conjunction with `body_size_limit` when it is expected that endpoints return a body larger than the specified limit, e.g. streaming endpoints that potentially return infinite data. Signed-off-by: Justin Kromlinger <[email protected]>
1 parent 3dd5dfe commit 1e0ff2b

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

CONFIGURATION.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ modules:
8989
# Probe fails if SSL is not present.
9090
[ fail_if_not_ssl: <boolean> | default = false ]
9191

92+
# Probe fails if a defined body_size_limit is exceeded.
93+
[ fail_if_body_too_large: <boolean> | default = true ]
94+
9295
# Probe fails if response body matches regex.
9396
fail_if_body_matches_regexp:
9497
[ - <regex>, ... ]

config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ type HTTPProbe struct {
212212
NoFollowRedirects *bool `yaml:"no_follow_redirects,omitempty"`
213213
FailIfSSL bool `yaml:"fail_if_ssl,omitempty"`
214214
FailIfNotSSL bool `yaml:"fail_if_not_ssl,omitempty"`
215+
FailIfBodyTooLarge *bool `yaml:"fail_if_body_too_large,omitempty"`
215216
Method string `yaml:"method,omitempty"`
216217
Headers map[string]string `yaml:"headers,omitempty"`
217218
FailIfBodyMatchesRegexp []Regexp `yaml:"fail_if_body_matches_regexp,omitempty"`
@@ -450,6 +451,13 @@ func (s *HeaderMatch) UnmarshalYAML(unmarshal func(interface{}) error) error {
450451
return nil
451452
}
452453

454+
func (h HTTPProbe) GetFailIfBodyTooLarge() bool {
455+
if h.FailIfBodyTooLarge == nil {
456+
return true
457+
}
458+
return *h.FailIfBodyTooLarge
459+
}
460+
453461
// isCompressionAcceptEncodingValid validates the compression +
454462
// Accept-Encoding combination.
455463
//

prober/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr
550550

551551
if !requestErrored {
552552
_, err = io.Copy(io.Discard, byteCounter)
553-
if err != nil {
553+
if err != nil && (errors.Is(err, &http.MaxBytesError{}) || httpConfig.GetFailIfBodyTooLarge()) {
554554
level.Info(logger).Log("msg", "Failed to read HTTP response body", "err", err)
555555
success = false
556556
}

prober/http_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"testing"
3535
"time"
3636

37+
"github.com/alecthomas/units"
3738
"github.com/andybalholm/brotli"
3839
"github.com/go-kit/log"
3940
"github.com/prometheus/client_golang/prometheus"
@@ -837,6 +838,32 @@ func TestFailIfNotSSL(t *testing.T) {
837838
checkRegistryResults(expectedResults, mfs, t)
838839
}
839840

841+
func TestFailIfBodySizeTooLarge(t *testing.T) {
842+
bodySizeLimit := units.Base2Bytes(1)
843+
844+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
845+
resp := bytes.Repeat([]byte{'A'}, int(bodySizeLimit)+1)
846+
847+
w.Header().Set("Content-Length", strconv.Itoa(len(resp)))
848+
w.WriteHeader(http.StatusOK)
849+
w.Write(resp)
850+
}))
851+
defer ts.Close()
852+
853+
for _, failIfBodyTooLarge := range []bool{true, false} {
854+
registry := prometheus.NewRegistry()
855+
testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
856+
defer cancel()
857+
result := ProbeHTTP(testCTX, ts.URL,
858+
config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, BodySizeLimit: bodySizeLimit, FailIfBodyTooLarge: &failIfBodyTooLarge}}, registry, log.NewNopLogger())
859+
if result && failIfBodyTooLarge {
860+
t.Fatal("Fail if body size too large succeeded unexpectedly")
861+
} else if !result && !failIfBodyTooLarge {
862+
t.Fatal("Dont't fail if body too large failed unexpectedly")
863+
}
864+
}
865+
}
866+
840867
type logRecorder struct {
841868
msgs map[string]bool
842869
}

0 commit comments

Comments
 (0)