Passed
Push — main ( 0c52e1...45ba15 )
by Acho
57s
created

mobilenig.*Client.do   A

Complexity

Conditions 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nop 1
dl 0
loc 19
rs 9.3333
c 0
b 0
f 0
1
package mobilenig
2
3
import (
4
	"context"
5
	"encoding/json"
6
	"fmt"
7
	"io"
8
	"io/ioutil"
9
	"net/http"
10
)
11
12
const (
13
	apiBaseURL = "https://mobilenig.com/API"
14
)
15
16
type service struct {
17
	client *Client
18
}
19
20
// Client is the MobileNig API client.
21
// Do not instantiate this client with Client{}. Use the New method instead.
22
type Client struct {
23
	httpClient  *http.Client
24
	common      service
25
	environment Environment
26
	username    string
27
	apiKey      string
28
	baseURL     string
29
	Bills       *BillsService
30
}
31
32
// New creates and returns a new mobilenig.Client from a slice of mobilenig.ClientOption.
33
func New(options ...ClientOption) *Client {
34
	config := defaultClientConfig()
35
36
	for _, option := range options {
37
		option.apply(config)
38
	}
39
40
	client := &Client{
41
		httpClient:  config.httpClient,
42
		environment: config.environment,
43
		username:    config.username,
44
		baseURL:     config.baseURL,
45
		apiKey:      config.apiKey,
46
	}
47
48
	client.common.client = client
49
	client.Bills = (*BillsService)(&client.common)
50
	return client
51
}
52
53
// newRequest creates an API request. A relative URL can be provided in uri,
54
// in which case it is resolved relative to the apiBaseURL of the Client.
55
// URI's should always be specified without a preceding slash.
56
func (client *Client) newRequest(ctx context.Context, uri string, params map[string]string) (*http.Request, error) {
57
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, client.baseURL+uri, nil)
58
	if err != nil {
59
		return nil, err
60
	}
61
62
	q := req.URL.Query()
63
64
	q.Add("username", client.username)
65
	q.Add("api_key", client.apiKey)
66
67
	for key, value := range params {
68
		q.Add(key, value)
69
	}
70
71
	req.URL.RawQuery = q.Encode()
72
73
	return req, nil
74
}
75
76
// do carries out an HTTP request and returns a Response
77
func (client *Client) do(req *http.Request) (*Response, error) {
78
	httpResponse, err := client.httpClient.Do(req)
79
	if err != nil {
80
		return nil, err
81
	}
82
83
	defer func() { _ = httpResponse.Body.Close() }()
84
85
	resp, err := client.newResponse(httpResponse)
86
	if err != nil {
87
		return resp, err
88
	}
89
90
	_, err = io.Copy(ioutil.Discard, httpResponse.Body)
91
	if err != nil {
92
		return resp, err
93
	}
94
95
	return resp, nil
96
}
97
98
// newResponse converts an *http.Response to *Response
99
func (client *Client) newResponse(httpResponse *http.Response) (*Response, error) {
100
	if httpResponse == nil {
101
		return nil, fmt.Errorf("%T cannot be nil", httpResponse)
102
	}
103
104
	resp := new(Response)
105
	resp.HTTPResponse = httpResponse
106
107
	buf, err := ioutil.ReadAll(resp.HTTPResponse.Body)
108
	if err != nil {
109
		return nil, err
110
	}
111
	resp.Body = &buf
112
113
	errResponse := new(ErrorResponse)
114
	err = json.Unmarshal(*resp.Body, errResponse)
115
	if err == nil {
116
		resp.Error = errResponse
117
	}
118
119
	return resp, resp.Err()
120
}
121