feat: 算力引擎 Go 后端核心(new-api)
- 统一 OpenAI 兼容 /v1 中继 + 渠道/额度/令牌/流水 - 各领域包:relay 模型网关、model 数据层、controller 管理 API
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseProxyURLStrict validates and normalizes a proxy URL for persistence.
|
||||
func ParseProxyURLStrict(rawProxyURL string) (*url.URL, error) {
|
||||
parsedURL, _, err := parseProxyURL(rawProxyURL, false)
|
||||
return parsedURL, err
|
||||
}
|
||||
|
||||
// ParseProxyURLRuntime validates and normalizes a proxy URL for runtime use.
|
||||
// The boolean result reports whether a legacy path, query, or fragment was removed.
|
||||
func ParseProxyURLRuntime(rawProxyURL string) (*url.URL, bool, error) {
|
||||
return parseProxyURL(rawProxyURL, true)
|
||||
}
|
||||
|
||||
func parseProxyURL(rawProxyURL string, allowLegacySuffix bool) (*url.URL, bool, error) {
|
||||
trimmedProxyURL := strings.TrimSpace(rawProxyURL)
|
||||
if trimmedProxyURL == "" {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(trimmedProxyURL)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("invalid proxy URL")
|
||||
}
|
||||
parsedURL.Scheme = strings.ToLower(parsedURL.Scheme)
|
||||
switch parsedURL.Scheme {
|
||||
case "http", "https", "socks5", "socks5h":
|
||||
default:
|
||||
return nil, false, fmt.Errorf("proxy URL must use http, https, socks5, or socks5h")
|
||||
}
|
||||
if parsedURL.Hostname() == "" {
|
||||
return nil, false, fmt.Errorf("proxy URL must include a host")
|
||||
}
|
||||
if portText := parsedURL.Port(); portText != "" {
|
||||
port, err := strconv.Atoi(portText)
|
||||
if err != nil || port < 1 || port > 65535 {
|
||||
return nil, false, fmt.Errorf("proxy URL must include a valid port")
|
||||
}
|
||||
}
|
||||
|
||||
hasQuery := parsedURL.RawQuery != "" || parsedURL.ForceQuery
|
||||
hasFragment := strings.Contains(trimmedProxyURL, "#")
|
||||
escapedPath := parsedURL.EscapedPath()
|
||||
hasNonRootPath := escapedPath != "" && escapedPath != "/"
|
||||
legacySuffixStripped := hasQuery || hasFragment || hasNonRootPath
|
||||
if !allowLegacySuffix {
|
||||
switch {
|
||||
case hasQuery:
|
||||
return nil, false, fmt.Errorf("proxy URL must not include a query")
|
||||
case hasFragment:
|
||||
return nil, false, fmt.Errorf("proxy URL must not include a fragment")
|
||||
case hasNonRootPath:
|
||||
return nil, false, fmt.Errorf("proxy URL must not include a path")
|
||||
}
|
||||
}
|
||||
|
||||
parsedURL.Path = ""
|
||||
parsedURL.RawPath = ""
|
||||
parsedURL.RawQuery = ""
|
||||
parsedURL.ForceQuery = false
|
||||
parsedURL.Fragment = ""
|
||||
parsedURL.RawFragment = ""
|
||||
|
||||
if (parsedURL.Scheme == "socks5" || parsedURL.Scheme == "socks5h") && parsedURL.Port() == "" {
|
||||
parsedURL.Host = net.JoinHostPort(parsedURL.Hostname(), "1080")
|
||||
}
|
||||
|
||||
return parsedURL, legacySuffixStripped, nil
|
||||
}
|
||||
Reference in New Issue
Block a user