diff --git a/go.work.sum b/go.work.sum index f4634f38..85e341db 100644 --- a/go.work.sum +++ b/go.work.sum @@ -2,3 +2,4 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= diff --git a/utils/httputil/client.go b/utils/httputil/client.go index a6525d29..d9059922 100644 --- a/utils/httputil/client.go +++ b/utils/httputil/client.go @@ -17,6 +17,10 @@ import ( // StatusTooManyRequests is the HTTP status code discord sends on rate-limiting. const StatusTooManyRequests = 429 +// StatusNirnTimeout is the HTTP status code Nirn Proxy sends when the request +// times out. +const StatusNirnTimeout = 408 + // Retries is the default attempts to retry if the API returns an error before // giving up. If the value is smaller than 1, then requests will retry forever. var Retries uint = 5 @@ -230,10 +234,34 @@ func (c *Client) request( continue } - if status = r.GetStatus(); status == StatusTooManyRequests || status >= 500 { + status = r.GetStatus() + + if status == StatusNirnTimeout || status >= 500 { continue } + if status == StatusTooManyRequests { + var body = r.GetBody() + defer body.Close() + + buf := bytes.Buffer{} + buf.ReadFrom(body) + + var errBody struct { + RetryAfter float32 `json:"retry_after"` + } + + err := json.Unmarshal(buf.Bytes(), &errBody) + + if err == nil { + time.Sleep(time.Duration(errBody.RetryAfter) * time.Second) + continue + } else { + doErr = fmt.Errorf("failed to parse rate limit body: %w", err) + continue + } + } + break }