From 71f814d1ce8655abbbce89f0255426440813fb41 Mon Sep 17 00:00:00 2001 From: Rogee Date: Wed, 29 Jul 2026 09:45:09 +0800 Subject: [PATCH] fix: filter out nodes missing server/port before rendering Nodes with port=0 or empty server cause client-side errors (e.g. sing-box decode config failures). Filter them at the render dispatch layer so all targets (sing-box, mihomo, surge, etc.) are protected. --- internal/render/dispatch.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/internal/render/dispatch.go b/internal/render/dispatch.go index 8d4ae43..c5390c4 100644 --- a/internal/render/dispatch.go +++ b/internal/render/dispatch.go @@ -9,9 +9,28 @@ import ( "github.com/peterqiu0516/sub-store/internal/util" ) +// filterInvalidProxies removes nodes missing required server/port fields. +// These would cause client-side errors (e.g. sing-box "missing server_port"). +func filterInvalidProxies(proxies []model.ProxyNode) []model.ProxyNode { + result := make([]model.ProxyNode, 0, len(proxies)) + for _, p := range proxies { + if p == nil { + continue + } + server := getString(p, "server") + port := getInt(p, "port") + if server == "" || port <= 0 { + continue + } + result = append(result, p) + } + return result +} + // RenderTarget dispatches to the appropriate renderer based on target. // This is the simplified entry point matching renderTarget() in the reference. func RenderTarget(proxies []model.ProxyNode, target string, template map[string]any) (string, error) { + proxies = filterInvalidProxies(proxies) if len(proxies) == 0 { return "", fmt.Errorf("No supported nodes for %s output", target) } @@ -45,6 +64,10 @@ func RenderTarget(proxies []model.ProxyNode, target string, template map[string] // RenderBuildTarget dispatches with a request URL for mihomo source comments. func RenderBuildTarget(proxies []model.ProxyNode, target string, requestUrl string, template map[string]any) (string, error) { + proxies = filterInvalidProxies(proxies) + if len(proxies) == 0 { + return "", fmt.Errorf("No supported nodes for %s output", target) + } switch target { case model.TargetMihomo, model.TargetStash: return RenderMihomoYaml(proxies, requestUrl, template), nil