diff --git a/internal/proxy/mihomo.go b/internal/proxy/mihomo.go index d7af141..313783c 100644 --- a/internal/proxy/mihomo.go +++ b/internal/proxy/mihomo.go @@ -36,10 +36,14 @@ func isWebSocketUpgrade(r *http.Request) bool { if r == nil { return false } - // Some clients/proxies pass comma-separated tokens or extra spaces. - // Treat request as WS only when both headers contain required upgrade tokens. - return headerHasToken(r.Header, "Connection", "upgrade") && - headerHasToken(r.Header, "Upgrade", "websocket") + // Be tolerant to proxy/header quirks: + // - RFC path: Connection: upgrade + Upgrade: websocket + // - Fallback: Sec-WebSocket-Key presence strongly indicates WS handshake. + if headerHasToken(r.Header, "Upgrade", "websocket") && + headerHasToken(r.Header, "Connection", "upgrade") { + return true + } + return strings.TrimSpace(r.Header.Get("Sec-WebSocket-Key")) != "" } func headerHasToken(h http.Header, key, token string) bool { diff --git a/internal/proxy/mihomo_test.go b/internal/proxy/mihomo_test.go index 41e1ec1..65ce798 100644 --- a/internal/proxy/mihomo_test.go +++ b/internal/proxy/mihomo_test.go @@ -53,4 +53,10 @@ func TestIsWebSocketUpgrade(t *testing.T) { if isWebSocketUpgrade(r2) { t.Fatal("expected non-websocket when Connection lacks upgrade") } + + r3 := httptest.NewRequest(http.MethodGet, "http://gw/api/mtg/mihomo/traffic", nil) + r3.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") + if !isWebSocketUpgrade(r3) { + t.Fatal("expected websocket upgrade when Sec-WebSocket-Key is present") + } }