Files
2026-05-09 17:30:16 +08:00

90 lines
2.0 KiB
Go

package proxy
import (
"fmt"
"net/url"
"strconv"
"strings"
)
type directProxyBridgeSpec struct {
Scheme string
Server string
Port int
Username string
Password string
}
func RequiresLocalProxyBridgeForBrowser(src string) bool {
spec, err := parseDirectProxyBridgeSpec(src)
return err == nil && spec != nil
}
func buildDirectProxyBridgeOutbound(src string) (map[string]interface{}, bool, error) {
spec, err := parseDirectProxyBridgeSpec(src)
if err != nil {
return nil, false, err
}
if spec == nil {
return nil, false, nil
}
if spec.Scheme == "socks5" || spec.Scheme == "http" {
return chainSocks5Outbound(chainSocks5Hop{
Protocol: spec.Scheme,
Server: spec.Server,
Port: spec.Port,
Username: spec.Username,
Password: spec.Password,
}, "proxy-out", ""), true, nil
}
return nil, false, nil
}
func parseDirectProxyBridgeSpec(src string) (*directProxyBridgeSpec, error) {
raw := strings.TrimSpace(src)
if raw == "" {
return nil, nil
}
lowerRaw := strings.ToLower(raw)
if !strings.HasPrefix(lowerRaw, "http://") && !strings.HasPrefix(lowerRaw, "socks5://") {
return nil, nil
}
parsed, err := url.Parse(raw)
if err != nil {
return nil, fmt.Errorf("代理地址解析失败: %w", err)
}
scheme := strings.ToLower(strings.TrimSpace(parsed.Scheme))
switch scheme {
case "socks5", "http":
if parsed.User == nil {
return nil, nil
}
username := strings.TrimSpace(parsed.User.Username())
if username == "" {
return nil, nil
}
server := strings.TrimSpace(parsed.Hostname())
if server == "" {
return nil, fmt.Errorf("代理地址缺少主机名")
}
port, err := strconv.Atoi(parsed.Port())
if err != nil || port < 1 || port > 65535 {
return nil, fmt.Errorf("代理端口无效")
}
password, _ := parsed.User.Password()
return &directProxyBridgeSpec{
Scheme: scheme,
Server: server,
Port: port,
Username: username,
Password: password,
}, nil
default:
return nil, nil
}
}