所有目标流量可经统一的全局代理出网(http/https/socks5,支持 user:pass): - 开启流量捕获时,作为 MITM 记录代理的上游(流量照录再经代理出网); 拦截与透传两条路径都走上游,不泄露源 IP。 - 关闭捕获时,直接注入 agent 的 bash 环境与 WebFetch;proxyEnv 增加 ALL_PROXY 以支持 socks5。 配置存于 settings KV 表(无需迁移),前端系统配置页新增「全局代理」卡片。 与网络搜索代理、LLM 代理相互独立。
60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
package traffic
|
|
|
|
import "testing"
|
|
|
|
func TestValidateProxyURL(t *testing.T) {
|
|
ok := []string{
|
|
"http://127.0.0.1:8080",
|
|
"https://proxy.example.com:3128",
|
|
"socks5://10.0.0.1:1080",
|
|
"socks5://user:[email protected]:1080",
|
|
}
|
|
for _, raw := range ok {
|
|
if _, err := ValidateProxyURL(raw); err != nil {
|
|
t.Errorf("ValidateProxyURL(%q) unexpected error: %v", raw, err)
|
|
}
|
|
}
|
|
bad := []string{
|
|
"127.0.0.1:8080", // no scheme
|
|
"ftp://host:21", // unsupported scheme
|
|
"http://", // no host
|
|
"socks4://10.0.0.1:1080", // unsupported scheme
|
|
}
|
|
for _, raw := range bad {
|
|
if _, err := ValidateProxyURL(raw); err == nil {
|
|
t.Errorf("ValidateProxyURL(%q) expected error, got nil", raw)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSetUpstreamProxyStoreClear(t *testing.T) {
|
|
tr := &Traffic{}
|
|
if got := tr.upstream.Load(); got != nil {
|
|
t.Fatalf("initial upstream = %v, want nil", got)
|
|
}
|
|
if err := tr.SetUpstreamProxy("socks5://user:[email protected]:1080"); err != nil {
|
|
t.Fatalf("SetUpstreamProxy: %v", err)
|
|
}
|
|
u := tr.upstream.Load()
|
|
if u == nil || u.Scheme != "socks5" || u.Host != "10.0.0.1:1080" {
|
|
t.Fatalf("stored upstream = %v, want socks5://10.0.0.1:1080", u)
|
|
}
|
|
if pw, _ := u.User.Password(); u.User.Username() != "user" || pw != "pass" {
|
|
t.Fatalf("stored upstream lost credentials: %v", u)
|
|
}
|
|
// Empty clears back to direct.
|
|
if err := tr.SetUpstreamProxy(" "); err != nil {
|
|
t.Fatalf("SetUpstreamProxy(clear): %v", err)
|
|
}
|
|
if got := tr.upstream.Load(); got != nil {
|
|
t.Fatalf("after clear upstream = %v, want nil", got)
|
|
}
|
|
// Invalid value is rejected and does not mutate current state.
|
|
if err := tr.SetUpstreamProxy("nope://x"); err == nil {
|
|
t.Fatal("SetUpstreamProxy(invalid) expected error")
|
|
}
|
|
if got := tr.upstream.Load(); got != nil {
|
|
t.Fatalf("invalid set mutated upstream to %v, want nil", got)
|
|
}
|
|
}
|