-
Notifications
You must be signed in to change notification settings - Fork 2
/
httpclient.go
156 lines (143 loc) · 4.04 KB
/
httpclient.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
147
148
149
150
151
152
153
154
155
156
package httpclient
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
)
var Client http.Client
const (
ErrJSON = "httpclient: json error decoding response"
ErrJSON2 = "httpclient: json error decoding error response"
ErrRequest = "httpclient: error creating http request"
ErrStatus = "httpclient: http.Status not OK"
)
// ErrHttpClient error stuct
type ErrHttpClient struct {
Status int
Message string
Body http.Response
}
// ErrHttpClient.Error implementation of error interface
func (e ErrHttpClient) Error() string {
return e.Message
}
// Endpoint struct for an http endpoint
type Endpoint struct {
URL string
Method string
Route string
Authorization string
Headers []Header
Data any
}
type JSONEndpoint[T any, R any] struct {
URL string
Method string
Route string
Authorization string
Headers []Header
Data any
Response T
ErrorResponse R
}
type Header struct {
Name string
Value string
}
func init() {
Client = http.Client{
Timeout: 30 * time.Second,
}
}
// GetResponse returns respnse from http request to url
func GetResponse(data any, method, url, auth string, headers []Header) (*http.Response, error) {
var request *http.Request
var response *http.Response
var err error
if data != nil {
payload, err := json.Marshal(data)
if err != nil {
return response, ErrHttpClient{
Status: http.StatusBadRequest,
Message: ErrJSON,
Body: *response,
}
}
request, err = http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
log.Println("httclient:NewRequest with payload", err)
return response, ErrHttpClient{
Status: http.StatusBadRequest,
Message: ErrRequest,
Body: *response,
}
}
request.Header.Set("Content-Type", "application/json")
} else {
request, err = http.NewRequest(method, url, nil)
if err != nil {
log.Println("httclient:NewRequest", err)
return response, ErrHttpClient{
Status: http.StatusBadRequest,
Message: ErrRequest,
Body: *response,
}
}
}
if auth != "" {
request.Header.Set("Authorization", auth)
}
for _, header := range headers {
request.Header.Set(header.Name, header.Value)
}
return Client.Do(request)
}
// JSON returns JSON response from http request
// if response.code is http.StatusOK (200) returns resp, nil, nil
// if response.code is not http.Status ok returns nil, errResponse, ErrStatus
// if json decode err returns nil, nil, err set to 'json decode err'
// for any other err returns nil, nil, err
func GetJSON[T any, R any](data any, resp T, errResponse R, method, url, auth string, headers []Header) (T, R, error) {
response, err := GetResponse(data, method, url, auth, headers)
if err != nil {
return resp, errResponse, ErrHttpClient{
Status: response.StatusCode,
Message: fmt.Errorf("%w", err).Error(),
Body: *response,
}
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
if err := json.NewDecoder(response.Body).Decode(&errResponse); err != nil {
return resp, errResponse, ErrHttpClient{
Status: response.StatusCode,
Message: fmt.Errorf("json decode err with error response %w", err).Error(),
Body: *response,
}
}
return resp, errResponse, ErrHttpClient{
Status: response.StatusCode,
Message: ErrStatus,
Body: *response,
}
}
if err := json.NewDecoder(response.Body).Decode(&resp); err != nil {
return resp, errResponse, ErrHttpClient{
Status: response.StatusCode,
Message: fmt.Errorf("json decode err with response %w", err).Error(),
Body: *response,
}
}
return resp, errResponse, nil
}
// GetResponse returns response from http endpoint
func (e *Endpoint) GetResponse() (*http.Response, error) {
return GetResponse(e.Data, e.Method, e.URL+e.Route, e.Authorization, e.Headers)
}
// GetJSON returns JSON received from http endpoint
func (e *JSONEndpoint[T, R]) GetJSON(response T, errResponse R) (T, R, error) {
return GetJSON(e.Data, response, errResponse, e.Method, e.URL+e.Route, e.Authorization, e.Headers)
}