77 "fmt"
88 "io"
99 "net/http"
10+ "strconv"
1011 "strings"
1112 "time"
1213
@@ -21,9 +22,10 @@ const (
2122type 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.
160163func (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