[core] Delete refresh token only for HTTP errors, not on connection issues

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2022-03-18 22:09:56 +01:00
parent 58b2f17885
commit 2c9a0adfa0
Signed by: luzifer
GPG key ID: 0066F03ED215AD7D
2 changed files with 59 additions and 4 deletions

47
twitch/http.go Normal file
View file

@ -0,0 +1,47 @@
package twitch
import (
"fmt"
)
type httpError struct {
body []byte
code int
err error
}
var errAnyHTTPError = newHTTPError(0, nil, nil)
func newHTTPError(status int, body []byte, wrappedErr error) httpError {
return httpError{
body: body,
code: status,
err: wrappedErr,
}
}
func (h httpError) Error() string {
selfE := fmt.Sprintf("unexpected status %d", h.code)
if h.body != nil {
selfE = fmt.Sprintf("%s (%s)", selfE, h.body)
}
if h.err == nil {
return selfE
}
return fmt.Sprintf("%s: %s", selfE, h.err)
}
func (h httpError) Is(target error) bool {
ht, ok := target.(httpError)
if !ok {
return false
}
return ht.code == 0 || ht.code == h.code
}
func (h httpError) Unwrap() error {
return h.err
}

View file

@ -529,22 +529,30 @@ func (c *Client) RefreshToken() error {
var resp OAuthTokenResponse var resp OAuthTokenResponse
if err := c.request(clientRequestOpts{ err := c.request(clientRequestOpts{
AuthType: authTypeUnauthorized, AuthType: authTypeUnauthorized,
Context: context.Background(), Context: context.Background(),
Method: http.MethodPost, Method: http.MethodPost,
OKStatus: http.StatusOK, OKStatus: http.StatusOK,
Out: &resp, Out: &resp,
URL: fmt.Sprintf("https://id.twitch.tv/oauth2/token?%s", params.Encode()), URL: fmt.Sprintf("https://id.twitch.tv/oauth2/token?%s", params.Encode()),
}); err != nil { })
switch {
case err == nil:
// That's fine, just continue
case errors.Is(err, errAnyHTTPError):
// Retried refresh failed, wipe tokens // Retried refresh failed, wipe tokens
log.WithError(err).Warning("resetting tokens after refresh-failure")
c.UpdateToken("", "") c.UpdateToken("", "")
if c.tokenUpdateHook != nil { if c.tokenUpdateHook != nil {
if herr := c.tokenUpdateHook("", ""); herr != nil { if herr := c.tokenUpdateHook("", ""); herr != nil {
log.WithError(err).Error("Unable to store token wipe after refresh failure") log.WithError(err).Error("Unable to store token wipe after refresh failure")
} }
} }
return errors.Wrap(err, "executing request")
default:
return errors.Wrap(err, "executing request") return errors.Wrap(err, "executing request")
} }
@ -793,9 +801,9 @@ func (c *Client) request(opts clientRequestOpts) error {
if opts.OKStatus != 0 && resp.StatusCode != opts.OKStatus { if opts.OKStatus != 0 && resp.StatusCode != opts.OKStatus {
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
return errors.Wrapf(err, "unexpected status %d and cannot read body", resp.StatusCode) return newHTTPError(resp.StatusCode, nil, err)
} }
return errors.Errorf("unexpected status %d: %s", resp.StatusCode, body) return newHTTPError(resp.StatusCode, body, nil)
} }
if opts.Out == nil { if opts.Out == nil {