Fix retries
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
|
|
||||||
attempt := 0
|
attempt := 0
|
||||||
var origBody []byte
|
var origBody []byte
|
||||||
if req.Method == "POST" {
|
if req.Method == "POST" || req.Method == "PUT" || req.Method == "PATCH" {
|
||||||
origBody, _ = io.ReadAll(req.Body)
|
origBody, _ = io.ReadAll(req.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +178,12 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
if resp != nil && resp.Body != nil {
|
if resp != nil && resp.Body != nil {
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
}
|
}
|
||||||
r.replaceHostIfNeeded(req) // needed for ipv6
|
|
||||||
|
r.replaceWithIPv6Host(req) // needed for ipv6
|
||||||
|
|
||||||
resp, err = r.client.Do(req)
|
resp, err = r.client.Do(req)
|
||||||
|
|
||||||
|
// http 4xx and 5xx errors
|
||||||
if resp != nil && resp.StatusCode/100 >= 4 {
|
if resp != nil && resp.StatusCode/100 >= 4 {
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
if body != nil {
|
if body != nil {
|
||||||
@@ -192,6 +195,7 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
incr := r.shouldRetry(resp, reqHasRangeHeader, err, r.cfg.GetRateLimitSleepSecs())
|
incr := r.shouldRetry(resp, reqHasRangeHeader, err, r.cfg.GetRateLimitSleepSecs())
|
||||||
if incr > 0 {
|
if incr > 0 {
|
||||||
attempt += incr
|
attempt += incr
|
||||||
@@ -213,34 +217,30 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HTTPClient) replaceHostIfNeeded(req *http.Request) {
|
func (r *HTTPClient) replaceWithIPv6Host(req *http.Request) {
|
||||||
if strings.HasSuffix(req.Host, "download.real-debrid.cloud") || !r.supportIPv6 || !r.cfg.ShouldForceIPv6() {
|
// don't replace host if IPv6 is not supported or not forced
|
||||||
|
if !r.supportIPv6 || !r.cfg.ShouldForceIPv6() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// get subdomain of req.Host
|
// this host should be replaced
|
||||||
subdomain := strings.Split(req.Host, ".")[0]
|
if !strings.HasSuffix(req.Host, ".download.real-debrid.com") {
|
||||||
// check if subdomain is numeric
|
return
|
||||||
_, err := strconv.Atoi(subdomain)
|
|
||||||
if err == nil {
|
|
||||||
// subdomain is numeric, replace it with .cloud
|
|
||||||
req.Host = strings.Replace(req.Host, ".com", ".cloud", 1)
|
|
||||||
req.URL.Host = req.Host
|
|
||||||
}
|
}
|
||||||
// check if host is in the list of IPv6 hosts
|
|
||||||
found := false
|
req.Host = strings.Replace(req.Host, ".com", ".cloud", 1)
|
||||||
|
req.URL.Host = req.Host
|
||||||
|
// check if this host is in the list of IPv6 hosts
|
||||||
for _, h := range r.ipv6Hosts {
|
for _, h := range r.ipv6Hosts {
|
||||||
if h == req.Host {
|
if h == req.Host {
|
||||||
found = true
|
return
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found && !r.CanFetchFirstByte(req.URL.String()) {
|
|
||||||
req.Host = r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
|
// if not then just assign a random IPv6 host
|
||||||
r.log.Debugf("Host %s is not a valid IPv6 host, assigning a random IPv6 host: %s", req.URL.Host, req.Host)
|
req.Host = r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
|
||||||
req.URL.Host = req.Host
|
req.URL.Host = req.Host
|
||||||
} else {
|
r.log.Debugf("Host %s is not a valid IPv6 host, assigning a random IPv6 host: %s", req.URL.Host, req.Host)
|
||||||
r.ipv6Hosts = append(r.ipv6Hosts, req.Host)
|
// if !found && !r.CanFetchFirstByte(req.URL.String()) {
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HTTPClient) proxyDialer(proxyURL *url.URL) (proxy.Dialer, error) {
|
func (r *HTTPClient) proxyDialer(proxyURL *url.URL) (proxy.Dialer, error) {
|
||||||
@@ -287,9 +287,19 @@ func (r *HTTPClient) shouldRetry(resp *http.Response, reqHasRangeHeader bool, er
|
|||||||
}
|
}
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
if resp.StatusCode == 429 {
|
if resp.StatusCode == 429 {
|
||||||
|
// Too many requests: retry infinitely
|
||||||
time.Sleep(time.Duration(rateLimitSleep) * time.Second)
|
time.Sleep(time.Duration(rateLimitSleep) * time.Second)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if resp.StatusCode/100 == 4 {
|
||||||
|
// other client errors: retry
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if resp.StatusCode/100 == 5 {
|
||||||
|
// server errors: don't retry
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// if the request has a Range header but the server doesn't respond with a Content-Range header
|
||||||
if resp.StatusCode/100 == 2 && resp.Header.Get("Content-Range") == "" && reqHasRangeHeader {
|
if resp.StatusCode/100 == 2 && resp.Header.Get("Content-Range") == "" && reqHasRangeHeader {
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user