More idiomatic naming for the rate limit handling

This commit is contained in:
Winni Neessen 2021-09-22 15:25:27 +02:00
parent 8b29b608c4
commit 297b5b86f1
Signed by: wneessen
GPG key ID: 385AC9889632126E
3 changed files with 20 additions and 17 deletions

View file

@ -99,7 +99,7 @@ func (b *BreachApi) Breaches(options ...BreachOption) ([]*Breach, *http.Response
queryParams := b.setBreachOpts(options...) queryParams := b.setBreachOpts(options...)
apiUrl := fmt.Sprintf("%s/breaches", BaseUrl) apiUrl := fmt.Sprintf("%s/breaches", BaseUrl)
hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, queryParams) hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, queryParams)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -121,7 +121,7 @@ func (b *BreachApi) BreachByName(n string, options ...BreachOption) (*Breach, *h
} }
apiUrl := fmt.Sprintf("%s/breach/%s", BaseUrl, n) apiUrl := fmt.Sprintf("%s/breach/%s", BaseUrl, n)
hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, queryParams) hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, queryParams)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -138,7 +138,7 @@ func (b *BreachApi) BreachByName(n string, options ...BreachOption) (*Breach, *h
// with all registered data classes known to HIBP // with all registered data classes known to HIBP
func (b *BreachApi) DataClasses() ([]string, *http.Response, error) { func (b *BreachApi) DataClasses() ([]string, *http.Response, error) {
apiUrl := fmt.Sprintf("%s/dataclasses", BaseUrl) apiUrl := fmt.Sprintf("%s/dataclasses", BaseUrl)
hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, nil) hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, nil)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -160,7 +160,7 @@ func (b *BreachApi) BreachedAccount(a string, options ...BreachOption) ([]*Breac
} }
apiUrl := fmt.Sprintf("%s/breachedaccount/%s", BaseUrl, a) apiUrl := fmt.Sprintf("%s/breachedaccount/%s", BaseUrl, a)
hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, queryParams) hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, queryParams)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View file

@ -244,7 +244,7 @@ func TestBreachedAccountWithoutTruncate(t *testing.T) {
if apiKey == "" { if apiKey == "" {
t.SkipNow() t.SkipNow()
} }
hc := New(WithApiKey(apiKey), WithRateLimitNoFail()) hc := New(WithApiKey(apiKey), WithRateLimitSleep())
if hc == nil { if hc == nil {
t.Error("failed to create HIBP client") t.Error("failed to create HIBP client")
return return

27
hibp.go
View file

@ -24,11 +24,14 @@ const DefaultUserAgent = `go-hibp v` + Version // + ` - https://github.com/wnees
// Client is the HIBP client object // Client is the HIBP client object
type Client struct { type Client struct {
hc *http.Client // HTTP client to perform the API requests hc *http.Client // HTTP client to perform the API requests
to time.Duration // HTTP client timeout to time.Duration // HTTP client timeout
ak string // HIBP API key ak string // HIBP API key
ua string // User agent string for the HTTP client ua string // User agent string for the HTTP client
rlNoFail bool // Controls wether the HTTP client should fail or sleep in case the rate limiting hits
// If set to true, the HTTP client will sleep instead of failing in case the HTTP 429
// rate limit hits a request
rlSleep bool
PwnedPassApi *PwnedPassApi // Reference to the PwnedPassApi API PwnedPassApi *PwnedPassApi // Reference to the PwnedPassApi API
PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API
@ -97,10 +100,10 @@ func WithUserAgent(a string) Option {
} }
} }
// WithRateLimitNoFail let's the HTTP client sleep in case the API rate limiting hits (Defaults to fail) // WithRateLimitSleep let's the HTTP client sleep in case the API rate limiting hits (Defaults to fail)
func WithRateLimitNoFail() Option { func WithRateLimitSleep() Option {
return func(c *Client) { return func(c *Client) {
c.rlNoFail = true c.rlSleep = true
} }
} }
@ -146,8 +149,8 @@ func (c *Client) HttpReq(m, p string, q map[string]string) (*http.Request, error
return hr, nil return hr, nil
} }
// HttpReqBody performs the API call to the given path and returns the response body as byte array // HttpResBody performs the API call to the given path and returns the response body as byte array
func (c *Client) HttpReqBody(m string, p string, q map[string]string) ([]byte, *http.Response, error) { func (c *Client) HttpResBody(m string, p string, q map[string]string) ([]byte, *http.Response, error) {
hreq, err := c.HttpReq(m, p, q) hreq, err := c.HttpReq(m, p, q)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -165,7 +168,7 @@ func (c *Client) HttpReqBody(m string, p string, q map[string]string) ([]byte, *
return nil, hr, err return nil, hr, err
} }
if hr.StatusCode == 429 && c.rlNoFail { if hr.StatusCode == 429 && c.rlSleep {
headerDelay := hr.Header.Get("Retry-After") headerDelay := hr.Header.Get("Retry-After")
delayTime, err := time.ParseDuration(headerDelay + "s") delayTime, err := time.ParseDuration(headerDelay + "s")
if err != nil { if err != nil {
@ -173,7 +176,7 @@ func (c *Client) HttpReqBody(m string, p string, q map[string]string) ([]byte, *
} }
log.Printf("API rate limit hit. Retrying request in %s", delayTime.String()) log.Printf("API rate limit hit. Retrying request in %s", delayTime.String())
time.Sleep(delayTime) time.Sleep(delayTime)
return c.HttpReqBody(m, p, q) return c.HttpResBody(m, p, q)
} }
if hr.StatusCode != 200 { if hr.StatusCode != 200 {