package agentproxy import ( "encoding/base64" "net/http" "strconv" "time" "github.com/bytedance/sonic" route "github.com/yusing/godoxy/internal/route/types" ) type Config struct { Scheme string `json:"scheme,omitempty"` Host string `json:"host,omitempty"` // host or host:port route.HTTPConfig } func ConfigFromHeaders(h http.Header) (Config, error) { cfg, err := proxyConfigFromHeaders(h) if cfg.Host == "" || err != nil { cfg = proxyConfigFromHeadersLegacy(h) } return cfg, nil } func proxyConfigFromHeadersLegacy(h http.Header) (cfg Config) { cfg.Host = h.Get(HeaderXProxyHost) isHTTPS, _ := strconv.ParseBool(h.Get(HeaderXProxyHTTPS)) cfg.NoTLSVerify, _ = strconv.ParseBool(h.Get(HeaderXProxySkipTLSVerify)) responseHeaderTimeout, err := strconv.Atoi(h.Get(HeaderXProxyResponseHeaderTimeout)) if err != nil { responseHeaderTimeout = 0 } cfg.ResponseHeaderTimeout = time.Duration(responseHeaderTimeout) * time.Second cfg.Scheme = "http" if isHTTPS { cfg.Scheme = "https" } return cfg } func proxyConfigFromHeaders(h http.Header) (cfg Config, err error) { cfg.Scheme = h.Get(HeaderXProxyScheme) cfg.Host = h.Get(HeaderXProxyHost) cfgBase64 := h.Get(HeaderXProxyConfig) cfgJSON, err := base64.StdEncoding.DecodeString(cfgBase64) if err != nil { return cfg, err } err = sonic.Unmarshal(cfgJSON, &cfg) return cfg, err } func (cfg *Config) SetAgentProxyConfigHeadersLegacy(h http.Header) { h.Set(HeaderXProxyHost, cfg.Host) h.Set(HeaderXProxyHTTPS, strconv.FormatBool(cfg.Scheme == "https")) h.Set(HeaderXProxySkipTLSVerify, strconv.FormatBool(cfg.NoTLSVerify)) h.Set(HeaderXProxyResponseHeaderTimeout, strconv.Itoa(int(cfg.ResponseHeaderTimeout.Round(time.Second).Seconds()))) } func (cfg *Config) SetAgentProxyConfigHeaders(h http.Header) { h.Set(HeaderXProxyHost, cfg.Host) h.Set(HeaderXProxyScheme, string(cfg.Scheme)) cfgJSON, _ := sonic.Marshal(cfg.HTTPConfig) cfgBase64 := base64.StdEncoding.EncodeToString(cfgJSON) h.Set(HeaderXProxyConfig, cfgBase64) }