mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 17:41:56 +08:00
fix: websocket proxy
This commit is contained in:
parent
1bda0cc3b7
commit
d1558b71c4
@ -3,7 +3,6 @@ import { useState, useEffect, useRef, useCallback } from "react";
|
|||||||
export interface WebSocketHook {
|
export interface WebSocketHook {
|
||||||
socket: WebSocket | null;
|
socket: WebSocket | null;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
onlineCount: number;
|
|
||||||
message: string | null;
|
message: string | null;
|
||||||
sendMessage: (msg: string) => void;
|
sendMessage: (msg: string) => void;
|
||||||
}
|
}
|
||||||
@ -12,7 +11,6 @@ export default function useWebSocket(url: string): WebSocketHook {
|
|||||||
const [socket, setSocket] = useState<WebSocket | null>(null);
|
const [socket, setSocket] = useState<WebSocket | null>(null);
|
||||||
const [message, setMessage] = useState<string | null>(null);
|
const [message, setMessage] = useState<string | null>(null);
|
||||||
const [connected, setConnected] = useState<boolean>(false);
|
const [connected, setConnected] = useState<boolean>(false);
|
||||||
const [onlineCount, setOnlineCount] = useState<number>(0);
|
|
||||||
const socketRef = useRef<WebSocket | null>(null);
|
const socketRef = useRef<WebSocket | null>(null);
|
||||||
const reconnectAttempts = useRef<number>(0);
|
const reconnectAttempts = useRef<number>(0);
|
||||||
const reconnectTimeout = useRef<NodeJS.Timeout | null>(null);
|
const reconnectTimeout = useRef<NodeJS.Timeout | null>(null);
|
||||||
@ -32,28 +30,37 @@ export default function useWebSocket(url: string): WebSocketHook {
|
|||||||
|
|
||||||
ws.onmessage = (event: MessageEvent) => {
|
ws.onmessage = (event: MessageEvent) => {
|
||||||
setMessage(event.data);
|
setMessage(event.data);
|
||||||
const msgJson = JSON.parse(event.data);
|
|
||||||
if (msgJson.type === "live") {
|
|
||||||
setOnlineCount(msgJson.data.count);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onerror = (error) => {
|
ws.onerror = (error) => {
|
||||||
console.error("WebSocket Error:", error);
|
console.error("WebSocket Error:", error);
|
||||||
|
// 在错误发生时主动关闭连接,触发重连
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onclose = () => {
|
ws.onclose = () => {
|
||||||
setConnected(false);
|
setConnected(false);
|
||||||
|
// 清理当前的 socket
|
||||||
|
socketRef.current = null;
|
||||||
|
|
||||||
if (!isUnmounted.current) {
|
if (!isUnmounted.current) {
|
||||||
// Attempt to reconnect
|
// 检查是否已经在重连中
|
||||||
if (reconnectAttempts.current < 5) {
|
if (reconnectTimeout.current) {
|
||||||
const timeout = Math.pow(2, reconnectAttempts.current) * 1000; // Exponential backoff
|
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;
|
reconnectAttempts.current += 1;
|
||||||
|
console.log(`Attempting to reconnect in ${timeout/1000} seconds...`);
|
||||||
reconnectTimeout.current = setTimeout(() => {
|
reconnectTimeout.current = setTimeout(() => {
|
||||||
connect();
|
connect();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
} else {
|
} 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 };
|
||||||
}
|
}
|
14
src/lib/websocketContext.tsx
Normal file
14
src/lib/websocketContext.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { createContext, useContext } from "react";
|
||||||
|
import { WebSocketHook } from "../hooks/use-websocket";
|
||||||
|
|
||||||
|
export const WebSocketContext = createContext<WebSocketHook | undefined>(undefined);
|
||||||
|
|
||||||
|
export const useWebSocketContext = (): WebSocketHook => {
|
||||||
|
const context = useContext(WebSocketContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
"useWebSocketContext must be used within a WebSocketProvider",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
@ -1,25 +1,14 @@
|
|||||||
import { createContext, useContext, ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import useWebSocket, { WebSocketHook } from "./useWebsocket";
|
import useWebSocket from "../hooks/use-websocket";
|
||||||
|
import { WebSocketContext } from "./websocketContext";
|
||||||
|
|
||||||
interface WebSocketProviderProps {
|
interface WebSocketProviderProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WebSocketContext = createContext<WebSocketHook | undefined>(undefined);
|
|
||||||
|
|
||||||
export const WebSocketProvider = ({ children }: WebSocketProviderProps) => {
|
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 (
|
return (
|
||||||
<WebSocketContext.Provider value={ws}>{children}</WebSocketContext.Provider>
|
<WebSocketContext.Provider value={ws}>{children}</WebSocketContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useWebSocketContext = (): WebSocketHook => {
|
|
||||||
const context = useContext(WebSocketContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useWebSocketContext must be used within a WebSocketProvider",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
};
|
|
||||||
|
@ -1,4 +1,20 @@
|
|||||||
|
import { useWebSocketContext } from "@/lib/websocketContext";
|
||||||
|
import { NezhaAPI } from "@/types/nezha-api";
|
||||||
|
|
||||||
|
|
||||||
export default function Servers() {
|
export default function Servers() {
|
||||||
|
const { connected, message } = useWebSocketContext()
|
||||||
|
|
||||||
|
if (!connected || !message) {
|
||||||
|
return (
|
||||||
|
<p>连接中...</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const nezhaWsData = JSON.parse(message) as NezhaAPI[]
|
||||||
|
|
||||||
|
console.log(nezhaWsData)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-5xl px-4 lg:px-0">
|
<div className="mx-auto w-full max-w-5xl px-4 lg:px-0">
|
||||||
<div className="flex justify-between mb-4 mt-4 items-center">
|
<div className="flex justify-between mb-4 mt-4 items-center">
|
||||||
|
@ -10,4 +10,13 @@ export default defineConfig({
|
|||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/api/v1/ws': {
|
||||||
|
target: 'http://localhost:8008',
|
||||||
|
changeOrigin: true,
|
||||||
|
ws: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user