feat: Implement S2A, Rod, and Chromedp based authentication for external services, and introduce new frontend pages and backend APIs for monitoring, configuration, upload, and team processes.

This commit is contained in:
2026-02-01 04:58:12 +08:00
parent 842a4ab4b2
commit e867bc5cbd
10 changed files with 314 additions and 22 deletions

View File

@@ -0,0 +1,107 @@
package proxyutil
import (
"fmt"
"net"
"net/url"
"strings"
)
// Info is a parsed proxy configuration.
//
// It supports the following input formats:
// - http://host:port
// - http://user:pass@host:port
// - host:port (defaults to http)
// - host:port:user:pass (defaults to http; password may contain ':')
// - user:pass@host:port (defaults to http)
type Info struct {
// URL is the normalized proxy URL (may include credentials).
URL *url.URL
// Server is the proxy server URL without credentials (scheme + host:port).
Server *url.URL
Username string
Password string
}
func Parse(raw string) (*Info, error) {
raw = strings.TrimSpace(raw)
if raw == "" {
return &Info{}, nil
}
// URL-style proxy (has scheme)
if strings.Contains(raw, "://") {
u, err := url.Parse(raw)
if err != nil {
return nil, fmt.Errorf("parse proxy url: %w", err)
}
if u.Scheme == "" || u.Host == "" {
return nil, fmt.Errorf("invalid proxy url: %q", raw)
}
u = &url.URL{
Scheme: strings.ToLower(u.Scheme),
Host: u.Host,
User: u.User,
}
user := ""
pass := ""
if u.User != nil {
user = u.User.Username()
pass, _ = u.User.Password()
}
server := &url.URL{Scheme: u.Scheme, Host: u.Host}
return &Info{
URL: u,
Server: server,
Username: user,
Password: pass,
}, nil
}
// user:pass@host:port (no scheme)
if strings.Contains(raw, "@") {
return Parse("http://" + raw)
}
// host:port[:user:pass]
parts := strings.Split(raw, ":")
switch {
case len(parts) == 2:
host, port := parts[0], parts[1]
hp := net.JoinHostPort(host, port)
u := &url.URL{Scheme: "http", Host: hp}
return &Info{URL: u, Server: &url.URL{Scheme: u.Scheme, Host: u.Host}}, nil
case len(parts) >= 4:
host, port := parts[0], parts[1]
user := parts[2]
pass := strings.Join(parts[3:], ":")
hp := net.JoinHostPort(host, port)
u := &url.URL{Scheme: "http", Host: hp, User: url.UserPassword(user, pass)}
return &Info{
URL: u,
Server: &url.URL{Scheme: u.Scheme, Host: u.Host},
Username: user,
Password: pass,
}, nil
default:
return nil, fmt.Errorf("unsupported proxy format: %q", raw)
}
}
// Normalize returns a normalized proxy URL string.
// Empty input returns empty output.
func Normalize(raw string) (string, error) {
info, err := Parse(raw)
if err != nil {
return "", err
}
if info.URL == nil {
return "", nil
}
return info.URL.String(), nil
}