generated from brevdev/seed
/
http.go
131 lines (109 loc) · 3.47 KB
/
http.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
package store
import (
"fmt"
"net/http"
breverrors "github.com/brevdev/brev-cli/pkg/errors"
resty "github.com/go-resty/resty/v2"
)
type NoAuthHTTPStore struct {
FileStore
noAuthHTTPClient *NoAuthHTTPClient
}
func (f *FileStore) WithNoAuthHTTPClient(c *NoAuthHTTPClient) *NoAuthHTTPStore {
return &NoAuthHTTPStore{*f, c}
}
// Used if need new instance to customize settings
func (n NoAuthHTTPStore) NewNoAuthHTTPStore() *NoAuthHTTPStore {
return n.WithNoAuthHTTPClient(NewNoAuthHTTPClient(n.noAuthHTTPClient.restyClient.BaseURL))
}
type NoAuthHTTPClient struct {
restyClient *resty.Client
}
func NewNoAuthHTTPClient(brevAPIURL string) *NoAuthHTTPClient {
restyClient := NewRestyClient(brevAPIURL)
return &NoAuthHTTPClient{restyClient}
}
func NewRestyClient(brevAPIURL string) *resty.Client {
restyClient := resty.New()
restyClient.SetBaseURL(brevAPIURL)
restyClient.SetQueryParam("utm_source", "cli")
return restyClient
}
type AuthHTTPStore struct {
NoAuthHTTPStore
authHTTPClient *AuthHTTPClient
isRefreshTokenHandlerSet bool
}
func (f *FileStore) WithAuthHTTPClient(c *AuthHTTPClient) *AuthHTTPStore {
na := f.WithNoAuthHTTPClient(NewNoAuthHTTPClient(c.restyClient.BaseURL))
return &AuthHTTPStore{NoAuthHTTPStore: *na, authHTTPClient: c}
}
func (n *NoAuthHTTPStore) WithAuthHTTPClient(c *AuthHTTPClient) *AuthHTTPStore {
return &AuthHTTPStore{NoAuthHTTPStore: *n, authHTTPClient: c}
}
func (n *NoAuthHTTPStore) WithAuth(auth Auth) *AuthHTTPStore {
return n.WithAuthHTTPClient(NewAuthHTTPClient(auth, n.noAuthHTTPClient.restyClient.BaseURL))
}
// Used if need new instance to customize settings
func (s AuthHTTPStore) NewAuthHTTPStore() *AuthHTTPStore {
return s.WithAuth(s.authHTTPClient.auth)
}
func (s *AuthHTTPStore) SetForbiddenStatusRetryHandler(handler func() error) error {
if s.isRefreshTokenHandlerSet { // need to create a way to idempotently set this
return fmt.Errorf("refresh token handler alreay set")
}
attemptsThresh := 1
s.authHTTPClient.restyClient.OnAfterResponse(func(c *resty.Client, r *resty.Response) error {
if r.StatusCode() == http.StatusForbidden && r.Request.Attempt < attemptsThresh+1 {
err := handler()
if err != nil {
return breverrors.WrapAndTrace(err)
}
}
return nil
})
s.authHTTPClient.restyClient.AddRetryCondition(
func(r *resty.Response, e error) bool {
if e != nil {
return false
}
return r.StatusCode() == http.StatusForbidden
})
s.authHTTPClient.restyClient.SetRetryCount(attemptsThresh)
s.isRefreshTokenHandlerSet = true
return nil
}
type AuthHTTPClient struct {
restyClient *resty.Client
auth Auth
}
type Auth interface {
GetAccessToken() (string, error)
}
func (s *AuthHTTPStore) WithStaticHeader(header string, value string) *AuthHTTPStore {
s.authHTTPClient.restyClient.SetHeader(header, value)
return s
}
func NewAuthHTTPClient(auth Auth, brevAPIURL string) *AuthHTTPClient {
restyClient := NewRestyClient(brevAPIURL)
restyClient.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error {
token, err := auth.GetAccessToken()
if err != nil {
return breverrors.WrapAndTrace(err)
}
r.SetAuthToken(token)
return nil
})
return &AuthHTTPClient{restyClient, auth}
}
type HTTPResponseError struct {
response *resty.Response
}
func NewHTTPResponseError(response *resty.Response) *HTTPResponseError {
return &HTTPResponseError{
response: response,
}
}
func (e HTTPResponseError) Error() string {
return fmt.Sprintf("%s %s", e.response.Request.URL, e.response.Status())
}