mirror of
https://github.com/rclone/rclone.git
synced 2024-12-25 13:33:40 +08:00
be9ee1d138
Before this change the 206 responses from putio Range requests were being returned as errors. This change checks for 200 and 206 in the GET response now.
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package putio
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/putdotio/go-putio/putio"
|
|
"github.com/rclone/rclone/fs/fserrors"
|
|
"github.com/rclone/rclone/lib/pacer"
|
|
)
|
|
|
|
func checkStatusCode(resp *http.Response, expected ...int) error {
|
|
for _, code := range expected {
|
|
if resp.StatusCode == code {
|
|
return nil
|
|
}
|
|
}
|
|
return &statusCodeError{response: resp}
|
|
}
|
|
|
|
type statusCodeError struct {
|
|
response *http.Response
|
|
}
|
|
|
|
func (e *statusCodeError) Error() string {
|
|
return fmt.Sprintf("unexpected status code (%d) response while doing %s to %s", e.response.StatusCode, e.response.Request.Method, e.response.Request.URL.String())
|
|
}
|
|
|
|
// This method is called from fserrors.ShouldRetry() to determine if an error should be retried.
|
|
// Some errors (e.g. 429 Too Many Requests) are handled before this step, so they are not included here.
|
|
func (e *statusCodeError) Temporary() bool {
|
|
return e.response.StatusCode >= 500
|
|
}
|
|
|
|
// shouldRetry returns a boolean as to whether this err deserves to be
|
|
// retried. It returns the err as a convenience
|
|
func shouldRetry(ctx context.Context, err error) (bool, error) {
|
|
if fserrors.ContextError(ctx, &err) {
|
|
return false, err
|
|
}
|
|
if err == nil {
|
|
return false, nil
|
|
}
|
|
if perr, ok := err.(*putio.ErrorResponse); ok {
|
|
err = &statusCodeError{response: perr.Response}
|
|
}
|
|
if scerr, ok := err.(*statusCodeError); ok && scerr.response.StatusCode == 429 {
|
|
delay := defaultRateLimitSleep
|
|
header := scerr.response.Header.Get("x-ratelimit-reset")
|
|
if header != "" {
|
|
if resetTime, cerr := strconv.ParseInt(header, 10, 64); cerr == nil {
|
|
delay = time.Until(time.Unix(resetTime+1, 0))
|
|
}
|
|
}
|
|
return true, pacer.RetryAfterError(scerr, delay)
|
|
}
|
|
if fserrors.ShouldRetry(err) {
|
|
return true, err
|
|
}
|
|
return false, err
|
|
}
|