Fix retries

This commit is contained in:
Ben Sarmiento
2024-04-28 00:16:55 +02:00
parent dd65d07037
commit eb04ed378b

View File

@@ -11,7 +11,6 @@ import (
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
@@ -168,7 +167,7 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
attempt := 0
var origBody []byte
if req.Method == "POST" {
if req.Method == "POST" || req.Method == "PUT" || req.Method == "PATCH" {
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 {
resp.Body.Close()
}
r.replaceHostIfNeeded(req) // needed for ipv6
r.replaceWithIPv6Host(req) // needed for ipv6
resp, err = r.client.Do(req)
// http 4xx and 5xx errors
if resp != nil && resp.StatusCode/100 >= 4 {
body, _ := io.ReadAll(resp.Body)
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())
if incr > 0 {
attempt += incr
@@ -213,34 +217,30 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
return resp, err
}
func (r *HTTPClient) replaceHostIfNeeded(req *http.Request) {
if strings.HasSuffix(req.Host, "download.real-debrid.cloud") || !r.supportIPv6 || !r.cfg.ShouldForceIPv6() {
func (r *HTTPClient) replaceWithIPv6Host(req *http.Request) {
// don't replace host if IPv6 is not supported or not forced
if !r.supportIPv6 || !r.cfg.ShouldForceIPv6() {
return
}
// get subdomain of req.Host
subdomain := strings.Split(req.Host, ".")[0]
// check if subdomain is numeric
_, 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
// this host should be replaced
if !strings.HasSuffix(req.Host, ".download.real-debrid.com") {
return
}
// 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 {
if h == req.Host {
found = true
break
return
}
}
if !found && !r.CanFetchFirstByte(req.URL.String()) {
req.Host = r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
r.log.Debugf("Host %s is not a valid IPv6 host, assigning a random IPv6 host: %s", req.URL.Host, req.Host)
req.URL.Host = req.Host
} else {
r.ipv6Hosts = append(r.ipv6Hosts, req.Host)
}
// if not then just assign a random IPv6 host
req.Host = r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
req.URL.Host = req.Host
r.log.Debugf("Host %s is not a valid IPv6 host, assigning a random IPv6 host: %s", req.URL.Host, req.Host)
// if !found && !r.CanFetchFirstByte(req.URL.String()) {
}
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.StatusCode == 429 {
// Too many requests: retry infinitely
time.Sleep(time.Duration(rateLimitSleep) * time.Second)
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 {
time.Sleep(10 * time.Millisecond)
return 0