-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
139 lines (107 loc) · 2.98 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
package corbado
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"runtime"
"github.com/deepmap/oapi-codegen/pkg/securityprovider"
"github.com/pkg/errors"
"github.com/corbado/corbado-go/v2/pkg/logger"
"github.com/corbado/corbado-go/v2/internal/assert"
"github.com/corbado/corbado-go/v2/pkg/generated/api"
)
func newClient(config *Config) (*api.ClientWithResponses, error) {
if err := assert.NotNil(config); err != nil {
return nil, err
}
basicAuth, err := securityprovider.NewSecurityProviderBasicAuth(config.ProjectID, config.APISecret)
if err != nil {
return nil, errors.WithStack(err)
}
extraOptions := []api.ClientOption{
api.WithRequestEditorFn(newSDKHeaderEditorFn),
api.WithRequestEditorFn(basicAuth.Intercept),
}
if config.ExtraClientOptions != nil {
extraOptions = append(extraOptions, config.ExtraClientOptions...)
}
backendServer := config.BackendAPI + "/v2"
return api.NewClientWithResponses(backendServer, extraOptions...)
}
type httpRequestDoer interface {
Do(req *http.Request) (*http.Response, error)
}
type loggingClient struct {
underlying httpRequestDoer
}
// Do implements HttpRequestDoer and executes HTTP request
func (l *loggingClient) Do(req *http.Request) (*http.Response, error) {
if err := assert.NotNil(req); err != nil {
return nil, err
}
logger.Debug("Sending request to Public API: %s %s", req.Method, req.URL.String())
if req.Body != nil {
requestBody, err := l.readBody(&req.Body)
if err != nil {
return nil, err
}
logger.Debug("Request body: %s", requestBody)
}
response, err := l.underlying.Do(req)
if err != nil {
return nil, err
}
responseBody, err := l.readBody(&response.Body)
if err != nil {
return nil, err
}
logger.Debug("Received response from Public API: %s", responseBody)
return response, nil
}
func (l *loggingClient) readBody(rc *io.ReadCloser /* nilable */) (string, error) {
if rc == nil {
return "", nil
}
var buf bytes.Buffer
tee := io.TeeReader(*rc, &buf)
body, err := io.ReadAll(tee)
if err != nil {
return "", errors.WithStack(err)
}
*rc = io.NopCloser(&buf)
return string(body), nil
}
// newLoggingClient returns new logging HTTP client
func newLoggingClient() (*loggingClient, error) {
return &loggingClient{&http.Client{}}, nil
}
// NewLoggingClientOption enhances HTTP client to log requests/responses
func NewLoggingClientOption() api.ClientOption {
return func(c *api.Client) error {
client, err := newLoggingClient()
if err != nil {
return err
}
c.Client = client
return nil
}
}
func newSDKHeaderEditorFn(_ context.Context, req *http.Request) error {
sdk := struct {
Name string `json:"name"`
SdkVersion string `json:"sdkVersion"`
LanguageVersion string `json:"languageVersion"`
}{
Name: "Go SDK",
SdkVersion: Version,
LanguageVersion: runtime.Version(),
}
marshaled, err := json.Marshal(sdk)
if err != nil {
return errors.WithStack(err)
}
req.Header.Set("X-Corbado-SDK", string(marshaled))
return nil
}