-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrestype.go
99 lines (85 loc) · 2.48 KB
/
restype.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
package restype
import (
"encoding/json"
"fmt"
"strings"
"github.com/go-resty/resty/v2"
)
// Request[T] represents a request with a response of type T.
type Request[T any] interface {
Method() string
Path() string
PathParams() map[string]string
QueryParams() map[string]string
Headers() map[string]string
Body() ([]byte, error)
ResponseFromBytes([]byte) (T, error)
}
// RequestOptions are functions that modify resty.Request and return a reference to it.
//
// Allows for modifying the request where required or
// where it does not make sense to add to implementations of Request[T].
type RequestOptions func(*resty.Request) *resty.Request
// Do performs a request using resty.Client with
// request of type `Request[T]`,
// response of type `T`,
// error of type `error`.
//
// Requests without response should specify the `any` type.
// Requests without typed error should specify the `error` type.
//
// RequestOptions enable modification of the request.
func Do[R Request[T], T any, E error](client *resty.Client, req R, opts ...RequestOptions) (t T, err error) {
_, t, err = DoRaw[R, T, E](client, req, opts...)
return t, err
}
// DoRaw performs the same function as Do
// and returns the raw resty.Response.
func DoRaw[R Request[T], T any, E error](client *resty.Client, req R, opts ...RequestOptions) (res *resty.Response, t T, err error) {
var (
method = req.Method()
path = req.Path()
pathParams = req.PathParams()
queryParams = req.QueryParams()
headers = req.Headers()
)
body, err := req.Body()
if err != nil {
return res, t, Error{kind: ErrorBodyFromRequest, original: err}
}
builder := client.R().
SetHeaders(headers).
SetQueryParams(queryParams).
SetPathParams(pathParams)
for _, opt := range opts {
builder = opt(builder)
}
// SetBody does not handle nil
if body != nil {
builder = builder.SetBody(body)
}
res, err = builder.
Execute(method, path)
if err != nil {
return res, t, Error{kind: ErrorExecuteRequest, original: err}
}
if res.IsSuccess() {
t, err = req.ResponseFromBytes(res.Body())
if err != nil {
return res, t, Error{kind: ErrorResponseFromBytes, original: err}
}
return res, t, nil
}
if res.IsError() {
if strings.HasPrefix(strings.ToLower(res.Header().Get("content-type")), "application/json") {
var e E
if err := json.Unmarshal(res.Body(), &e); err == nil {
return res, t, e
}
}
// Return body as error string
err = fmt.Errorf("%s", res.Body())
return res, t, err
}
return res, t, nil
}