Passed
Push — main ( ca1a65...aff05a )
by Acho
02:34
created

client.*Client.newRequestWithPublicKey   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 4
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
package client
2
3
import (
4
	"bytes"
5
	"context"
6
	"encoding/json"
7
	"fmt"
8
	"io"
9
	"net/http"
10
)
11
12
type service struct {
13
	client *Client
14
}
15
16
// Client is the plunk API client.
17
// Do not instantiate this client with Client. Use the New method instead.
18
type Client struct {
19
	httpClient *http.Client
20
	common     service
21
	baseURL    string
22
	secretKey  string
23
	publicKey  string
24
25
	Contacts *contactService
26
	Tracker  *trackerService
27
}
28
29
// New creates and returns a new Client from a slice of Option.
30
func New(options ...Option) *Client {
31
	config := defaultClientConfig()
32
33
	for _, option := range options {
34
		option.apply(config)
35
	}
36
37
	client := &Client{
38
		httpClient: config.httpClient,
39
		secretKey:  config.secretKey,
40
		publicKey:  config.publicKey,
41
		baseURL:    config.baseURL,
42
	}
43
44
	client.common.client = client
45
	client.Contacts = (*contactService)(&client.common)
46
	client.Tracker = (*trackerService)(&client.common)
47
	return client
48
}
49
50
// newRequest creates an API request. A relative URL can be provided in uri,
51
// in which case it is resolved relative to the BaseURL of the Client.
52
// URI's should always be specified without a preceding slash.
53
func (client *Client) newRequest(ctx context.Context, key, method, uri string, body any) (*http.Request, error) {
54
	var buf io.ReadWriter
55
	if body != nil {
56
		buf = &bytes.Buffer{}
57
		enc := json.NewEncoder(buf)
58
		enc.SetEscapeHTML(false)
59
		err := enc.Encode(body)
60
		if err != nil {
61
			return nil, err
62
		}
63
	}
64
65
	req, err := http.NewRequestWithContext(ctx, method, client.baseURL+uri, buf)
66
	if err != nil {
67
		return nil, err
68
	}
69
70
	req.Header.Set("Content-Type", "application/json")
71
	req.Header.Set("Accept", "application/json")
72
	req.Header.Set("Authorization", "Bearer "+key)
73
74
	return req, nil
75
}
76
77
func (client *Client) newRequestWithSecretKey(ctx context.Context, method, uri string, body any) (*http.Request, error) {
78
	return client.newRequest(ctx, client.secretKey, method, uri, body)
79
}
80
81
func (client *Client) newRequestWithPublicKey(ctx context.Context, method, uri string, body any) (*http.Request, error) {
82
	return client.newRequest(ctx, client.publicKey, method, uri, body)
83
}
84
85
// addURLParams adds urls parameters to an *http.Request
86
func (client *Client) addURLParams(request *http.Request, params map[string]string) *http.Request {
87
	q := request.URL.Query()
88
	for key, value := range params {
89
		q.Add(key, value)
90
	}
91
	request.URL.RawQuery = q.Encode()
92
	return request
93
}
94
95
// do carries out an HTTP request and returns a Response
96
func (client *Client) do(req *http.Request) (*Response, error) {
97
	if req == nil {
98
		return nil, fmt.Errorf("%T cannot be nil", req)
99
	}
100
101
	httpResponse, err := client.httpClient.Do(req)
102
	if err != nil {
103
		return nil, err
104
	}
105
106
	defer func() { _ = httpResponse.Body.Close() }()
107
108
	resp, err := client.newResponse(httpResponse)
109
	if err != nil {
110
		return resp, err
111
	}
112
113
	_, err = io.Copy(io.Discard, httpResponse.Body)
114
	if err != nil {
115
		return resp, err
116
	}
117
118
	return resp, nil
119
}
120
121
// newResponse converts an *http.Response to *Response
122
func (client *Client) newResponse(httpResponse *http.Response) (*Response, error) {
123
	if httpResponse == nil {
124
		return nil, fmt.Errorf("%T cannot be nil", httpResponse)
125
	}
126
127
	resp := new(Response)
128
	resp.HTTPResponse = httpResponse
129
130
	buf, err := io.ReadAll(resp.HTTPResponse.Body)
131
	if err != nil {
132
		return nil, err
133
	}
134
	resp.Body = &buf
135
136
	return resp, resp.Error()
137
}
138