forked from sendgrid/sendgrid-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbase_interface.go
130 lines (108 loc) · 2.91 KB
/
base_interface.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
package sendgrid
import (
"errors"
"net/http"
"strconv"
"time"
"github.com/sendgrid/rest"
"github.com/sendgrid/sendgrid-go/helpers/mail"
)
// Version is this client library's current version
const (
Version = "3.7.0"
rateLimitRetry = 5
rateLimitSleep = 1100
)
type options struct {
Auth string
Endpoint string
Host string
Subuser string
}
// Client is the Twilio SendGrid Go client
type Client struct {
rest.Request
}
func (o *options) baseURL() string {
return o.Host + o.Endpoint
}
// requestNew create Request
// @return [Request] a default request object
func requestNew(options options) rest.Request {
requestHeaders := map[string]string{
"Authorization": options.Auth,
"User-Agent": "sendgrid/" + Version + ";go",
"Accept": "application/json",
}
if len(options.Subuser) != 0 {
requestHeaders["On-Behalf-Of"] = options.Subuser
}
return rest.Request{
BaseURL: options.baseURL(),
Headers: requestHeaders,
}
}
// Send sends an email through Twilio SendGrid
func (cl *Client) Send(email *mail.SGMailV3) (*rest.Response, error) {
cl.Body = mail.GetRequestBody(email)
return MakeRequest(cl.Request)
}
// DefaultClient is used if no custom HTTP client is defined
var DefaultClient = rest.DefaultClient
// API sets up the request to the Twilio SendGrid API, this is main interface.
// Please use the MakeRequest or MakeRequestAsync functions instead.
// (deprecated)
func API(request rest.Request) (*rest.Response, error) {
return MakeRequest(request)
}
// MakeRequest attempts a Twilio SendGrid request synchronously.
func MakeRequest(request rest.Request) (*rest.Response, error) {
return DefaultClient.Send(request)
}
// MakeRequestRetry a synchronous request, but retry in the event of a rate
// limited response.
func MakeRequestRetry(request rest.Request) (*rest.Response, error) {
retry := 0
var response *rest.Response
var err error
for {
response, err = MakeRequest(request)
if err != nil {
return nil, err
}
if response.StatusCode != http.StatusTooManyRequests {
return response, nil
}
if retry > rateLimitRetry {
return nil, errors.New("rate limit retry exceeded")
}
retry++
resetTime := time.Now().Add(rateLimitSleep * time.Millisecond)
reset, ok := response.Headers["X-RateLimit-Reset"]
if ok && len(reset) > 0 {
t, err := strconv.Atoi(reset[0])
if err == nil {
resetTime = time.Unix(int64(t), 0)
}
}
time.Sleep(resetTime.Sub(time.Now()))
}
}
// MakeRequestAsync attempts a request asynchronously in a new go
// routine. This function returns two channels: responses
// and errors. This function will retry in the case of a
// rate limit.
func MakeRequestAsync(request rest.Request) (chan *rest.Response, chan error) {
r := make(chan *rest.Response)
e := make(chan error)
go func() {
response, err := MakeRequestRetry(request)
if err != nil {
e <- err
}
if response != nil {
r <- response
}
}()
return r, e
}