- 实例配置独立:支持为每个实例单独配置 http/https/socks5 代理,避免单机多开挤兑触发斗鱼出口 IP 限流 - 动态 API 提取:原生支持星空代理等平台的 API 提取(兼容 JSON/文本格式),提供前端一键提取填入与连通性/延迟测速 - 定时前自动拉取:针对 3 分钟短效代理,支持在开抢前 15 秒自动提取并绑定最新 IP,并在预热前完成热连接与时间复校 - 修复复校竞态:将 resyncBeforeTrigger 从 3s 提升至 8s,确保三轮采样在开抢前顺利落盘,消除时钟漂移 - 验证方式:通过 go test ./... 全量测试与前端 vue-tsc/vite 编译,实测通过星空代理 API 解析测试用例
102 lines
2.9 KiB
Go
102 lines
2.9 KiB
Go
package client
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseProxyURL(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expectURL string
|
|
expectError bool
|
|
}{
|
|
{"", "", false},
|
|
{" ", "", false},
|
|
{"127.0.0.1:8888", "http://127.0.0.1:8888", false},
|
|
{"http://127.0.0.1:8888", "http://127.0.0.1:8888", false},
|
|
{"https://127.0.0.1:8888", "https://127.0.0.1:8888", false},
|
|
{"socks5://127.0.0.1:1080", "socks5://127.0.0.1:1080", false},
|
|
{"http://user:pass@127.0.0.1:8888", "http://user:pass@127.0.0.1:8888", false},
|
|
{"ftp://127.0.0.1:21", "", true},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
u, err := ParseProxyURL(tc.input)
|
|
if tc.expectError {
|
|
if err == nil {
|
|
t.Fatalf("ParseProxyURL(%q) expected error, got nil", tc.input)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("ParseProxyURL(%q) unexpected error: %v", tc.input, err)
|
|
}
|
|
if tc.expectURL == "" {
|
|
if u != nil {
|
|
t.Fatalf("ParseProxyURL(%q) expected nil, got %v", tc.input, u)
|
|
}
|
|
} else if u.String() != tc.expectURL {
|
|
t.Fatalf("ParseProxyURL(%q) = %q, want %q", tc.input, u.String(), tc.expectURL)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFetchProxyFromAPI_XKDaili(t *testing.T) {
|
|
// 模拟星空代理正常返回
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
fmt.Fprint(w, `{ "status":100 ,"info":"成功" , "data": [{"ip": "115.230.134.174", "port": "40014", "prov": "浙江", "city": "嘉兴"}]}`)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
res, err := FetchProxyFromAPI(ts.URL)
|
|
if err != nil {
|
|
t.Fatalf("FetchProxyFromAPI failed: %v", err)
|
|
}
|
|
if res.IP != "115.230.134.174" || res.Port != "40014" {
|
|
t.Fatalf("unexpected res: %+v", res)
|
|
}
|
|
if res.ProxyURL != "http://115.230.134.174:40014" {
|
|
t.Fatalf("unexpected proxy url: %s", res.ProxyURL)
|
|
}
|
|
if res.Region != "浙江 嘉兴" {
|
|
t.Fatalf("unexpected region: %s", res.Region)
|
|
}
|
|
}
|
|
|
|
func TestFetchProxyFromAPI_Error(t *testing.T) {
|
|
// 模拟星空代理未加白名单报错
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
fmt.Fprint(w, `{ "status":211 , "info":"当前IP不在白名单内" }`)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
_, err := FetchProxyFromAPI(ts.URL)
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
if err.Error() != "代理平台返回: 当前IP不在白名单内 (状态码=211)" {
|
|
t.Fatalf("unexpected error string: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFetchProxyFromAPI_Text(t *testing.T) {
|
|
// 模拟纯文本返回
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprint(w, "221.122.91.45:3128\r\n")
|
|
}))
|
|
defer ts.Close()
|
|
|
|
res, err := FetchProxyFromAPI(ts.URL)
|
|
if err != nil {
|
|
t.Fatalf("FetchProxyFromAPI failed: %v", err)
|
|
}
|
|
if res.ProxyURL != "http://221.122.91.45:3128" {
|
|
t.Fatalf("unexpected proxy url: %s", res.ProxyURL)
|
|
}
|
|
}
|