package naive import ( "fmt" "net/url" "strings" ) // NormalizeProxyURI converts share links and aliases into a naive --proxy URI. // // Supported inputs: // - https://user:pass@host:443 // - quic://user:pass@host // - naive+https://user:pass@host:443#remark // - naive+quic://user:pass@host#remark func NormalizeProxyURI(raw string) (string, error) { uri, _, err := ParseShareLink(raw) return uri, err } // ParseShareLink returns a normalized proxy URI and optional remark from #fragment. func ParseShareLink(raw string) (proxyURI, remark string, err error) { raw = strings.TrimSpace(raw) if raw == "" { return "", "", fmt.Errorf("empty proxy URI") } if i := strings.IndexByte(raw, '#'); i >= 0 { remark = strings.TrimSpace(raw[i+1:]) raw = raw[:i] } lower := strings.ToLower(raw) switch { case strings.HasPrefix(lower, "naive+https://"): raw = "https://" + raw[len("naive+https://"):] case strings.HasPrefix(lower, "naive+quic://"): raw = "quic://" + raw[len("naive+quic://"):] case strings.HasPrefix(lower, "naive://"): raw = "https://" + raw[len("naive://"):] } u, err := url.Parse(raw) if err != nil { return "", "", fmt.Errorf("parse proxy URI: %w", err) } switch strings.ToLower(u.Scheme) { case "https", "quic", "http": default: return "", "", fmt.Errorf("unsupported proxy scheme %q (use https://, quic:// or naive+https://)", u.Scheme) } if u.Host == "" { return "", "", fmt.Errorf("proxy URI missing host") } if u.User == nil || u.User.Username() == "" { return "", "", fmt.Errorf("proxy URI missing username") } if _, ok := u.User.Password(); !ok { return "", "", fmt.Errorf("proxy URI missing password") } out := &url.URL{ Scheme: strings.ToLower(u.Scheme), User: u.User, Host: u.Host, } return out.String(), remark, nil }