From d1558b71c41bec68672172658faeff00077e578b Mon Sep 17 00:00:00 2001 From: hamster1963 <1410514192@qq.com> Date: Sat, 23 Nov 2024 17:31:00 +0800 Subject: [PATCH] fix: websocket proxy --- .../use-websocket.tsx} | 29 ++++++++++++------- src/lib/websocketContext.tsx | 14 +++++++++ src/lib/websocketProvider.tsx | 19 +++--------- src/pages/Server.tsx | 16 ++++++++++ vite.config.ts | 9 ++++++ 5 files changed, 61 insertions(+), 26 deletions(-) rename src/{lib/useWebsocket.tsx => hooks/use-websocket.tsx} (71%) create mode 100644 src/lib/websocketContext.tsx diff --git a/src/lib/useWebsocket.tsx b/src/hooks/use-websocket.tsx similarity index 71% rename from src/lib/useWebsocket.tsx rename to src/hooks/use-websocket.tsx index 1ebe770..62fdd8a 100644 --- a/src/lib/useWebsocket.tsx +++ b/src/hooks/use-websocket.tsx @@ -3,7 +3,6 @@ import { useState, useEffect, useRef, useCallback } from "react"; export interface WebSocketHook { socket: WebSocket | null; connected: boolean; - onlineCount: number; message: string | null; sendMessage: (msg: string) => void; } @@ -12,7 +11,6 @@ export default function useWebSocket(url: string): WebSocketHook { const [socket, setSocket] = useState(null); const [message, setMessage] = useState(null); const [connected, setConnected] = useState(false); - const [onlineCount, setOnlineCount] = useState(0); const socketRef = useRef(null); const reconnectAttempts = useRef(0); const reconnectTimeout = useRef(null); @@ -32,28 +30,37 @@ export default function useWebSocket(url: string): WebSocketHook { ws.onmessage = (event: MessageEvent) => { setMessage(event.data); - const msgJson = JSON.parse(event.data); - if (msgJson.type === "live") { - setOnlineCount(msgJson.data.count); - } }; ws.onerror = (error) => { console.error("WebSocket Error:", error); + // 在错误发生时主动关闭连接,触发重连 + if (ws.readyState === WebSocket.OPEN) { + ws.close(); + } }; ws.onclose = () => { setConnected(false); + // 清理当前的 socket + socketRef.current = null; + if (!isUnmounted.current) { - // Attempt to reconnect - if (reconnectAttempts.current < 5) { - const timeout = Math.pow(2, reconnectAttempts.current) * 1000; // Exponential backoff + // 检查是否已经在重连中 + if (reconnectTimeout.current) { + clearTimeout(reconnectTimeout.current); + } + + // Attempt to reconnect with increased max attempts + if (reconnectAttempts.current < 10) { + const timeout = Math.min(Math.pow(2, reconnectAttempts.current) * 1000, 30000); // 最大30秒 reconnectAttempts.current += 1; + console.log(`Attempting to reconnect in ${timeout/1000} seconds...`); reconnectTimeout.current = setTimeout(() => { connect(); }, timeout); } else { - console.warn("Max reconnect attempts reached."); + console.warn("Max reconnect attempts reached. Please refresh the page to try again."); } } }; @@ -85,5 +92,5 @@ export default function useWebSocket(url: string): WebSocketHook { } }, []); - return { socket, message, sendMessage, connected, onlineCount }; + return { socket, message, sendMessage, connected }; } diff --git a/src/lib/websocketContext.tsx b/src/lib/websocketContext.tsx new file mode 100644 index 0000000..16f6ca8 --- /dev/null +++ b/src/lib/websocketContext.tsx @@ -0,0 +1,14 @@ +import { createContext, useContext } from "react"; +import { WebSocketHook } from "../hooks/use-websocket"; + +export const WebSocketContext = createContext(undefined); + +export const useWebSocketContext = (): WebSocketHook => { + const context = useContext(WebSocketContext); + if (!context) { + throw new Error( + "useWebSocketContext must be used within a WebSocketProvider", + ); + } + return context; +}; diff --git a/src/lib/websocketProvider.tsx b/src/lib/websocketProvider.tsx index 1cf6688..b951e12 100644 --- a/src/lib/websocketProvider.tsx +++ b/src/lib/websocketProvider.tsx @@ -1,25 +1,14 @@ -import { createContext, useContext, ReactNode } from "react"; -import useWebSocket, { WebSocketHook } from "./useWebsocket"; +import { ReactNode } from "react"; +import useWebSocket from "../hooks/use-websocket"; +import { WebSocketContext } from "./websocketContext"; interface WebSocketProviderProps { children: ReactNode; } -const WebSocketContext = createContext(undefined); - export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { - const ws = useWebSocket("wss://dev-next.buycoffee.top:4433/api/v1/ws/server"); + const ws = useWebSocket('/api/v1/ws/server'); return ( {children} ); }; - -export const useWebSocketContext = (): WebSocketHook => { - const context = useContext(WebSocketContext); - if (!context) { - throw new Error( - "useWebSocketContext must be used within a WebSocketProvider", - ); - } - return context; -}; diff --git a/src/pages/Server.tsx b/src/pages/Server.tsx index 534dd79..61b6208 100644 --- a/src/pages/Server.tsx +++ b/src/pages/Server.tsx @@ -1,4 +1,20 @@ +import { useWebSocketContext } from "@/lib/websocketContext"; +import { NezhaAPI } from "@/types/nezha-api"; + + export default function Servers() { + const { connected, message } = useWebSocketContext() + + if (!connected || !message) { + return ( +

连接中...

+ ) + } + + const nezhaWsData = JSON.parse(message) as NezhaAPI[] + + console.log(nezhaWsData) + return (
diff --git a/vite.config.ts b/vite.config.ts index 4e939e1..bdb68f3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,4 +10,13 @@ export default defineConfig({ "@": path.resolve(__dirname, "./src"), }, }, + server: { + proxy: { + '/api/v1/ws': { + target: 'http://localhost:8008', + changeOrigin: true, + ws: true, + }, + } + } });