This commit is contained in:
2025-07-05 22:54:02 +08:00
parent 0fa95888cb
commit ff81d03492
25 changed files with 221 additions and 118 deletions

3
.gitignore vendored
View File

@ -6,3 +6,6 @@ logs
data
.env
.vscode/settings.json
config.yaml
config.yml
config.json

View File

@ -154,7 +154,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
return nil, NewRegexInvalidError("prefix", err)
}
if reg.Match(data) {
p, err := parser.ParseProxies(strings.Split(string(data), "\n")...)
p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, strings.Split(string(data), "\n")...)
if err != nil {
return nil, err
}
@ -169,7 +169,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
)
return nil, NewSubscriptionParseError(err)
}
p, err := parser.ParseProxies(strings.Split(base64, "\n")...)
p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, strings.Split(base64, "\n")...)
if err != nil {
return nil, err
}
@ -187,7 +187,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
}
if len(query.Proxy) != 0 {
p, err := parser.ParseProxies(query.Proxies...)
p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, query.Proxies...)
if err != nil {
return nil, err
}
@ -200,6 +200,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
}
}
// 去重
proxies := make(map[string]*P.Proxy)
newProxies := make([]P.Proxy, 0, len(proxyList))
for i := range proxyList {
@ -216,6 +217,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
}
proxyList = newProxies
// 移除
if strings.TrimSpace(query.Remove) != "" {
newProxyList := make([]P.Proxy, 0, len(proxyList))
for i := range proxyList {
@ -233,8 +235,8 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
proxyList = newProxyList
}
// 替换
if len(query.ReplaceKeys) != 0 {
replaceRegs := make([]*regexp.Regexp, 0, len(query.ReplaceKeys))
for _, v := range query.ReplaceKeys {
replaceReg, err := regexp.Compile(v)
@ -256,6 +258,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string,
}
}
// 重命名有相同名称的节点
names := make(map[string]int)
for i := range proxyList {
if _, exist := names[proxyList[i].Name]; exist {

View File

@ -32,6 +32,7 @@ type SubConfig struct {
NodeListMode bool `form:"nodeList,default=false" binding:""`
IgnoreCountryGrooup bool `form:"ignoreCountryGroup,default=false" binding:""`
UserAgent string `form:"userAgent" binding:""`
UseUDP bool `form:"useUDP,default=false" binding:""`
}
type RuleProviderStruct struct {

View File

@ -26,7 +26,7 @@ func (p *AnytlsParser) GetType() string {
return "anytls"
}
func (p *AnytlsParser) Parse(proxy string) (P.Proxy, error) {
func (p *AnytlsParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}
@ -72,6 +72,7 @@ func (p *AnytlsParser) Parse(proxy string) (P.Proxy, error) {
Password: password,
SNI: sni,
SkipCertVerify: insecureBool,
UDP: config.UseUDP,
},
}
return result, nil

View File

@ -77,14 +77,18 @@ func DecodeBase64(s string) (string, error) {
return string(decodeStr), nil
}
func ParseProxies(proxies ...string) ([]P.Proxy, error) {
type ParseConfig struct {
UseUDP bool
}
func ParseProxies(config ParseConfig, proxies ...string) ([]P.Proxy, error) {
var result []P.Proxy
for _, proxy := range proxies {
if proxy != "" {
var proxyItem P.Proxy
var err error
proxyItem, err = ParseProxyWithRegistry(proxy)
proxyItem, err = ParseProxyWithRegistry(config, proxy)
if err != nil {
return nil, err
}

View File

@ -27,7 +27,7 @@ func (p *HysteriaParser) GetType() string {
return "hysteria"
}
func (p *HysteriaParser) Parse(proxy string) (P.Proxy, error) {
func (p *HysteriaParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}

View File

@ -26,7 +26,7 @@ func (p *Hysteria2Parser) GetType() string {
return "hysteria2"
}
func (p *Hysteria2Parser) Parse(proxy string) (P.Proxy, error) {
func (p *Hysteria2Parser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}

View File

@ -9,7 +9,7 @@ import (
)
type ProxyParser interface {
Parse(proxy string) (P.Proxy, error)
Parse(config ParseConfig, proxy string) (P.Proxy, error)
GetPrefixes() []string
GetType() string
SupportClash() bool
@ -64,7 +64,7 @@ func GetAllPrefixes() []string {
return prefixes
}
func ParseProxyWithRegistry(proxy string) (P.Proxy, error) {
func ParseProxyWithRegistry(config ParseConfig, proxy string) (P.Proxy, error) {
proxy = strings.TrimSpace(proxy)
if proxy == "" {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidStruct, "empty proxy string")
@ -72,7 +72,7 @@ func ParseProxyWithRegistry(proxy string) (P.Proxy, error) {
for prefix, parser := range registry.parsers {
if strings.HasPrefix(proxy, prefix) {
return parser.Parse(proxy)
return parser.Parse(config, proxy)
}
}

View File

@ -30,7 +30,7 @@ func (p *ShadowsocksParser) GetType() string {
}
// Parse 解析Shadowsocks代理
func (p *ShadowsocksParser) Parse(proxy string) (P.Proxy, error) {
func (p *ShadowsocksParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}
@ -108,9 +108,9 @@ func (p *ShadowsocksParser) Parse(proxy string) (P.Proxy, error) {
Password: password,
Server: server,
Port: port,
UDP: config.UseUDP,
},
}
return result, nil
}

View File

@ -27,7 +27,7 @@ func (p *ShadowsocksRParser) GetType() string {
return "ssr"
}
func (p *ShadowsocksRParser) Parse(proxy string) (P.Proxy, error) {
func (p *ShadowsocksRParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}
@ -100,9 +100,9 @@ func (p *ShadowsocksRParser) Parse(proxy string) (P.Proxy, error) {
Password: password,
ObfsParam: obfsParam,
ProtocolParam: protoParam,
UDP: config.UseUDP,
},
}
return result, nil
}

View File

@ -25,7 +25,7 @@ func (p *SocksParser) GetType() string {
return "socks5"
}
func (p *SocksParser) Parse(proxy string) (P.Proxy, error) {
func (p *SocksParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}

View File

@ -26,7 +26,7 @@ func (p *TrojanParser) GetType() string {
return "trojan"
}
func (p *TrojanParser) Parse(proxy string) (P.Proxy, error) {
func (p *TrojanParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}

View File

@ -26,7 +26,7 @@ func (p *VlessParser) GetType() string {
return "vless"
}
func (p *VlessParser) Parse(proxy string) (P.Proxy, error) {
func (p *VlessParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}

View File

@ -46,7 +46,7 @@ func (p *VmessParser) GetType() string {
return "vmess"
}
func (p *VmessParser) Parse(proxy string) (P.Proxy, error) {
func (p *VmessParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) {
if !hasPrefix(proxy, p.GetPrefixes()) {
return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy)
}
@ -112,6 +112,7 @@ func (p *VmessParser) Parse(proxy string) (P.Proxy, error) {
UUID: vmess.Id,
AlterID: aid,
Cipher: vmess.Scy,
UDP: config.UseUDP,
}
if len(alpn) > 0 {

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="zh-CN">
<html lang="zh-CN" data-bs-theme="light">
<head>
<meta charset="UTF-8" />
@ -28,10 +28,38 @@
height: 25px;
width: 25px;
}
/* 主题切换按钮样式 */
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.theme-toggle:hover {
transform: scale(1.1);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
</style>
</head>
<body class="bg-light">
<body>
<!-- 主题切换按钮 -->
<button class="theme-toggle btn btn-outline-secondary" onclick="toggleTheme()" title="切换深色/浅色模式">
<span id="theme-icon">🌙</span>
</button>
<div class="container mt-5">
<div class="mb-4">
<h2>sub2clash</h2>
@ -104,6 +132,11 @@
<input class="form-check-input" id="igcg" name="igcg" type="checkbox" />
<label class="form-check-label" for="igcg">不输出国家策略组</label>
</div>
<!-- Use UDP -->
<div class="form-check mb-3">
<input class="form-check-input" id="useUDP" name="useUDP" type="checkbox" />
<label class="form-check-label" for="useUDP">使用 UDP</label>
</div>
<!-- Rule Provider -->
<div class="form-group mb-3" id="ruleProviderGroup">
<label>Rule Provider:</label>
@ -145,7 +178,7 @@
<div class="form-group mb-5">
<label for="apiLink">配置链接:</label>
<div class="input-group mb-2">
<input class="form-control bg-light" id="apiLink" type="text" placeholder="链接" readonly
<input class="form-control" id="apiLink" type="text" placeholder="链接" readonly
style="cursor: not-allowed;" />
<button class="btn btn-primary" onclick="copyToClipboard('apiLink',this)" type="button">
复制链接
@ -162,7 +195,7 @@
</button>
</div>
<div class="input-group">
<input class="form-control bg-light" id="apiShortLink" type="text" placeholder="短链接" readonly
<input class="form-control" id="apiShortLink" type="text" placeholder="短链接" readonly
style="cursor: not-allowed;" />
<button class="btn btn-primary" onclick="updateShortLink()" type="button">
更新短链

View File

@ -19,6 +19,7 @@ function clearExistingValues() {
document.getElementById("autoTest").checked = false;
document.getElementById("lazy").checked = false;
document.getElementById("igcg").checked = false;
document.getElementById("useUDP").checked = false;
document.getElementById("template").value = "";
document.getElementById("sort").value = "nameasc";
document.getElementById("remove").value = "";
@ -110,6 +111,8 @@ function generateURI() {
queryParams.push(`nodeList=${nodeList ? "true" : "false"}`);
const igcg = document.getElementById("igcg").checked;
queryParams.push(`ignoreCountryGroup=${igcg ? "true" : "false"}`);
const useUDP = document.getElementById("useUDP").checked;
queryParams.push(`useUDP=${useUDP ? "true" : "false"}`);
// 获取模板链接或名称(如果存在)
const template = document.getElementById("template").value;
@ -336,6 +339,11 @@ async function parseInputURL() {
document.getElementById("nodeList").checked =
params.get("nodeList") === "true";
}
if (params.has("useUDP")) {
document.getElementById("useUDP").checked =
params.get("useUDP") === "true";
}
}
function clearInputGroup(groupId) {
@ -580,4 +588,53 @@ function updateShortLink() {
});
}
// 主题切换功能
function initTheme() {
const html = document.querySelector('html');
const themeIcon = document.getElementById('theme-icon');
let theme;
// 从localStorage获取用户偏好的主题
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
// 如果用户之前设置过主题,使用保存的主题
theme = savedTheme;
} else {
// 如果没有设置过,检测系统主题偏好
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
theme = prefersDark ? 'dark' : 'light';
}
// 设置主题
html.setAttribute('data-bs-theme', theme);
// 更新图标
if (theme === 'dark') {
themeIcon.textContent = '☀️';
} else {
themeIcon.textContent = '🌙';
}
}
function toggleTheme() {
const html = document.querySelector('html');
const currentTheme = html.getAttribute('data-bs-theme');
// 切换主题
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-bs-theme', newTheme);
// 更新图标
if (newTheme === 'dark') {
themeIcon.textContent = '☀️';
} else {
themeIcon.textContent = '🌙';
}
// 保存用户偏好到localStorage
localStorage.setItem('theme', newTheme);
}
listenInput();
initTheme();

View File

@ -22,7 +22,7 @@ func TestAnytls_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -47,7 +47,7 @@ func TestAnytls_Basic_WithSNI(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -72,7 +72,7 @@ func TestAnytls_Basic_WithInsecure(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -96,7 +96,7 @@ func TestAnytls_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -121,7 +121,7 @@ func TestAnytls_Basic_ComplexPassword(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -145,7 +145,7 @@ func TestAnytls_Basic_NoPassword(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -169,7 +169,7 @@ func TestAnytls_Basic_UsernameOnly(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -182,7 +182,7 @@ func TestAnytls_Error_MissingServer(t *testing.T) {
p := &parser.AnytlsParser{}
input := "anytls://password123@:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -192,7 +192,7 @@ func TestAnytls_Error_MissingPort(t *testing.T) {
p := &parser.AnytlsParser{}
input := "anytls://password123@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -202,7 +202,7 @@ func TestAnytls_Error_InvalidPort(t *testing.T) {
p := &parser.AnytlsParser{}
input := "anytls://password123@127.0.0.1:99999"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -212,7 +212,7 @@ func TestAnytls_Error_InvalidProtocol(t *testing.T) {
p := &parser.AnytlsParser{}
input := "anyssl://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -22,7 +22,7 @@ func TestHysteria2_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -47,7 +47,7 @@ func TestHysteria2_Basic_AltPrefix(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -73,7 +73,7 @@ func TestHysteria2_Basic_WithObfs(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -97,7 +97,7 @@ func TestHysteria2_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -124,7 +124,7 @@ func TestHysteria2_Basic_FullConfig(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -148,7 +148,7 @@ func TestHysteria2_Basic_NoPassword(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -161,7 +161,7 @@ func TestHysteria2_Error_MissingServer(t *testing.T) {
p := &parser.Hysteria2Parser{}
input := "hysteria2://password123@:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -171,7 +171,7 @@ func TestHysteria2_Error_MissingPort(t *testing.T) {
p := &parser.Hysteria2Parser{}
input := "hysteria2://password123@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -181,7 +181,7 @@ func TestHysteria2_Error_InvalidPort(t *testing.T) {
p := &parser.Hysteria2Parser{}
input := "hysteria2://password123@127.0.0.1:99999"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -191,7 +191,7 @@ func TestHysteria2_Error_InvalidProtocol(t *testing.T) {
p := &parser.Hysteria2Parser{}
input := "hysteria://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -25,7 +25,7 @@ func TestHysteria_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -52,7 +52,7 @@ func TestHysteria_Basic_WithAuthString(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -80,7 +80,7 @@ func TestHysteria_Basic_WithObfs(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -106,7 +106,7 @@ func TestHysteria_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -133,7 +133,7 @@ func TestHysteria_Basic_MultiALPN(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -146,7 +146,7 @@ func TestHysteria_Error_MissingServer(t *testing.T) {
p := &parser.HysteriaParser{}
input := "hysteria://:8080?auth=password123"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -156,7 +156,7 @@ func TestHysteria_Error_MissingPort(t *testing.T) {
p := &parser.HysteriaParser{}
input := "hysteria://127.0.0.1?auth=password123"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -166,7 +166,7 @@ func TestHysteria_Error_InvalidPort(t *testing.T) {
p := &parser.HysteriaParser{}
input := "hysteria://127.0.0.1:99999?auth=password123"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -176,7 +176,7 @@ func TestHysteria_Error_InvalidProtocol(t *testing.T) {
p := &parser.HysteriaParser{}
input := "hysteria2://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -23,7 +23,7 @@ func TestShadowsocks_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -47,7 +47,7 @@ func TestShadowsocks_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -71,7 +71,7 @@ func TestShadowsocks_Basic_WithRemark(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -95,7 +95,7 @@ func TestShadowsocks_Advanced_Base64FullEncoded(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -119,7 +119,7 @@ func TestShadowsocks_Advanced_PlainUserPassword(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -143,7 +143,7 @@ func TestShadowsocks_Advanced_ChaCha20Cipher(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -157,7 +157,7 @@ func TestShadowsocks_Error_MissingServer(t *testing.T) {
p := &parser.ShadowsocksParser{}
input := "ss://YWVzLTI1Ni1nY206cGFzc3dvcmQ=@:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if !errors.Is(err, parser.ErrInvalidStruct) {
t.Errorf("Error is not expected: %v", err)
}
@ -167,7 +167,7 @@ func TestShadowsocks_Error_MissingPort(t *testing.T) {
p := &parser.ShadowsocksParser{}
input := "ss://YWVzLTI1Ni1nY206cGFzc3dvcmQ=@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if !errors.Is(err, parser.ErrInvalidStruct) {
t.Errorf("Error is not expected: %v", err)
}
@ -177,7 +177,7 @@ func TestShadowsocks_Error_InvalidProtocol(t *testing.T) {
p := &parser.ShadowsocksParser{}
input := "http://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if !errors.Is(err, parser.ErrInvalidPrefix) {
t.Errorf("Error is not expected: %v", err)
}

View File

@ -26,7 +26,7 @@ func TestShadowsocksR_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -54,7 +54,7 @@ func TestShadowsocksR_Basic_WithParams(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -82,7 +82,7 @@ func TestShadowsocksR_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -95,7 +95,7 @@ func TestShadowsocksR_Error_InvalidBase64(t *testing.T) {
p := &parser.ShadowsocksRParser{}
input := "ssr://invalid_base64"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -105,7 +105,7 @@ func TestShadowsocksR_Error_InvalidProtocol(t *testing.T) {
p := &parser.ShadowsocksRParser{}
input := "ss://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -22,7 +22,7 @@ func TestSocks_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -44,7 +44,7 @@ func TestSocks_Basic_NoAuth(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -68,7 +68,7 @@ func TestSocks_Basic_IPv6Address(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -93,7 +93,7 @@ func TestSocks_Basic_WithTLS(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -118,7 +118,7 @@ func TestSocks_Basic_WithUDP(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -131,7 +131,7 @@ func TestSocks_Error_MissingServer(t *testing.T) {
p := &parser.SocksParser{}
input := "socks://user:pass@:1080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -141,7 +141,7 @@ func TestSocks_Error_MissingPort(t *testing.T) {
p := &parser.SocksParser{}
input := "socks://user:pass@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -151,7 +151,7 @@ func TestSocks_Error_InvalidPort(t *testing.T) {
p := &parser.SocksParser{}
input := "socks://user:pass@127.0.0.1:99999"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -161,7 +161,7 @@ func TestSocks_Error_InvalidProtocol(t *testing.T) {
p := &parser.SocksParser{}
input := "ss://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -21,7 +21,7 @@ func TestTrojan_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -46,7 +46,7 @@ func TestTrojan_Basic_WithTLS(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -75,7 +75,7 @@ func TestTrojan_Basic_WithReality(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -105,7 +105,7 @@ func TestTrojan_Basic_WithWebSocket(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -132,7 +132,7 @@ func TestTrojan_Basic_WithGrpc(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -145,7 +145,7 @@ func TestTrojan_Error_MissingServer(t *testing.T) {
p := &parser.TrojanParser{}
input := "trojan://password@:443"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -155,7 +155,7 @@ func TestTrojan_Error_MissingPort(t *testing.T) {
p := &parser.TrojanParser{}
input := "trojan://password@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -165,7 +165,7 @@ func TestTrojan_Error_InvalidPort(t *testing.T) {
p := &parser.TrojanParser{}
input := "trojan://password@127.0.0.1:99999"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -175,7 +175,7 @@ func TestTrojan_Error_InvalidProtocol(t *testing.T) {
p := &parser.TrojanParser{}
input := "ss://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -21,7 +21,7 @@ func TestVless_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -47,7 +47,7 @@ func TestVless_Basic_WithTLS(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -77,7 +77,7 @@ func TestVless_Basic_WithReality(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -107,7 +107,7 @@ func TestVless_Basic_WithWebSocket(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -134,7 +134,7 @@ func TestVless_Basic_WithGrpc(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -164,7 +164,7 @@ func TestVless_Basic_WithHTTP(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -177,7 +177,7 @@ func TestVless_Error_MissingServer(t *testing.T) {
p := &parser.VlessParser{}
input := "vless://b831b0c4-33b7-4873-9834-28d66d87d4ce@:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -187,7 +187,7 @@ func TestVless_Error_MissingPort(t *testing.T) {
p := &parser.VlessParser{}
input := "vless://b831b0c4-33b7-4873-9834-28d66d87d4ce@127.0.0.1"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -197,7 +197,7 @@ func TestVless_Error_InvalidPort(t *testing.T) {
p := &parser.VlessParser{}
input := "vless://b831b0c4-33b7-4873-9834-28d66d87d4ce@127.0.0.1:99999"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -207,7 +207,7 @@ func TestVless_Error_InvalidProtocol(t *testing.T) {
p := &parser.VlessParser{}
input := "ss://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}

View File

@ -31,7 +31,7 @@ func TestVmess_Basic_SimpleLink(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -64,7 +64,7 @@ func TestVmess_Basic_WithPath(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -97,7 +97,7 @@ func TestVmess_Basic_WithHost(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -131,7 +131,7 @@ func TestVmess_Basic_WithSNI(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -164,7 +164,7 @@ func TestVmess_Basic_WithAlterID(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -192,7 +192,7 @@ func TestVmess_Basic_GRPC(t *testing.T) {
},
}
result, err := p.Parse(input)
result, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
@ -205,7 +205,7 @@ func TestVmess_Error_InvalidBase64(t *testing.T) {
p := &parser.VmessParser{}
input := "vmess://invalid_base64"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -215,7 +215,7 @@ func TestVmess_Error_InvalidJSON(t *testing.T) {
p := &parser.VmessParser{}
input := "vmess://eyJpbnZhbGlkIjoianNvbn0="
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}
@ -225,7 +225,7 @@ func TestVmess_Error_InvalidProtocol(t *testing.T) {
p := &parser.VmessParser{}
input := "ss://example.com:8080"
_, err := p.Parse(input)
_, err := p.Parse(parser.ParseConfig{UseUDP: false}, input)
if err == nil {
t.Errorf("Expected error but got none")
}