lego/vendor/github.com/nrdcg/auroradns/client.go
2019-02-04 22:43:10 +01:00

144 lines
2.8 KiB
Go

package auroradns
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
)
const defaultBaseURL = "https://api.auroradns.eu"
const (
contentTypeHeader = "Content-Type"
contentTypeJSON = "application/json"
)
// ErrorResponse A representation of an API error message.
type ErrorResponse struct {
ErrorCode string `json:"error"`
Message string `json:"errormsg"`
}
func (e *ErrorResponse) Error() string {
return fmt.Sprintf("%s - %s", e.ErrorCode, e.Message)
}
// Option Type of a client option
type Option func(*Client) error
// Client The API client
type Client struct {
baseURL *url.URL
UserAgent string
httpClient *http.Client
}
// NewClient Creates a new client
func NewClient(httpClient *http.Client, opts ...Option) (*Client, error) {
if httpClient == nil {
httpClient = http.DefaultClient
}
baseURL, _ := url.Parse(defaultBaseURL)
client := &Client{
baseURL: baseURL,
httpClient: httpClient,
}
for _, opt := range opts {
err := opt(client)
if err != nil {
return nil, err
}
}
return client, nil
}
func (c *Client) newRequest(method, resource string, body io.Reader) (*http.Request, error) {
u, err := c.baseURL.Parse(resource)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, u.String(), body)
if err != nil {
return nil, err
}
req.Header.Set(contentTypeHeader, contentTypeJSON)
if c.UserAgent != "" {
req.Header.Set("User-Agent", c.UserAgent)
}
return req, nil
}
func (c *Client) do(req *http.Request, v interface{}) (*http.Response, error) {
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
if err = checkResponse(resp); err != nil {
return resp, err
}
if v == nil {
return resp, nil
}
raw, err := ioutil.ReadAll(resp.Body)
if err != nil {
return resp, fmt.Errorf("failed to read body: %v", err)
}
if err = json.Unmarshal(raw, v); err != nil {
return resp, fmt.Errorf("unmarshaling %T error: %v: %s", err, v, string(raw))
}
return resp, nil
}
func checkResponse(resp *http.Response) error {
if c := resp.StatusCode; 200 <= c && c <= 299 {
return nil
}
data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
errorResponse := new(ErrorResponse)
err = json.Unmarshal(data, errorResponse)
if err != nil {
return fmt.Errorf("unmarshaling ErrorResponse error: %v: %s", err.Error(), string(data))
}
return errorResponse
}
defer func() { _ = resp.Body.Close() }()
return nil
}
// WithBaseURL Allows to define a custom base URL
func WithBaseURL(rawBaseURL string) func(*Client) error {
return func(client *Client) error {
if len(rawBaseURL) == 0 {
return nil
}
baseURL, err := url.Parse(rawBaseURL)
if err != nil {
return err
}
client.baseURL = baseURL
return nil
}
}