go-hibp/hibp.go

139 lines
3 KiB
Go
Raw Normal View History

2021-09-21 11:21:04 +02:00
package hibp
2021-09-19 18:10:12 +02:00
import (
"bytes"
2021-09-21 11:21:04 +02:00
"crypto/tls"
2021-09-19 18:10:12 +02:00
"fmt"
"io"
2021-09-19 18:10:12 +02:00
"net/http"
2021-09-21 11:21:04 +02:00
"net/url"
2021-09-19 18:10:12 +02:00
"time"
)
2021-09-21 11:21:04 +02:00
// Version represents the version of this package
const Version = "0.1.2"
2021-09-19 18:10:12 +02:00
2021-09-21 18:21:23 +02:00
// BaseUrl is the base URL for the majority of API calls
const BaseUrl = "https://haveibeenpwned.com/api/v3"
2021-09-21 11:21:04 +02:00
// 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
2021-09-19 18:10:12 +02:00
2021-09-21 18:21:23 +02:00
PwnedPassApi *PwnedPassApi // Reference to the PwnedPassApi API
PwnedPassApiOpts *PwnedPasswordOptions // Additional options for the PwnedPassApi API
BreachApi *BreachApi // Reference to the BreachApi API
2021-09-21 11:21:04 +02:00
}
// Option is a function that is used for grouping of Client options.
type Option func(*Client)
// New creates and returns a new HIBP client object
func New(options ...Option) *Client {
c := &Client{}
// Set defaults
c.to = time.Second * 5
2021-09-21 18:21:23 +02:00
c.PwnedPassApiOpts = &PwnedPasswordOptions{}
2021-09-21 11:21:04 +02:00
// Set additional options
for _, opt := range options {
opt(c)
}
// Add a http client to the Client object
c.hc = httpClient(c.to)
// Associate the different HIBP service APIs with the Client
2021-09-21 18:21:23 +02:00
c.PwnedPassApi = &PwnedPassApi{hibp: c}
c.BreachApi = &BreachApi{hibp: c}
2021-09-21 11:21:04 +02:00
return c
}
// WithHttpTimeout overrides the default http client timeout
func WithHttpTimeout(t time.Duration) Option {
return func(c *Client) {
c.to = t
}
}
// WithApiKey set the optional API key to the Client object
func WithApiKey(k string) Option {
return func(c *Client) {
c.ak = k
}
}
2021-09-21 18:21:23 +02:00
// WithPwnedPadding enables padding-mode for the PwnedPasswords API client
func WithPwnedPadding() Option {
return func(c *Client) {
c.PwnedPassApiOpts.WithPadding = true
}
}
2021-09-21 11:21:04 +02:00
// HttpReq performs an HTTP request to the corresponding API
func (c *Client) HttpReq(m, p string, q map[string]string) (*http.Request, error) {
2021-09-21 11:21:04 +02:00
u, err := url.Parse(p)
if err != nil {
return nil, err
}
if m == http.MethodGet {
uq := u.Query()
for k, v := range q {
uq.Add(k, v)
}
u.RawQuery = uq.Encode()
}
2021-09-21 11:21:04 +02:00
hr, err := http.NewRequest(m, u.String(), nil)
2021-09-19 18:10:12 +02:00
if err != nil {
2021-09-21 11:21:04 +02:00
return nil, err
}
if m == http.MethodPost {
pd := url.Values{}
for k, v := range q {
pd.Add(k, v)
}
rb := io.NopCloser(bytes.NewBufferString(pd.Encode()))
hr.Body = rb
}
2021-09-21 11:21:04 +02:00
hr.Header.Set("Accept", "application/json")
hr.Header.Set("User-Agent", fmt.Sprintf("go-hibp v%s - https://github.com/wneessen/go-hibp", Version))
if c.ak != "" {
2021-09-21 18:21:23 +02:00
hr.Header.Set("hibp-api-key", c.ak)
}
if c.PwnedPassApiOpts.WithPadding {
hr.Header.Set("Add-Padding", "true")
2021-09-19 18:10:12 +02:00
}
2021-09-21 11:21:04 +02:00
return hr, nil
}
// httpClient returns a custom http client for the HIBP Client object
func httpClient(to time.Duration) *http.Client {
tlsConfig := &tls.Config{
MaxVersion: tls.VersionTLS13,
MinVersion: tls.VersionTLS12,
}
httpTransport := &http.Transport{TLSClientConfig: tlsConfig}
httpClient := &http.Client{
Transport: httpTransport,
Timeout: 5 * time.Second,
2021-09-19 18:10:12 +02:00
}
2021-09-21 11:21:04 +02:00
if to.Nanoseconds() > 0 {
httpClient.Timeout = to
2021-09-19 18:10:12 +02:00
}
2021-09-21 11:21:04 +02:00
return httpClient
2021-09-19 18:10:12 +02:00
}