transport.go raw

   1  package namecheap
   2  
   3  import (
   4  	"net/http"
   5  	"net/url"
   6  	"strings"
   7  	"sync"
   8  
   9  	"github.com/go-acme/lego/v4/platform/config/env"
  10  	"golang.org/x/net/http/httpproxy"
  11  )
  12  
  13  const (
  14  	envHTTPProxy       = "HTTP_PROXY"
  15  	envHTTPProxyLower  = "http_proxy"
  16  	envHTTPSProxy      = "HTTPS_PROXY"
  17  	envHTTPSProxyLower = "https_proxy"
  18  	envNoProxy         = "NO_PROXY"
  19  	envNoProxyLower    = "no_proxy"
  20  	envRequestMethod   = "REQUEST_METHOD"
  21  )
  22  
  23  // Allows lazy loading of the proxy.
  24  var (
  25  	envProxyOnce      sync.Once
  26  	envProxyFuncValue func(*url.URL) (*url.URL, error)
  27  )
  28  
  29  func defaultTransport(namespace string) http.RoundTripper {
  30  	tr, ok := http.DefaultTransport.(*http.Transport)
  31  	if !ok {
  32  		return nil
  33  	}
  34  
  35  	clone := tr.Clone()
  36  	clone.Proxy = proxyFromEnvironment(namespace)
  37  
  38  	return clone
  39  }
  40  
  41  // Inspired by:
  42  // - https://pkg.go.dev/net/http#ProxyFromEnvironment
  43  // - https://pkg.go.dev/golang.org/x/net/http/httpproxy#FromEnvironment
  44  func envProxyFunc(namespace string) func(*url.URL) (*url.URL, error) {
  45  	envProxyOnce.Do(func() {
  46  		cfg := &httpproxy.Config{
  47  			HTTPProxy:  getEnv(namespace, envHTTPProxy, envHTTPProxyLower),
  48  			HTTPSProxy: getEnv(namespace, envHTTPSProxy, envHTTPSProxyLower),
  49  			NoProxy:    getEnv(namespace, envNoProxy, envNoProxyLower),
  50  			CGI:        env.GetOneWithFallback(namespace+envRequestMethod, "", env.ParseString, envRequestMethod) != "",
  51  		}
  52  
  53  		envProxyFuncValue = cfg.ProxyFunc()
  54  	})
  55  
  56  	return envProxyFuncValue
  57  }
  58  
  59  // Inspired by:
  60  // - https://pkg.go.dev/net/http#ProxyFromEnvironment
  61  // - https://pkg.go.dev/golang.org/x/net/http/httpproxy#FromEnvironment
  62  func proxyFromEnvironment(namespace string) func(req *http.Request) (*url.URL, error) {
  63  	return func(req *http.Request) (*url.URL, error) {
  64  		return envProxyFunc(namespace)(req.URL)
  65  	}
  66  }
  67  
  68  func getEnv(namespace, baseEnvName, baseEnvNameLower string) string {
  69  	return env.GetOneWithFallback(namespace+baseEnvName, "", env.ParseString,
  70  		strings.ToLower(namespace)+baseEnvNameLower, baseEnvName, baseEnvNameLower)
  71  }
  72