-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
124 lines (110 loc) · 2.48 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
package workflow
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
)
type Options struct {
// Url is the address of the QStash.
// If not provided, the default production URL is used.
Url string
// Token is the authentication token for the QStash.
Token string
// Client is the HTTP client used to make requests to the QStash server.
// If not provided, a default HTTP client is used.
Client *http.Client
}
func (o *Options) validate() error {
if o.Token == "" {
return fmt.Errorf("token is empty")
}
return nil
}
type Client struct {
url string
token string
client *http.Client
}
func newClient(opts Options) (*Client, error) {
if err := opts.validate(); err != nil {
return nil, err
}
if opts.Url == "" {
opts.Url = productionUrl
} else if !strings.HasSuffix(opts.Url, "/") {
opts.Url += "/"
}
if opts.Client == nil {
opts.Client = http.DefaultClient
}
return &Client{
url: opts.Url,
token: fmt.Sprintf("Bearer %s", opts.Token),
client: opts.Client,
}, nil
}
func NewClientWith(opts Options) (*Client, error) {
return newClient(opts)
}
func NewClient(token string) (*Client, error) {
return newClient(Options{
Token: token,
})
}
func NewClientWithEnv() (*Client, error) {
return newClient(Options{
Url: os.Getenv("QSTASH_URL"),
Token: os.Getenv("QSTASH_TOKEN"),
})
}
type requestOptions struct {
method string
path []string
body []byte
header http.Header
params url.Values
}
func (c *Client) do(opts requestOptions) ([]byte, int, error) {
request, err := http.NewRequest(opts.method, fmt.Sprintf("%s%s", c.url, strings.Join(opts.path, "/")), bytes.NewReader(opts.body))
if err != nil {
return nil, -1, err
}
if opts.params != nil {
request.URL.RawQuery = opts.params.Encode()
}
header := opts.header
if header == nil {
header = http.Header{}
}
header.Set(authorizationHeader, c.token)
request.Header = header
res, err := c.client.Do(request)
if err != nil {
return nil, -1, err
}
response, err := io.ReadAll(res.Body)
if err != nil {
return nil, -1, err
}
if res.StatusCode >= http.StatusMultipleChoices {
var rErr restError
if err = json.Unmarshal(response, &rErr); err != nil {
return response, res.StatusCode, err
}
return response, res.StatusCode, errors.New(rErr.Error)
}
return response, res.StatusCode, nil
}
func parse[T any](data []byte) (t T, err error) {
err = json.Unmarshal(data, &t)
return
}
type restError struct {
Error string `json:"error"`
}