1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-01-20 19:47:12 +00:00

Added HTTP retry, fixed async JSON body corrupting

This commit is contained in:
diamondburned (Forefront) 2020-01-20 11:28:55 -08:00
parent ff0bc7b98b
commit 73f5cdec9e
6 changed files with 41 additions and 28 deletions

View file

@ -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 != "" {

1
go.mod
View file

@ -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

1
go.sum
View file

@ -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=

View file

@ -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,

View file

@ -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
}

View file

@ -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
}
}