diff --git a/breach.go b/breach.go index 280a601..4ae83f4 100644 --- a/breach.go +++ b/breach.go @@ -99,7 +99,7 @@ func (b *BreachApi) Breaches(options ...BreachOption) ([]*Breach, *http.Response queryParams := b.setBreachOpts(options...) 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 { 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) - hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, queryParams) + hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, queryParams) if err != nil { 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 func (b *BreachApi) DataClasses() ([]string, *http.Response, error) { 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 { 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) - hb, hr, err := b.hibp.HttpReqBody(http.MethodGet, apiUrl, queryParams) + hb, hr, err := b.hibp.HttpResBody(http.MethodGet, apiUrl, queryParams) if err != nil { return nil, nil, err } diff --git a/breach_test.go b/breach_test.go index 4e27d37..b69270c 100644 --- a/breach_test.go +++ b/breach_test.go @@ -9,11 +9,6 @@ import ( // TestBreaches tests the Breaches() method of the breaches API func TestBreaches(t *testing.T) { hc := New() - if hc == nil { - t.Errorf("hibp client creation failed") - return - } - breachList, _, err := hc.BreachApi.Breaches() if err != nil { t.Error(err) @@ -26,11 +21,6 @@ func TestBreaches(t *testing.T) { // TestBreachesWithNil tests the Breaches() method of the breaches API with a nil option func TestBreachesWithNil(t *testing.T) { hc := New() - if hc == nil { - t.Errorf("hibp client creation failed") - return - } - breachList, _, err := hc.BreachApi.Breaches(nil) if err != nil { t.Error(err) @@ -52,11 +42,6 @@ func TestBreachesWithDomain(t *testing.T) { } hc := New() - if hc == nil { - t.Error("failed to create HIBP client") - return - } - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { breachList, _, err := hc.BreachApi.Breaches(WithDomain(tc.domain)) @@ -96,11 +81,6 @@ func TestBreachesWithoutUnverified(t *testing.T) { } hc := New() - if hc == nil { - t.Error("failed to create HIBP client") - return - } - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { breachList, _, err := hc.BreachApi.Breaches(WithDomain(tc.domain), WithoutUnverified()) @@ -129,11 +109,6 @@ func TestBreachByName(t *testing.T) { } hc := New() - if hc == nil { - t.Error("failed to create HIBP client") - return - } - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { breachDetails, _, err := hc.BreachApi.BreachByName(tc.breachName) @@ -156,11 +131,6 @@ func TestBreachByName(t *testing.T) { // TestDataClasses tests the DataClasses() method of the breaches API func TestDataClasses(t *testing.T) { hc := New() - if hc == nil { - t.Errorf("hibp client creation failed") - return - } - classList, _, err := hc.BreachApi.DataClasses() if err != nil { t.Error(err) @@ -190,11 +160,6 @@ func TestBreachedAccount(t *testing.T) { t.SkipNow() } hc := New(WithApiKey(apiKey)) - if hc == nil { - t.Error("failed to create HIBP client") - return - } - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { breachDetails, _, err := hc.BreachApi.BreachedAccount( @@ -244,12 +209,7 @@ func TestBreachedAccountWithoutTruncate(t *testing.T) { if apiKey == "" { t.SkipNow() } - hc := New(WithApiKey(apiKey), WithRateLimitNoFail()) - if hc == nil { - t.Error("failed to create HIBP client") - return - } - + hc := New(WithApiKey(apiKey), WithRateLimitSleep()) for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { breachDetails, _, err := hc.BreachApi.BreachedAccount( diff --git a/examples/breaches/all-breaches-nounverified.go b/examples/breaches-api/all-breaches-nounverified/main.go similarity index 81% rename from examples/breaches/all-breaches-nounverified.go rename to examples/breaches-api/all-breaches-nounverified/main.go index 8e02fc6..e051605 100644 --- a/examples/breaches/all-breaches-nounverified.go +++ b/examples/breaches-api/all-breaches-nounverified/main.go @@ -2,15 +2,11 @@ package main import ( "fmt" - hibp "github.com/wneessen/go-hibp" + "github.com/wneessen/go-hibp" ) func main() { hc := hibp.New() - if hc == nil { - panic("failed to create HIBP client") - } - bl, _, err := hc.BreachApi.Breaches() if err != nil { panic(err) diff --git a/examples/breaches/all-breaches.go b/examples/breaches-api/all-breaches/main.go similarity index 78% rename from examples/breaches/all-breaches.go rename to examples/breaches-api/all-breaches/main.go index d33d9b0..c60685d 100644 --- a/examples/breaches/all-breaches.go +++ b/examples/breaches-api/all-breaches/main.go @@ -2,15 +2,11 @@ package main import ( "fmt" - hibp "github.com/wneessen/go-hibp" + "github.com/wneessen/go-hibp" ) func main() { hc := hibp.New() - if hc == nil { - panic("failed to create HIBP client") - } - bl, _, err := hc.BreachApi.Breaches() if err != nil { panic(err) diff --git a/examples/breaches/breach-by-name.go b/examples/breaches-api/breach-by-name/main.go similarity index 87% rename from examples/breaches/breach-by-name.go rename to examples/breaches-api/breach-by-name/main.go index f5e0886..d0326d5 100644 --- a/examples/breaches/breach-by-name.go +++ b/examples/breaches-api/breach-by-name/main.go @@ -7,10 +7,6 @@ import ( func main() { hc := hibp.New() - if hc == nil { - panic("failed to create HIBP client") - } - bd, _, err := hc.BreachApi.BreachByName("Adobe") if err != nil { panic(err) diff --git a/examples/pwned-password/check-password-withpadding.go b/examples/pwned-password-api/check-password-withpadding/main.go similarity index 77% rename from examples/pwned-password/check-password-withpadding.go rename to examples/pwned-password-api/check-password-withpadding/main.go index 107c28c..62673fa 100644 --- a/examples/pwned-password/check-password-withpadding.go +++ b/examples/pwned-password-api/check-password-withpadding/main.go @@ -2,15 +2,11 @@ package main import ( "fmt" - hibp "github.com/wneessen/go-hibp" + "github.com/wneessen/go-hibp" ) func main() { hc := hibp.New(hibp.WithPwnedPadding()) - if hc == nil { - panic("failed to create HIBP client") - } - m, _, err := hc.PwnedPassApi.CheckPassword("test") if err != nil { panic(err) diff --git a/examples/pwned-password/check-password.go b/examples/pwned-password-api/check-password/main.go similarity index 75% rename from examples/pwned-password/check-password.go rename to examples/pwned-password-api/check-password/main.go index c6996b8..d45b66d 100644 --- a/examples/pwned-password/check-password.go +++ b/examples/pwned-password-api/check-password/main.go @@ -2,15 +2,11 @@ package main import ( "fmt" - hibp "github.com/wneessen/go-hibp" + "github.com/wneessen/go-hibp" ) func main() { hc := hibp.New() - if hc == nil { - panic("failed to create HIBP client") - } - m, _, err := hc.PwnedPassApi.CheckPassword("test") if err != nil { panic(err) diff --git a/examples/pwned-password/check-sha1.go b/examples/pwned-password-api/check-sha1/main.go similarity index 79% rename from examples/pwned-password/check-sha1.go rename to examples/pwned-password-api/check-sha1/main.go index 71a7c30..591b4f3 100644 --- a/examples/pwned-password/check-sha1.go +++ b/examples/pwned-password-api/check-sha1/main.go @@ -2,15 +2,11 @@ package main import ( "fmt" - hibp "github.com/wneessen/go-hibp" + "github.com/wneessen/go-hibp" ) func main() { hc := hibp.New() - if hc == nil { - panic("failed to create HIBP client") - } - pwHash := "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3" // represents the PW: "test" m, _, err := hc.PwnedPassApi.CheckSHA1(pwHash) if err != nil { diff --git a/hibp.go b/hibp.go index 89fec59..7cdbd44 100644 --- a/hibp.go +++ b/hibp.go @@ -12,7 +12,7 @@ import ( ) // Version represents the version of this package -const Version = "0.1.4" +const Version = "0.1.5" // BaseUrl is the base URL for the majority of API calls const BaseUrl = "https://haveibeenpwned.com/api/v3" @@ -24,11 +24,14 @@ const DefaultUserAgent = `go-hibp v` + Version // + ` - https://github.com/wnees // Client is the HIBP client object type Client struct { - hc *http.Client // HTTP client to perform the API requests - to time.Duration // HTTP client timeout - ak string // HIBP API key - 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 + hc *http.Client // HTTP client to perform the API requests + to time.Duration // HTTP client timeout + ak string // HIBP API key + ua string // User agent string for the HTTP client + + // 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 PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API @@ -40,8 +43,8 @@ type Client struct { type Option func(*Client) // New creates and returns a new HIBP client object -func New(options ...Option) *Client { - c := &Client{} +func New(options ...Option) Client { + c := Client{} // Set defaults c.to = time.Second * 5 @@ -53,15 +56,15 @@ func New(options ...Option) *Client { if opt == nil { continue } - opt(c) + opt(&c) } // Add a http client to the Client object c.hc = httpClient(c.to) // Associate the different HIBP service APIs with the Client - c.PwnedPassApi = &PwnedPassApi{hibp: c} - c.BreachApi = &BreachApi{hibp: c} + c.PwnedPassApi = &PwnedPassApi{hibp: &c} + c.BreachApi = &BreachApi{hibp: &c} return c } @@ -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) -func WithRateLimitNoFail() Option { +// WithRateLimitSleep let's the HTTP client sleep in case the API rate limiting hits (Defaults to fail) +func WithRateLimitSleep() Option { 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 } -// HttpReqBody 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) { +// HttpResBody performs the API call to the given path and returns the response body as byte array +func (c *Client) HttpResBody(m string, p string, q map[string]string) ([]byte, *http.Response, error) { hreq, err := c.HttpReq(m, p, q) if err != nil { 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 } - if hr.StatusCode == 429 && c.rlNoFail { + if hr.StatusCode == 429 && c.rlSleep { headerDelay := hr.Header.Get("Retry-After") delayTime, err := time.ParseDuration(headerDelay + "s") 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()) time.Sleep(delayTime) - return c.HttpReqBody(m, p, q) + return c.HttpResBody(m, p, q) } if hr.StatusCode != 200 { diff --git a/hibp_test.go b/hibp_test.go index 5783c41..a264f86 100644 --- a/hibp_test.go +++ b/hibp_test.go @@ -10,7 +10,7 @@ import ( // TestNew tests the New() function func TestNew(t *testing.T) { hc := New() - if hc == nil { + if *hc.PwnedPassApi.hibp != hc { t.Errorf("hibp client creation failed") } } @@ -18,7 +18,7 @@ func TestNew(t *testing.T) { // TestNewWithNil tests the New() function with a nil option func TestNewWithNil(t *testing.T) { hc := New(nil) - if hc == nil { + if *hc.PwnedPassApi.hibp != hc { t.Errorf("hibp client creation failed") } } @@ -26,10 +26,6 @@ func TestNewWithNil(t *testing.T) { // TestNewWithHttpTimeout tests the New() function with the http timeout option func TestNewWithHttpTimeout(t *testing.T) { hc := New(WithHttpTimeout(time.Second * 10)) - if hc == nil { - t.Errorf("hibp client creation failed") - return - } if hc.to != time.Second*10 { t.Errorf("hibp client timeout option was not set properly. Expected %d, got: %d", time.Second*10, hc.to) @@ -39,10 +35,6 @@ func TestNewWithHttpTimeout(t *testing.T) { // TestNewWithPwnedPadding tests the New() function with the PwnedPadding option func TestNewWithPwnedPadding(t *testing.T) { hc := New(WithPwnedPadding()) - if hc == nil { - t.Errorf("hibp client creation failed") - return - } if !hc.PwnedPassApiOpts.WithPadding { t.Errorf("hibp client pwned padding option was not set properly. Expected %v, got: %v", true, hc.PwnedPassApiOpts.WithPadding) @@ -53,10 +45,6 @@ func TestNewWithPwnedPadding(t *testing.T) { func TestNewWithApiKey(t *testing.T) { apiKey := os.Getenv("HIBP_API_KEY") hc := New(WithApiKey(apiKey)) - if hc == nil { - t.Errorf("hibp client creation failed") - return - } if hc.ak != apiKey { t.Errorf("hibp client API key was not set properly. Expected %s, got: %s", apiKey, hc.ak) @@ -66,10 +54,6 @@ func TestNewWithApiKey(t *testing.T) { // TestNewWithUserAgent tests the New() function with a custom user agent func TestNewWithUserAgent(t *testing.T) { hc := New() - if hc == nil { - t.Errorf("hibp client creation failed") - return - } if hc.ua != DefaultUserAgent { t.Errorf("hibp client default user agent was not set properly. Expected %s, got: %s", DefaultUserAgent, hc.ua) @@ -77,10 +61,6 @@ func TestNewWithUserAgent(t *testing.T) { custUA := fmt.Sprintf("customUA v%s", Version) hc = New(WithUserAgent(custUA)) - if hc == nil { - t.Errorf("hibp client creation failed") - return - } if hc.ua != custUA { t.Errorf("hibp client custom user agent was not set properly. Expected %s, got: %s", custUA, hc.ua) diff --git a/password_test.go b/password_test.go index f5ab63b..888cea4 100644 --- a/password_test.go +++ b/password_test.go @@ -16,7 +16,6 @@ func TestPwnedPasswordString(t *testing.T) { "F/0Ws#.%{Z/NVax=OU8Ajf1qTRLNS12p/?s/adX", false}, } hc := New() - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { m, _, err := hc.PwnedPassApi.CheckPassword(tc.pwString) @@ -47,11 +46,6 @@ func TestPwnedPasswordHash(t *testing.T) { "90efc095c82eab44e882fda507cfab1a2cd31fc0", false}, } hc := New() - if hc == nil { - t.Error("failed to create HIBP client") - return - } - for _, tc := range testTable { t.Run(tc.testName, func(t *testing.T) { m, _, err := hc.PwnedPassApi.CheckSHA1(tc.pwHash)