mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 20:01:17 +00:00
[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:
parent
58b2f17885
commit
2c9a0adfa0
2 changed files with 59 additions and 4 deletions
47
twitch/http.go
Normal file
47
twitch/http.go
Normal 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
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue