package alert_lifecycle import ( "bytes" "errors" "io" "net/http" "strings" "github.com/gin-gonic/gin" ) const maxCloseRequestBytes = 8 * 1024 const closeBodyKey = "bell.lifecycle.close-body" const closeBodyErrorKey = "bell.lifecycle.close-body-error" func RedactRequestBody() gin.HandlerFunc { return func(c *gin.Context) { if c.Request.Method != http.MethodPost || !strings.HasPrefix(c.Request.URL.Path, "/api/v1/bell/alerts/") || !strings.HasSuffix(c.Request.URL.Path, "/close") { c.Next() return } body, err := io.ReadAll(io.LimitReader(c.Request.Body, maxCloseRequestBytes+1)) if err != nil { c.Set(closeBodyErrorKey, err) } else if len(body) > maxCloseRequestBytes { c.Set(closeBodyErrorKey, errors.New("request body too large")) } else { c.Set(closeBodyKey, body) } _ = c.Request.Body.Close() c.Request.Body = io.NopCloser(bytes.NewReader([]byte(`{"redacted":true}`))) c.Next() } } func restoreCloseBody(c *gin.Context) error { if value, ok := c.Get(closeBodyErrorKey); ok { return value.(error) } value, ok := c.Get(closeBodyKey) if !ok { return errors.New("close request body was not captured") } c.Request.Body = io.NopCloser(bytes.NewReader(value.([]byte))) return nil }