diff --git a/common/convert/converter.go b/common/convert/converter.go index ddc5c944..5a618f42 100644 --- a/common/convert/converter.go +++ b/common/convert/converter.go @@ -68,7 +68,39 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) { hysteria["skip-cert-verify"], _ = strconv.ParseBool(query.Get("insecure")) proxies = append(proxies, hysteria) + case "hysteria2": + urlHysteria2, err := url.Parse(line) + if err != nil { + continue + } + query := urlHysteria2.Query() + name := uniqueName(names, urlHysteria2.Fragment) + hysteria2 := make(map[string]any, 20) + + hysteria2["name"] = name + hysteria2["type"] = scheme + hysteria2["server"] = urlHysteria2.Hostname() + if port := urlHysteria2.Port(); port != "" { + hysteria2["port"] = port + } else { + hysteria2["port"] = "443" + } + hysteria2["obfs"] = query.Get("obfs") + hysteria2["obfs-password"] = query.Get("obfs-password") + hysteria2["sni"] = query.Get("sni") + hysteria2["skip-cert-verify"], _ = strconv.ParseBool(query.Get("insecure")) + if alpn := query.Get("alpn"); alpn != "" { + hysteria2["alpn"] = strings.Split(alpn, ",") + } + if auth := urlHysteria2.User.String(); auth != "" { + hysteria2["password"] = auth + } + hysteria2["fingerprint"] = query.Get("pinSHA256") + hysteria2["down"] = query.Get("down") + hysteria2["up"] = query.Get("up") + + proxies = append(proxies, hysteria2) case "tuic": // A temporary unofficial TUIC share link standard // Modified from https://github.com/daeuniverse/dae/discussions/182 diff --git a/common/convert/converter_test.go b/common/convert/converter_test.go new file mode 100644 index 00000000..83b41c4c --- /dev/null +++ b/common/convert/converter_test.go @@ -0,0 +1,35 @@ +package convert + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// https://v2.hysteria.network/zh/docs/developers/URI-Scheme/ +func TestConvertsV2Ray_normal(t *testing.T) { + hy2test := "hysteria2://letmein@example.com:8443/?insecure=1&obfs=salamander&obfs-password=gawrgura&pinSHA256=deadbeef&sni=real.example.com&up=114&down=514&alpn=h3,h4#hy2test" + + expected := []map[string]interface{}{ + { + "name": "hy2test", + "type": "hysteria2", + "server": "example.com", + "port": "8443", + "sni": "real.example.com", + "obfs": "salamander", + "obfs-password": "gawrgura", + "alpn": []string{"h3", "h4"}, + "password": "letmein", + "up": "114", + "down": "514", + "skip-cert-verify": true, + "fingerprint": "deadbeef", + }, + } + + proxies, err := ConvertsV2Ray([]byte(hy2test)) + + assert.Nil(t, err) + assert.Equal(t, expected, proxies) +}