ProbeServerWithProxy is the hot-path variant for callers that already know the effective proxy and want probe traffic to match the eventual download path without re-reading settings from disk.
(ctx context.Context, rawurl string, filenameHint string, headers map[string]string, runCfg *types.RuntimeConfig)
| 75 | // the effective proxy and want probe traffic to match the eventual download path |
| 76 | // without re-reading settings from disk. |
| 77 | func ProbeServerWithProxy(ctx context.Context, rawurl string, filenameHint string, headers map[string]string, runCfg *types.RuntimeConfig) (*ProbeResult, error) { |
| 78 | utils.Debug("Probing server: %s", rawurl) |
| 79 | |
| 80 | // Embed custom headers in context so CheckRedirect can use them |
| 81 | if headers != nil { |
| 82 | ctx = context.WithValue(ctx, probeHeadersContextKey{}, headers) |
| 83 | } |
| 84 | |
| 85 | var resp *http.Response |
| 86 | |
| 87 | var proxyURL, customDNS string |
| 88 | if runCfg != nil { |
| 89 | proxyURL = runCfg.ProxyURL |
| 90 | customDNS = runCfg.CustomDNS |
| 91 | } |
| 92 | |
| 93 | // Standardize on PoolMaxConnsPerHost for probes to match the eventual download path |
| 94 | transport := engine.DefaultNetworkPool.AcquireTransport(proxyURL, customDNS, types.PoolMaxConnsPerHost) |
| 95 | defer engine.DefaultNetworkPool.ReleaseTransport(transport) |
| 96 | |
| 97 | client := &http.Client{ |
| 98 | Transport: transport, |
| 99 | CheckRedirect: func(req *http.Request, via []*http.Request) error { |
| 100 | if len(via) >= 10 { |
| 101 | return fmt.Errorf("stopped after 10 redirects") |
| 102 | } |
| 103 | if len(via) > 0 { |
| 104 | copyProbeRedirectHeaders(req, via[0]) |
| 105 | } |
| 106 | |
| 107 | // Re-apply custom explicitly provided headers on cross-origin redirects |
| 108 | if customHeaders, ok := req.Context().Value(probeHeadersContextKey{}).(map[string]string); ok { |
| 109 | for k, v := range customHeaders { |
| 110 | if !strings.EqualFold(k, "Range") { |
| 111 | req.Header.Set(k, v) |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | return nil |
| 116 | }, |
| 117 | } |
| 118 | |
| 119 | // Sequentialize probes to the same host to prevent rate limiting (e.g., Google Drive) |
| 120 | hostLock := getProbeHostLock(rawurl) |
| 121 | hostLock.Lock() |
| 122 | defer hostLock.Unlock() |
| 123 | |
| 124 | var err error |
| 125 | var finalCancel context.CancelFunc |
| 126 | |
| 127 | for attempt := range 3 { |
| 128 | if ctx.Err() != nil { |
| 129 | if err == nil { |
| 130 | err = fmt.Errorf("probe request aborted: %w", ctx.Err()) |
| 131 | } |
| 132 | break |
| 133 | } |
| 134 |