feat: add wss/https auto-detect with fallback for node-backend comm

This commit is contained in:
qimaoww
2026-03-08 20:00:54 +08:00
parent 508a37a84c
commit fbb4d82a44
7 changed files with 670 additions and 111 deletions
@@ -6,6 +6,7 @@ import (
"fmt"
"net"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
@@ -1612,29 +1613,55 @@ func buildForwarderNodes(targets []string) []map[string]interface{} {
}
func processServerAddress(serverAddr string) string {
serverAddr = strings.TrimSpace(serverAddr)
serverAddr = normalizeServerAddressInput(serverAddr)
if serverAddr == "" {
return serverAddr
}
if strings.HasPrefix(serverAddr, "[") {
return serverAddr
}
if looksLikeIPv6(serverAddr) {
return "[" + strings.Trim(serverAddr, "[]") + "]"
}
idx := strings.LastIndex(serverAddr, ":")
if idx < 0 {
if looksLikeIPv6(serverAddr) {
return "[" + serverAddr + "]"
}
return serverAddr
}
if strings.Count(serverAddr, ":") != 1 {
return "[" + strings.Trim(serverAddr, "[]") + "]"
}
host := strings.TrimSpace(serverAddr[:idx])
port := strings.TrimSpace(serverAddr[idx+1:])
if host == "" || port == "" {
return serverAddr
}
if looksLikeIPv6(host) {
return "[" + host + "]:" + port
return "[" + strings.Trim(host, "[]") + "]:" + port
}
return serverAddr
return host + ":" + port
}
func normalizeServerAddressInput(serverAddr string) string {
serverAddr = strings.TrimSpace(serverAddr)
if serverAddr == "" {
return serverAddr
}
if idx := strings.Index(serverAddr, "://"); idx > 0 {
if parsed, err := url.Parse(serverAddr); err == nil {
if host := strings.TrimSpace(parsed.Host); host != "" {
return host
}
}
serverAddr = serverAddr[idx+3:]
}
if idx := strings.IndexAny(serverAddr, "/?#"); idx >= 0 {
serverAddr = serverAddr[:idx]
}
return strings.TrimSpace(serverAddr)
}
func looksLikeIPv6(address string) bool {
@@ -420,3 +420,68 @@ func TestBuildForwardServiceConfigs_BindIPAlreadyContainsPort(t *testing.T) {
}
}
}
func TestProcessServerAddress_StripsURLSchemeAndPath(t *testing.T) {
tests := []struct {
name string
in string
want string
}{
{
name: "https with path",
in: "https://panel.example.com:8443/api/v1",
want: "panel.example.com:8443",
},
{
name: "wss with query",
in: "wss://panel.example.com:443/system-info?x=1",
want: "panel.example.com:443",
},
{
name: "http without port",
in: "http://panel.example.com",
want: "panel.example.com",
},
{
name: "manual host with trailing path",
in: "panel.example.com:8080/path",
want: "panel.example.com:8080",
},
}
for _, tt := range tests {
if got := processServerAddress(tt.in); got != tt.want {
t.Fatalf("%s: expected %q, got %q", tt.name, tt.want, got)
}
}
}
func TestProcessServerAddress_NormalizesIPv6(t *testing.T) {
tests := []struct {
name string
in string
want string
}{
{
name: "ipv6 host only",
in: "2001:db8::1",
want: "[2001:db8::1]",
},
{
name: "ipv6 host and port",
in: "https://[2001:db8::1]:8443/path",
want: "[2001:db8::1]:8443",
},
{
name: "already bracketed",
in: "[2001:db8::2]:9000",
want: "[2001:db8::2]:9000",
},
}
for _, tt := range tests {
if got := processServerAddress(tt.in); got != tt.want {
t.Fatalf("%s: expected %q, got %q", tt.name, tt.want, got)
}
}
}