diff --git a/src/backend/ssh/server-stats.ts b/src/backend/ssh/server-stats.ts index 78c5606d..8abda3ea 100644 --- a/src/backend/ssh/server-stats.ts +++ b/src/backend/ssh/server-stats.ts @@ -8,10 +8,7 @@ import {sshData, sshCredentials} from '../database/db/schema.js'; import {eq, and} from 'drizzle-orm'; import { statsLogger } from '../utils/logger.js'; -// Rate limiting -const requestCounts = new Map(); -const RATE_LIMIT_WINDOW = 15 * 60 * 1000; // 15 minutes -const RATE_LIMIT_MAX = 100; // 100 requests per window +// Rate limiting removed - not needed for internal application // Connection pooling interface PooledConnection { @@ -271,27 +268,7 @@ type StatusEntry = { lastChecked: string; }; -// Rate limiting middleware -function rateLimitMiddleware(req: express.Request, res: express.Response, next: express.NextFunction) { - const clientId = req.ip || 'unknown'; - const now = Date.now(); - const clientData = requestCounts.get(clientId); - - if (!clientData || now > clientData.resetTime) { - requestCounts.set(clientId, { count: 1, resetTime: now + RATE_LIMIT_WINDOW }); - return next(); - } - - if (clientData.count >= RATE_LIMIT_MAX) { - return res.status(429).json({ - error: 'Too many requests', - retryAfter: Math.ceil((clientData.resetTime - now) / 1000) - }); - } - - clientData.count++; - next(); -} +// Rate limiting middleware removed // Input validation middleware function validateHostId(req: express.Request, res: express.Response, next: express.NextFunction) { @@ -318,7 +295,6 @@ app.use((req, res, next) => { next(); }); app.use(express.json({ limit: '1mb' })); // Add request size limit -app.use(rateLimitMiddleware); const hostStatuses: Map = new Map(); diff --git a/src/ui/Desktop/Apps/Server/Server.tsx b/src/ui/Desktop/Apps/Server/Server.tsx index 5e732ee0..3f872712 100644 --- a/src/ui/Desktop/Apps/Server/Server.tsx +++ b/src/ui/Desktop/Apps/Server/Server.tsx @@ -88,10 +88,23 @@ export function Server({ if (!cancelled) { setServerStatus(res?.status === 'online' ? 'online' : 'offline'); } - } catch (error) { + } catch (error: any) { console.error('Failed to fetch server status:', error); if (!cancelled) { - setServerStatus('offline'); + // Handle different error types from the new backend + if (error?.response?.status === 503) { + // Server is offline + setServerStatus('offline'); + } else if (error?.response?.status === 504) { + // Timeout - treat as degraded + setServerStatus('offline'); + } else if (error?.response?.status === 404) { + // Host not found + setServerStatus('offline'); + } else { + // Other errors - treat as offline + setServerStatus('offline'); + } toast.error(t('serverStats.failedToFetchStatus')); } } @@ -190,8 +203,21 @@ export function Server({ setServerStatus(res?.status === 'online' ? 'online' : 'offline'); const data = await getServerMetricsById(currentHostConfig.id); setMetrics(data); - } catch { - setServerStatus('offline'); + } catch (error: any) { + // Handle different error types from the new backend + if (error?.response?.status === 503) { + // Server is offline + setServerStatus('offline'); + } else if (error?.response?.status === 504) { + // Timeout - treat as offline + setServerStatus('offline'); + } else if (error?.response?.status === 404) { + // Host not found + setServerStatus('offline'); + } else { + // Other errors - treat as offline + setServerStatus('offline'); + } setMetrics(null); } finally { setIsRefreshing(false); diff --git a/src/ui/Desktop/Navigation/Hosts/Host.tsx b/src/ui/Desktop/Navigation/Hosts/Host.tsx index 94af3e45..e9d7f35a 100644 --- a/src/ui/Desktop/Navigation/Hosts/Host.tsx +++ b/src/ui/Desktop/Navigation/Hosts/Host.tsx @@ -5,7 +5,7 @@ import {ButtonGroup} from "@/components/ui/button-group.tsx"; import {Server, Terminal} from "lucide-react"; import {useTabs} from "@/ui/Desktop/Navigation/Tabs/TabContext.tsx"; import {getServerStatusById} from "@/ui/main-axios.ts"; -import type { SSHHost, HostProps } from '../../../types/index.js'; +import type { HostProps } from '../../../../types/index.js'; export function Host({host}: HostProps): React.ReactElement { const {addTab} = useTabs(); @@ -25,8 +25,18 @@ export function Host({host}: HostProps): React.ReactElement { if (!cancelled) { setServerStatus(res?.status === 'online' ? 'online' : 'offline'); } - } catch { - if (!cancelled) setServerStatus('offline'); + } catch (error: any) { + if (!cancelled) { + if (error?.response?.status === 503) { + setServerStatus('offline'); + } else if (error?.response?.status === 504) { + setServerStatus('degraded'); + } else if (error?.response?.status === 404) { + setServerStatus('offline'); + } else { + setServerStatus('offline'); + } + } } }; diff --git a/src/ui/Mobile/Apps/Navigation/Hosts/Host.tsx b/src/ui/Mobile/Apps/Navigation/Hosts/Host.tsx index a737c6ae..c2242e66 100644 --- a/src/ui/Mobile/Apps/Navigation/Hosts/Host.tsx +++ b/src/ui/Mobile/Apps/Navigation/Hosts/Host.tsx @@ -5,34 +5,7 @@ import {ButtonGroup} from "@/components/ui/button-group.tsx"; import {Server, Terminal} from "lucide-react"; import {getServerStatusById} from "@/ui/main-axios.ts"; import {useTabs} from "@/ui/Mobile/Apps/Navigation/Tabs/TabContext.tsx"; - -interface SSHHost { - id: number; - name: string; - ip: string; - port: number; - username: string; - folder: string; - tags: string[]; - pin: boolean; - authType: string; - password?: string; - key?: string; - keyPassword?: string; - keyType?: string; - enableTerminal: boolean; - enableTunnel: boolean; - enableFileManager: boolean; - defaultPath: string; - tunnelConnections: any[]; - createdAt: string; - updatedAt: string; -} - -interface HostProps { - host: SSHHost; - onHostConnect: () => void; -} +import type { HostProps } from '../../../../../types/index.js'; export function Host({host, onHostConnect}: HostProps): React.ReactElement { const {addTab} = useTabs(); @@ -52,8 +25,18 @@ export function Host({host, onHostConnect}: HostProps): React.ReactElement { if (!cancelled) { setServerStatus(res?.status === 'online' ? 'online' : 'offline'); } - } catch { - if (!cancelled) setServerStatus('offline'); + } catch (error: any) { + if (!cancelled) { + if (error?.response?.status === 503) { + setServerStatus('offline'); + } else if (error?.response?.status === 504) { + setServerStatus('degraded'); + } else if (error?.response?.status === 404) { + setServerStatus('offline'); + } else { + setServerStatus('offline'); + } + } } }; diff --git a/src/ui/Mobile/Navigation/Hosts/Host.tsx b/src/ui/Mobile/Navigation/Hosts/Host.tsx index 7b4ca34e..d13a0f84 100644 --- a/src/ui/Mobile/Navigation/Hosts/Host.tsx +++ b/src/ui/Mobile/Navigation/Hosts/Host.tsx @@ -5,34 +5,7 @@ import {ButtonGroup} from "@/components/ui/button-group.tsx"; import {Server, Terminal} from "lucide-react"; import {getServerStatusById} from "@/ui/main-axios.ts"; import {useTabs} from "@/ui/Mobile/Navigation/Tabs/TabContext.tsx"; - -interface SSHHost { - id: number; - name: string; - ip: string; - port: number; - username: string; - folder: string; - tags: string[]; - pin: boolean; - authType: string; - password?: string; - key?: string; - keyPassword?: string; - keyType?: string; - enableTerminal: boolean; - enableTunnel: boolean; - enableFileManager: boolean; - defaultPath: string; - tunnelConnections: any[]; - createdAt: string; - updatedAt: string; -} - -interface HostProps { - host: SSHHost; - onHostConnect: () => void; -} +import type { HostProps } from '../../../../types/index.js'; export function Host({host, onHostConnect}: HostProps): React.ReactElement { const {addTab} = useTabs(); @@ -52,8 +25,18 @@ export function Host({host, onHostConnect}: HostProps): React.ReactElement { if (!cancelled) { setServerStatus(res?.status === 'online' ? 'online' : 'offline'); } - } catch { - if (!cancelled) setServerStatus('offline'); + } catch (error: any) { + if (!cancelled) { + if (error?.response?.status === 503) { + setServerStatus('offline'); + } else if (error?.response?.status === 504) { + setServerStatus('degraded'); + } else if (error?.response?.status === 404) { + setServerStatus('offline'); + } else { + setServerStatus('offline'); + } + } } };