diff --git a/api/rate/rate.go b/api/rate/rate.go index 79dbdf3..3a7d0d2 100644 --- a/api/rate/rate.go +++ b/api/rate/rate.go @@ -171,22 +171,13 @@ func (l *Limiter) Release(path string, headers http.Header) error { } case reset != "": - date := headers.Get("Date") - - t, err := http.ParseTime(date) - if err != nil { - return errors.Wrap(err, "Invalid date "+date) - } - unix, err := strconv.ParseFloat(reset, 64) if err != nil { return errors.Wrap(err, "Invalid reset "+reset) } - reset := time.Unix(0, int64(unix*float64(time.Second))) - delta := reset.Sub(t) + ExtraDelay - - b.reset = time.Now().Add(delta) + b.reset = time.Unix(0, int64(unix*float64(time.Second))). + Add(ExtraDelay) } if remaining != "" { diff --git a/go.mod b/go.mod index a5cc4b7..2046973 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( github.com/bwmarrin/discordgo v0.20.2 + github.com/davecgh/go-spew v1.1.1 github.com/gorilla/schema v1.1.0 github.com/gorilla/websocket v1.4.1 github.com/k0kubun/pp v3.0.1+incompatible diff --git a/go.sum b/go.sum index cc42101..58764a2 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/bwmarrin/discordgo v0.20.2 h1:nA7jiTtqUA9lT93WL2jPjUp8ZTEInRujBdx1C9gkr20= github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= diff --git a/internal/httputil/client.go b/internal/httputil/client.go index 3c636e5..bd9460c 100644 --- a/internal/httputil/client.go +++ b/internal/httputil/client.go @@ -6,7 +6,6 @@ import ( "context" "io" "io/ioutil" - "log" "mime/multipart" "net/http" "time" @@ -14,10 +13,16 @@ import ( "github.com/diamondburned/arikawa/internal/json" ) +// Retries is the default attempts to retry if the API returns an error before +// giving up. +var Retries uint = 5 + type Client struct { http.Client json.Driver SchemaEncoder + + Retries uint } var DefaultClient = NewClient() @@ -29,6 +34,7 @@ func NewClient() Client { }, Driver: json.Default{}, SchemaEncoder: &DefaultSchema{}, + Retries: Retries, } } @@ -97,12 +103,27 @@ func (c *Client) RequestCtx(ctx context.Context, } } - r, err := c.Client.Do(req) + var r *http.Response + + for i := uint(0); i < c.Retries; i++ { + r, err = c.Client.Do(req) + if err != nil { + continue + } + + if r.StatusCode < 200 || r.StatusCode > 299 { + continue + } + + break + } + + // If all retries failed: if err != nil { - log.Println("Do error", url, err) return nil, RequestError{err} } + // Response received, but with a failure status code: if r.StatusCode < 200 || r.StatusCode > 299 { httpErr := &HTTPError{ Status: r.StatusCode, diff --git a/internal/httputil/http.go b/internal/httputil/http.go index bcd03ba..f407cfe 100644 --- a/internal/httputil/http.go +++ b/internal/httputil/http.go @@ -5,18 +5,18 @@ import ( ) type TransportWrapper struct { - http.RoundTripper - - Pre func(*http.Request) error - Post func(*http.Response) error + Default http.RoundTripper + Pre func(*http.Request) error + Post func(*http.Response) error } +var _ http.RoundTripper = (*TransportWrapper)(nil) + func NewTransportWrapper() *TransportWrapper { return &TransportWrapper{ - RoundTripper: http.DefaultTransport, - - Pre: func(*http.Request) error { return nil }, - Post: func(*http.Response) error { return nil }, + Default: http.DefaultTransport, + Pre: func(*http.Request) error { return nil }, + Post: func(*http.Response) error { return nil }, } } @@ -25,7 +25,7 @@ func (c *TransportWrapper) RoundTrip(req *http.Request) (*http.Response, error) return nil, err } - r, err := c.RoundTripper.RoundTrip(req) + r, err := c.Default.RoundTrip(req) if err != nil { return nil, err } diff --git a/internal/httputil/options.go b/internal/httputil/options.go index e612fe9..bb86ba8 100644 --- a/internal/httputil/options.go +++ b/internal/httputil/options.go @@ -1,9 +1,7 @@ package httputil import ( - "bytes" "io" - "io/ioutil" "net/http" "github.com/diamondburned/arikawa/internal/json" @@ -62,11 +60,12 @@ func WithJSONBody(json json.Driver, v interface{}) RequestOption { } } - var buf bytes.Buffer var err error + var rp, wp = io.Pipe() go func() { - err = json.EncodeStream(&buf, v) + err = json.EncodeStream(wp, v) + wp.Close() }() return func(r *http.Request) error { @@ -75,7 +74,7 @@ func WithJSONBody(json json.Driver, v interface{}) RequestOption { } r.Header.Set("Content-Type", "application/json") - r.Body = ioutil.NopCloser(&buf) + r.Body = rp return nil } }