Skip to content

Commit 80433fb

Browse files
author
vladhanzha
committed
Integrate with rate limit response headers from API
1 parent dc969f9 commit 80433fb

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

cloudconnexa/cloudconnexa.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"net/http"
10+
"strconv"
1011
"strings"
1112
"time"
1213

@@ -21,9 +22,10 @@ const (
2122
type Client struct {
2223
client *http.Client
2324

24-
BaseURL string
25-
Token string
26-
RateLimiter *rate.Limiter
25+
BaseURL string
26+
Token string
27+
ReadRateLimiter *rate.Limiter
28+
UpdateRateLimiter *rate.Limiter
2729

2830
UserAgent string
2931

@@ -115,11 +117,12 @@ func NewClient(baseURL, clientID, clientSecret string) (*Client, error) {
115117
}
116118

117119
c := &Client{
118-
client: httpClient,
119-
BaseURL: baseURL,
120-
Token: credentials.AccessToken,
121-
UserAgent: userAgent,
122-
RateLimiter: rate.NewLimiter(rate.Every(1*time.Second), 5),
120+
client: httpClient,
121+
BaseURL: baseURL,
122+
Token: credentials.AccessToken,
123+
UserAgent: userAgent,
124+
ReadRateLimiter: rate.NewLimiter(rate.Every(1*time.Second), 1),
125+
UpdateRateLimiter: rate.NewLimiter(rate.Every(4*time.Second), 1),
123126
}
124127
c.common.client = c
125128
c.HostConnectors = (*HostConnectorsService)(&c.common)
@@ -158,7 +161,13 @@ func (c *Client) setCommonHeaders(req *http.Request) {
158161
// DoRequest executes an HTTP request with authentication and rate limiting.
159162
// It automatically adds the Bearer token, sets headers, and handles errors.
160163
func (c *Client) DoRequest(req *http.Request) ([]byte, error) {
161-
err := c.RateLimiter.Wait(context.Background())
164+
var rateLimiter *rate.Limiter
165+
if req.Method == "GET" {
166+
rateLimiter = c.ReadRateLimiter
167+
} else {
168+
rateLimiter = c.UpdateRateLimiter
169+
}
170+
err := rateLimiter.Wait(context.Background())
162171
if err != nil {
163172
return nil, err
164173
}
@@ -185,6 +194,30 @@ func (c *Client) DoRequest(req *http.Request) ([]byte, error) {
185194
return nil, &ErrClientResponse{status: res.StatusCode, body: string(body)}
186195
}
187196

197+
rateHeader := res.Header.Get("X-RateLimit-Replenish-Rate")
198+
timeHeader := res.Header.Get("X-RateLimit-Replenish-Time")
199+
remainingHeader := res.Header.Get("X-RateLimit-Remaining")
200+
201+
if rateHeader != "" && timeHeader != "" && remainingHeader != "" {
202+
rateValue, err := strconv.Atoi(rateHeader)
203+
if err != nil {
204+
return nil, err
205+
}
206+
timeValue, err := strconv.Atoi(timeHeader)
207+
if err != nil {
208+
return nil, err
209+
}
210+
remainingValue, err := strconv.Atoi(remainingHeader)
211+
if err != nil {
212+
return nil, err
213+
}
214+
if remainingValue <= 0 {
215+
remainingValue = 1
216+
}
217+
rateLimiter.SetLimit(rate.Every(time.Duration(timeValue * 1_000_000_000 / rateValue)))
218+
rateLimiter.SetBurst(remainingValue)
219+
}
220+
188221
return body, nil
189222
}
190223

0 commit comments

Comments
 (0)