Enhance Mihomo WebSocket functionality and testing for connections
- Added support for WebSocket connections to the `/connections` endpoint, allowing for improved handling of WebSocket requests. - Updated the `useMihomoWebSocketTunnel` function to accept `Sec-WebSocket-Key` for `/connections`, enhancing compatibility with various proxies. - Introduced new test cases in `mihomo_test.go` to validate WebSocket tunnel behavior for connections, ensuring comprehensive coverage. - Enhanced the `applyMihomoWSDialAuth` function to manage token handling for WebSocket connections, improving security and functionality. - Updated Svelte components to implement native WebSocket loops for connections, providing real-time data updates and improved user experience.
This commit is contained in:
@@ -42,7 +42,7 @@ func NewMihomoForward(
|
||||
}
|
||||
|
||||
// useMihomoWebSocketTunnel is true when the client is doing a WS handshake.
|
||||
// For /traffic and /memory we also accept Sec-WebSocket-Key alone: some hops strip
|
||||
// For /traffic, /memory, /connections we also accept Sec-WebSocket-Key alone: some hops strip
|
||||
// Connection/Upgrade but leave Sec-WebSocket-Key; plain streaming GET has no key.
|
||||
func useMihomoWebSocketTunnel(rest string, r *http.Request) bool {
|
||||
if r == nil {
|
||||
@@ -55,13 +55,36 @@ func useMihomoWebSocketTunnel(rest string, r *http.Request) bool {
|
||||
return false
|
||||
}
|
||||
switch rest {
|
||||
case "traffic", "memory":
|
||||
case "traffic", "memory", "connections":
|
||||
return strings.TrimSpace(r.Header.Get("Sec-WebSocket-Key")) != ""
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// applyMihomoWSDialAuth prepares upstream WS URL and Dial headers.
|
||||
// Mihomo: /connections WebSocket expects ?token=<secret> (raw secret, no "Bearer " prefix);
|
||||
// /traffic, /memory use Authorization: Bearer … like REST.
|
||||
func applyMihomoWSDialAuth(rest string, dest *url.URL, auth string) http.Header {
|
||||
hdr := make(http.Header)
|
||||
a := strings.TrimSpace(auth)
|
||||
if a == "" || dest == nil {
|
||||
return hdr
|
||||
}
|
||||
if rest == "connections" {
|
||||
token := a
|
||||
if len(token) > 7 && strings.EqualFold(token[:7], "Bearer ") {
|
||||
token = strings.TrimSpace(token[7:])
|
||||
}
|
||||
q := dest.Query()
|
||||
q.Set("token", token)
|
||||
dest.RawQuery = q.Encode()
|
||||
return hdr
|
||||
}
|
||||
hdr.Set("Authorization", a)
|
||||
return hdr
|
||||
}
|
||||
|
||||
func mihomoWebSocketURL(dest *url.URL) (string, error) {
|
||||
if dest == nil {
|
||||
return "", fmt.Errorf("nil destination URL")
|
||||
@@ -111,16 +134,13 @@ func newMihomoWSTunnel(
|
||||
du.RawQuery = r.URL.RawQuery
|
||||
dest = &du
|
||||
|
||||
dialHdr := applyMihomoWSDialAuth(rest, dest, auth)
|
||||
wsURL, err := mihomoWebSocketURL(dest)
|
||||
if err != nil {
|
||||
errHandler(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
dialHdr := make(http.Header)
|
||||
if auth != "" {
|
||||
dialHdr.Set("Authorization", auth)
|
||||
}
|
||||
d := websocket.Dialer{
|
||||
HandshakeTimeout: 15 * time.Second,
|
||||
Proxy: func(*http.Request) (*url.URL, error) { return nil, nil },
|
||||
|
||||
Reference in New Issue
Block a user