GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 89a659...e28386 )
by Victor Hugo
01:11 queued 11s
created

mollie.*Client.Do   A

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
cc 3
eloc 10
dl 0
loc 13
c 0
b 0
f 0
ccs 8
cts 9
cp 0.8889
crap 3.0123
rs 9.9
nop 1
1
package mollie
2
3
import (
4
	"bytes"
5
	"encoding/json"
6
	"errors"
7
	"fmt"
8
	"io"
9
	"io/ioutil"
10
	"net/http"
11
	"net/url"
12
	"os"
13
	"strings"
14
)
15
16
// Mollie  constants holding values to initialize the client and create requests.
17
const (
18
	BaseURL            string = "https://api.mollie.com/"
19
	AuthHeader         string = "Authorization"
20
	TokenType          string = "Bearer"
21
	APITokenEnv        string = "MOLLIE_API_TOKEN"
22
	OrgTokenEnv        string = "MOLLIE_ORG_TOKEN"
23
	RequestContentType string = "application/json"
24
)
25
26
var (
27
	errEmptyAPIKey = errors.New("you must provide a non-empty API key")
28
	errBadBaseURL  = errors.New("malformed base url, it must contain a trailing slash")
29
)
30
31
// Client manages communication with Mollie's API.
32
type Client struct {
33
	BaseURL        *url.URL
34
	authentication string
35
	client         *http.Client
36
	common         service // Reuse a single struct instead of allocating one for each service on the heap.
37
	config         *Config
38
	// Services
39
	Payments    *PaymentsService
40
	Chargebacks *ChargebacksService
41
	Methods     *MethodsService
42
}
43
44
type service struct {
45
	client *Client
46
}
47
48
// WithAuthenticationValue offers a convenient setter for any of the valid authentication
49
// tokens provided by Mollie.
50
//
51
// Ideally your API key will be provided from and environment variable or
52
// a secret management engine.
53
// This should only be used when environment variables are "impossible" to be used.
54
func (c *Client) WithAuthenticationValue(k string) error {
55 1
	if k == "" {
56 1
		return errEmptyAPIKey
57
	}
58
59 1
	c.authentication = strings.TrimSpace(k)
60
61 1
	return nil
62
}
63
64
// NewAPIRequest is a wrapper around the http.NewRequest function.
65
//
66
// It will setup the authentication headers/parameters according to the client config.
67
func (c *Client) NewAPIRequest(method string, uri string, body interface{}) (req *http.Request, err error) {
68 1
	if !strings.HasSuffix(c.BaseURL.Path, "/") {
69 1
		return nil, errBadBaseURL
70
	}
71
72 1
	u, err := c.BaseURL.Parse(uri)
73 1
	if err != nil {
74 1
		return nil, err
75
	}
76
77 1
	if c.config.testing == true {
78 1
		u.Query().Add("testmode", "true")
79
	}
80
81 1
	var buf io.ReadWriter
82 1
	if body != nil {
83 1
		buf = new(bytes.Buffer)
84 1
		enc := json.NewEncoder(buf)
85 1
		enc.SetEscapeHTML(false)
86 1
		err := enc.Encode(body)
87 1
		if err != nil {
88 1
			return nil, err
89
		}
90
	}
91
92 1
	req, err = http.NewRequest(method, u.String(), buf)
93 1
	if err != nil {
94 1
		return nil, err
95
	}
96
97 1
	req.Header.Add(AuthHeader, strings.Join([]string{TokenType, c.authentication}, " "))
98
99 1
	if body != nil {
100 1
		req.Header.Set("Content-Type", RequestContentType)
101
	}
102 1
	req.Header.Set("Accept", RequestContentType)
103
104 1
	return
105
}
106
107
// Do sends an API request and returns the API response or returned as an
108
// error if an API error has occurred.
109
func (c *Client) Do(req *http.Request) (*Response, error) {
110 1
	resp, err := c.client.Do(req)
111 1
	if err != nil {
112
		return nil, err
113
	}
114 1
	defer resp.Body.Close()
115 1
	response := newResponse(resp)
116 1
	err = CheckResponse(resp)
117 1
	if err != nil {
118 1
		return nil, err
119
	}
120
121 1
	return response, nil
122
}
123
124
// NewClient returns a new Mollie HTTP API client.
125
// You can pass a previously build http client, if none is provided then
126
// http.DefaultClient will be used.
127
//
128
// NewClient will lookup the environment for values to assign to the
129
// API token (`MOLLIE_API_TOKEN`) and the Organization token (`MOLLIE_ORG_TOKEN`)
130
// according to the provided Config object.
131
//
132
// You can also set the token values programmatically by using the Client
133
// WithAPIKey and WithOrganizationKey functions.
134
func NewClient(baseClient *http.Client, c *Config) (mollie *Client, err error) {
135 1
	if baseClient == nil {
136 1
		baseClient = http.DefaultClient
137
	}
138
139 1
	u, _ := url.Parse(BaseURL)
140
141 1
	mollie = &Client{
142
		BaseURL: u,
143
		client:  baseClient,
144
		config:  c,
145
	}
146
147 1
	mollie.common.client = mollie
148
149
	// services for resources
150 1
	mollie.Payments = (*PaymentsService)(&mollie.common)
151 1
	mollie.Chargebacks = (*ChargebacksService)(&mollie.common)
152 1
	mollie.Methods = (*MethodsService)(&mollie.common)
153
154
	// Parse authorization from environment
155 1
	if tkn, ok := os.LookupEnv(APITokenEnv); ok {
156 1
		mollie.authentication = tkn
157
	}
158 1
	return
159
}
160
161
/*
162
Error reports details on a failed API request.
163
The success or failure of each HTTP request is shown in the status field of the HTTP response header,
164
which contains standard HTTP status codes:
165
- a 2xx code for success
166
- a 4xx or 5xx code for failure
167
*/
168
type Error struct {
169
	Code     int            `json:"code"`
170
	Message  string         `json:"message"`
171
	Response *http.Response `json:"response"` // the full response that produced the error
172
}
173
174
// Error functions implement the Error interface on the zuora.Error struct.
175
func (e *Error) Error() string {
176 1
	return fmt.Sprintf("response failed with status %v", e.Message)
177
}
178
179
/*
180
Constructor for Error
181
*/
182
func newError(r *http.Response) *Error {
183 1
	var e Error
184 1
	e.Response = r
185 1
	e.Code = r.StatusCode
186 1
	e.Message = r.Status
187 1
	return &e
188
}
189
190
// Response is a Mollie API response. This wraps the standard http.Response
191
// returned from Mollie and provides convenient access to things like
192
// pagination links.
193
type Response struct {
194
	*http.Response
195
	content []byte
196
}
197
198
func newResponse(r *http.Response) *Response {
199 1
	var res Response
200 1
	if c, err := ioutil.ReadAll(r.Body); err == nil {
201 1
		res.content = c
202
	}
203 1
	json.NewDecoder(r.Body).Decode(&res)
204 1
	res.Response = r
205 1
	return &res
206
}
207
208
// CheckResponse checks the API response for errors, and returns them if
209
// present. A response is considered an error if it has a status code outside
210
// the 200 range.
211
// API error responses are expected to have either no response
212
// body, or a JSON response body.
213
func CheckResponse(r *http.Response) error {
214 1
	if r.StatusCode >= http.StatusMultipleChoices {
215 1
		return newError(r)
216
	}
217 1
	return nil
218
}
219