R3: gateway edge hardening — body cap, h2c sizing, rate-limit observability
- GATEWAY_MAX_BODY_BYTES (1 MiB): connect WithReadMaxBytes + http.MaxBytesReader
on the public mux; explicit http2.Server MaxConcurrentStreams/IdleTimeout and
an http.Server ReadHeaderTimeout (R2 report follow-up).
- gateway_rate_limited_total{class} counter, Debug per rejection, a rejection
tracker drained every 30 s into a Warn summary per key and a report POST to
/api/v1/internal/ratelimit/report (feeds the admin view + auto-flag).
- The dead AdminPerMinute/AdminBurst policy now guards the /_gm mount (429),
ahead of its Basic-Auth.
- resolve() logs the cause of infra session-resolve failures at Warn (the
transient unauthenticated dips from the R2 run); unknown tokens stay silent.
This commit is contained in:
@@ -29,3 +29,19 @@ func TestLoadRejectsUnsupportedExporter(t *testing.T) {
|
||||
t.Fatal("Load: expected an error for an unsupported exporter, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadMaxBodyBytes verifies the body-cap default and that a non-positive
|
||||
// override fails validation.
|
||||
func TestLoadMaxBodyBytes(t *testing.T) {
|
||||
c, err := Load()
|
||||
if err != nil {
|
||||
t.Fatalf("Load: %v", err)
|
||||
}
|
||||
if c.MaxBodyBytes != DefaultMaxBodyBytes {
|
||||
t.Errorf("MaxBodyBytes = %d, want %d", c.MaxBodyBytes, DefaultMaxBodyBytes)
|
||||
}
|
||||
t.Setenv("GATEWAY_MAX_BODY_BYTES", "0")
|
||||
if _, err := Load(); err == nil {
|
||||
t.Fatal("Load: expected an error for a non-positive body cap, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user