Skip to content

Commit

Permalink
Add HasRetryAfter helper
Browse files Browse the repository at this point in the history
  • Loading branch information
deankarn committed Mar 25, 2024
1 parent adf96d9 commit 6e8b778
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `errorsext.Retrier` configurable retry helper for any fallible operation.
- `httpext.Retrier` configurable retry helper for HTTP requests and parsing of responses.
- `DecodeResponseAny` non-generic helper for decoding HTTP responses.
- `HasRetryAfter` helper for checking if a response has a `Retry-After` header and returning duration to wait.

## [5.28.1] - 2024-02-14
### Fixed
Expand Down
24 changes: 23 additions & 1 deletion net/http/helpers_go1.18.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ package httpext

import (
"errors"
bytesext "github.com/go-playground/pkg/v5/bytes"
"net/http"
"strconv"
"strings"
"time"

asciiext "github.com/go-playground/pkg/v5/ascii"
bytesext "github.com/go-playground/pkg/v5/bytes"
. "github.com/go-playground/pkg/v5/values/option"
)

// DecodeResponse takes the response and attempts to discover its content type via
Expand All @@ -30,3 +35,20 @@ func DecodeResponse[T any](r *http.Response, maxMemory bytesext.Bytes) (result T
}
return
}

// HasRetryAfter parses the Retry-After header and returns the duration if possible.
func HasRetryAfter(headers http.Header) Option[time.Duration] {
if ra := headers.Get(RetryAfter); ra != "" {
if asciiext.IsDigit(ra[0]) {
if n, err := strconv.ParseInt(ra, 10, 64); err == nil {
return Some(time.Duration(n) * time.Second)
}
} else {
// not a number so must be a date in the future
if t, err := http.ParseTime(ra); err == nil {
return Some(time.Until(t))
}
}
}
return None[time.Duration]()
}
14 changes: 2 additions & 12 deletions net/http/retrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"strconv"
"time"

asciiext "github.com/go-playground/pkg/v5/ascii"
bytesext "github.com/go-playground/pkg/v5/bytes"
errorsext "github.com/go-playground/pkg/v5/errors"
typesext "github.com/go-playground/pkg/v5/types"
Expand Down Expand Up @@ -111,17 +110,8 @@ func NewRetryer() Retryer {

var sce ErrStatusCode
if (sce.StatusCode == http.StatusTooManyRequests || sce.StatusCode == http.StatusServiceUnavailable) && errors.As(err, &sce) && sce.Headers != nil {
if ra := sce.Headers.Get(RetryAfter); ra != "" {
if asciiext.IsDigit(ra[0]) {
if n, err := strconv.ParseInt(ra, 10, 64); err == nil {
wait = time.Duration(n) * time.Second
}
} else {
// not a number so must be a date in the future
if t, err := http.ParseTime(ra); err == nil {
wait = time.Until(t)
}
}
if ra := HasRetryAfter(sce.Headers); ra.IsSome() {
wait = ra.Unwrap()
}
}

Expand Down

0 comments on commit 6e8b778

Please sign in to comment.