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
Pull Request — master (#7)
by Victor Hugo
01:15
created

mollie.newResponse   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

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