forked from DrFaust92/terraform-provider-bitbucket
/
client.go
146 lines (117 loc) · 4.02 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package bitbucket
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"golang.org/x/oauth2"
)
// Error represents a error from the bitbucket api.
type Error struct {
APIError struct {
Message string `json:"message,omitempty"`
} `json:"error,omitempty"`
Type string `json:"type,omitempty"`
StatusCode int
Endpoint string
}
func (e Error) Error() string {
return fmt.Sprintf("API Error: %d %s %s", e.StatusCode, e.Endpoint, e.APIError.Message)
}
const (
// BitbucketEndpoint is the fqdn used to talk to bitbucket
BitbucketEndpoint string = "https://api.bitbucket.org/"
)
// Client is the base internal Client to talk to bitbuckets API. This should be a username and password
// the password should be a app-password.
type Client struct {
Username *string
Password *string
OAuthToken *string
OAuthTokenSource oauth2.TokenSource
HTTPClient *http.Client
}
// Do Will just call the bitbucket api but also add auth to it and some extra headers
func (c *Client) Do(method, endpoint string, payload *bytes.Buffer, contentType string) (*http.Response, error) {
absoluteendpoint := BitbucketEndpoint + endpoint
log.Printf("[DEBUG] Sending request to %s %s", method, absoluteendpoint)
var bodyreader io.Reader
if payload != nil {
log.Printf("[DEBUG] With payload %s", payload.String())
bodyreader = payload
}
req, err := http.NewRequest(method, absoluteendpoint, bodyreader)
if err != nil {
return nil, err
}
if c.Username != nil && c.Password != nil {
log.Printf("[DEBUG] Setting Basic Auth")
req.SetBasicAuth(*c.Username, *c.Password)
}
if c.OAuthToken != nil {
log.Printf("[DEBUG] Setting Bearer Token")
bearer := "Bearer " + *c.OAuthToken
req.Header.Add("Authorization", bearer)
}
if c.OAuthTokenSource != nil {
token, err := c.OAuthTokenSource.Token()
if err != nil {
return nil, err
}
token.SetAuthHeader(req)
}
if payload != nil && contentType != "" {
// Can cause bad request when putting default reviews if set.
req.Header.Add("Content-Type", contentType)
}
req.Close = true
resp, err := c.HTTPClient.Do(req)
log.Printf("[DEBUG] Resp: %v Err: %v", resp, err)
if resp.StatusCode >= 400 || resp.StatusCode < 200 {
apiError := Error{
StatusCode: resp.StatusCode,
Endpoint: endpoint,
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
log.Printf("[DEBUG] Resp Body: %s", string(body))
err = json.Unmarshal(body, &apiError)
if err != nil {
apiError.APIError.Message = string(body)
}
return resp, error(apiError)
}
return resp, err
}
// Get is just a helper method to do but with a GET verb
func (c *Client) Get(endpoint string) (*http.Response, error) {
return c.Do("GET", endpoint, nil, "application/json")
}
// Post is just a helper method to do but with a POST verb
func (c *Client) Post(endpoint string, jsonpayload *bytes.Buffer) (*http.Response, error) {
return c.Do("POST", endpoint, jsonpayload, "application/json")
}
// PostNonJson is just a helper method to do but with a POST verb without Json Header
func (c *Client) PostNonJson(endpoint string, payload *bytes.Buffer) (*http.Response, error) {
return c.Do("POST", endpoint, payload, "")
}
// PostWithContentType is just a helper method to do but with a POST verb and a provided content type
func (c *Client) PostWithContentType(endpoint, contentType string, payload *bytes.Buffer) (*http.Response, error) {
return c.Do("POST", endpoint, payload, contentType)
}
// Put is just a helper method to do but with a PUT verb
func (c *Client) Put(endpoint string, jsonpayload *bytes.Buffer) (*http.Response, error) {
return c.Do("PUT", endpoint, jsonpayload, "application/json")
}
// PutOnly is just a helper method to do but with a PUT verb and a nil body
func (c *Client) PutOnly(endpoint string) (*http.Response, error) {
return c.Do("PUT", endpoint, nil, "application/json")
}
// Delete is just a helper to Do but with a DELETE verb
func (c *Client) Delete(endpoint string) (*http.Response, error) {
return c.Do("DELETE", endpoint, nil, "application/json")
}