mirror of
https://github.com/diamondburned/arikawa.git
synced 2025-01-21 03:57:26 +00:00
Added HTTP retry, fixed async JSON body corrupting
This commit is contained in:
parent
ff0bc7b98b
commit
73f5cdec9e
|
@ -171,22 +171,13 @@ func (l *Limiter) Release(path string, headers http.Header) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
case reset != "":
|
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)
|
unix, err := strconv.ParseFloat(reset, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Invalid reset "+reset)
|
return errors.Wrap(err, "Invalid reset "+reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
reset := time.Unix(0, int64(unix*float64(time.Second)))
|
b.reset = time.Unix(0, int64(unix*float64(time.Second))).
|
||||||
delta := reset.Sub(t) + ExtraDelay
|
Add(ExtraDelay)
|
||||||
|
|
||||||
b.reset = time.Now().Add(delta)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if remaining != "" {
|
if remaining != "" {
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bwmarrin/discordgo v0.20.2
|
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/schema v1.1.0
|
||||||
github.com/gorilla/websocket v1.4.1
|
github.com/gorilla/websocket v1.4.1
|
||||||
github.com/k0kubun/pp v3.0.1+incompatible
|
github.com/k0kubun/pp v3.0.1+incompatible
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -1,6 +1,7 @@
|
||||||
github.com/bwmarrin/discordgo v0.20.2 h1:nA7jiTtqUA9lT93WL2jPjUp8ZTEInRujBdx1C9gkr20=
|
github.com/bwmarrin/discordgo v0.20.2 h1:nA7jiTtqUA9lT93WL2jPjUp8ZTEInRujBdx1C9gkr20=
|
||||||
github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
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.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/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 h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
@ -14,10 +13,16 @@ import (
|
||||||
"github.com/diamondburned/arikawa/internal/json"
|
"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 {
|
type Client struct {
|
||||||
http.Client
|
http.Client
|
||||||
json.Driver
|
json.Driver
|
||||||
SchemaEncoder
|
SchemaEncoder
|
||||||
|
|
||||||
|
Retries uint
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultClient = NewClient()
|
var DefaultClient = NewClient()
|
||||||
|
@ -29,6 +34,7 @@ func NewClient() Client {
|
||||||
},
|
},
|
||||||
Driver: json.Default{},
|
Driver: json.Default{},
|
||||||
SchemaEncoder: &DefaultSchema{},
|
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 {
|
if err != nil {
|
||||||
log.Println("Do error", url, err)
|
|
||||||
return nil, RequestError{err}
|
return nil, RequestError{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Response received, but with a failure status code:
|
||||||
if r.StatusCode < 200 || r.StatusCode > 299 {
|
if r.StatusCode < 200 || r.StatusCode > 299 {
|
||||||
httpErr := &HTTPError{
|
httpErr := &HTTPError{
|
||||||
Status: r.StatusCode,
|
Status: r.StatusCode,
|
||||||
|
|
|
@ -5,16 +5,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TransportWrapper struct {
|
type TransportWrapper struct {
|
||||||
http.RoundTripper
|
Default http.RoundTripper
|
||||||
|
|
||||||
Pre func(*http.Request) error
|
Pre func(*http.Request) error
|
||||||
Post func(*http.Response) error
|
Post func(*http.Response) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ http.RoundTripper = (*TransportWrapper)(nil)
|
||||||
|
|
||||||
func NewTransportWrapper() *TransportWrapper {
|
func NewTransportWrapper() *TransportWrapper {
|
||||||
return &TransportWrapper{
|
return &TransportWrapper{
|
||||||
RoundTripper: http.DefaultTransport,
|
Default: http.DefaultTransport,
|
||||||
|
|
||||||
Pre: func(*http.Request) error { return nil },
|
Pre: func(*http.Request) error { return nil },
|
||||||
Post: func(*http.Response) 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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := c.RoundTripper.RoundTrip(req)
|
r, err := c.Default.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package httputil
|
package httputil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/diamondburned/arikawa/internal/json"
|
"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 err error
|
||||||
|
var rp, wp = io.Pipe()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err = json.EncodeStream(&buf, v)
|
err = json.EncodeStream(wp, v)
|
||||||
|
wp.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return func(r *http.Request) error {
|
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.Header.Set("Content-Type", "application/json")
|
||||||
r.Body = ioutil.NopCloser(&buf)
|
r.Body = rp
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue