Replace host on every retry

This commit is contained in:
Ben Sarmiento
2024-01-26 18:33:15 +01:00
parent 8d4cdbbd1f
commit 1ff8cf2dfc

View File

@@ -10,6 +10,7 @@ import (
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
@@ -25,6 +26,7 @@ import (
type HTTPClient struct {
client *http.Client
maxRetries int
timeoutSecs int
backoff func(attempt int) time.Duration
getRetryIncr func(resp *http.Response, reqHasRangeHeader bool, err error) int
bearerToken string
@@ -54,6 +56,7 @@ func NewHTTPClient(token string, maxRetries int, timeoutSecs int, ensureIPv6Host
bearerToken: token,
client: &http.Client{},
maxRetries: maxRetries,
timeoutSecs: timeoutSecs,
backoff: func(attempt int) time.Duration {
maxDuration := 60
backoff := int(math.Pow(2, float64(attempt)))
@@ -182,7 +185,6 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
if r.bearerToken != "" {
req.Header.Set("Authorization", "Bearer "+r.bearerToken)
}
r.replaceHostIfNeeded(req)
// check if Range header is set
reqHasRangeHeader := req.Header.Get("Range") != "" && req.Header.Get("Range") != "bytes=0-"
@@ -190,7 +192,21 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
var err error
attempt := 0
for {
r.replaceHostIfNeeded(req)
ctx, cancel := context.WithTimeout(req.Context(), time.Duration(r.timeoutSecs)*time.Second)
defer cancel()
req = req.WithContext(ctx)
resp, err = r.client.Do(req)
select {
case <-ctx.Done():
if ctx.Err() == context.DeadlineExceeded {
err = fmt.Errorf("request timed out after %d seconds", r.timeoutSecs)
}
default:
}
if resp != nil && (resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent) {
body, _ := io.ReadAll(resp.Body)
if body != nil {
@@ -221,19 +237,18 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
}
func (r *HTTPClient) replaceHostIfNeeded(req *http.Request) {
if !r.ensureIPv6Host || !r.cfg.ShouldForceIPv6() {
if !r.ensureIPv6Host && !r.cfg.ShouldForceIPv6() || !strings.HasSuffix(req.URL.Host, "real-debrid.com") {
return
}
// if no hosts are found, just replace .com with .cloud
if len(r.ipv6Hosts) == 0 {
host := req.URL.Host
if strings.HasSuffix(host, ".com") {
newHost := strings.Replace(host, ".com", ".cloud", 1)
req.Host = newHost
req.URL.Host = newHost
// get subdomain of req.URL.Host
subdomain := strings.Split(req.URL.Host, ".")[0]
// check if subdomain is numeric
_, err := strconv.Atoi(subdomain)
if err == nil {
// subdomain is numeric, replace it with .cloud
req.URL.Host = strings.Replace(req.URL.Host, ".com", ".cloud", 1)
}
}
// if hosts are found, ensure the host is an IPv6 host
// check if host is in the list of IPv6 hosts
found := false
for _, h := range r.ipv6Hosts {
if h == req.URL.Host {
@@ -241,12 +256,9 @@ func (r *HTTPClient) replaceHostIfNeeded(req *http.Request) {
break
}
}
// if host is not an IPv6 host, replace it with a random IPv6 host
if !found {
r.log.Warnf("Host %s is not an IPv6 host, replacing with a random IPv6 host (ensure you have preferred_hosts properly set in your config.yml, if unset, run `zurg network-test -t ipv6`)", req.URL.Host)
newHost := r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
req.Host = newHost
req.URL.Host = newHost
// random IPv6 host
req.URL.Host = r.ipv6Hosts[rand.Intn(len(r.ipv6Hosts))]
}
}