diff --git a/notify/util.go b/notify/util.go index fe4c9ea508..305fa23563 100644 --- a/notify/util.go +++ b/notify/util.go @@ -23,7 +23,9 @@ import ( "net/http" "net/url" "slices" + "strconv" "strings" + "time" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/version" @@ -239,6 +241,28 @@ type Retrier struct { RetryCodes []int } +// ParseRetryAfter parses the Retry-After header value, which can be either +// a delay in seconds (integer) or an HTTP-date. Returns zero if absent or unparseable. +func ParseRetryAfter(h http.Header) time.Duration { + val := h.Get("Retry-After") + if val == "" { + return 0 + } + // Try integer seconds first. + if secs, err := strconv.Atoi(val); err == nil { + return time.Duration(secs) * time.Second + } + // Try HTTP-date format. + if t, err := http.ParseTime(val); err == nil { + d := time.Until(t) + if d < 0 { + return 0 + } + return d + } + return 0 +} + // Check returns a boolean indicating whether the request should be retried // and an optional error if the request has failed. If body is not nil, it will // be included in the error message.