UNPKG

express-rate-limiter-ts

Version:

A powerful, flexible and modern rate limiter middleware for Express.js written in TypeScript.

183 lines (182 loc) 6.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.startAdminPanel = startAdminPanel; exports.getRateLimiterStats = getRateLimiterStats; const express_1 = __importDefault(require("express")); function startAdminPanel(store) { const app = (0, express_1.default)(); app.use(express_1.default.json()); // JSON API endpoints app.get('/api/stats', async (_req, res) => { res.json(await store.getStats()); }); app.get('/api/banned', async (_req, res) => { res.json(await store.getBanned()); }); app.post('/api/unban', async (req, res) => { const { key } = req.body; if (key) { await store.unban(key); res.json({ success: true }); } else { res.status(400).json({ success: false, message: 'Key not specified.' }); } }); app.get('/', async (_req, res) => { const stats = await getRateLimiterStats(store); const bannedKeys = Object.keys(stats.banned); res.send(` <!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\" /> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /> <title>WAFGuard - Rate Limiter - Management Panel</title> <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"> <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin> <link href=\"https://fonts.googleapis.com/css2?family=Montserrat:wght@700;400&display=swap\" rel=\"stylesheet\"> <style> body { background: #fff; color: #111; font-family: 'Montserrat', Arial, sans-serif; margin: 0; padding: 0; } .header { display: flex; align-items: center; background: #111; color: #fff; padding: 24px 32px 18px 32px; font-size: 2.2rem; font-weight: 700; letter-spacing: 1px; } .logo { width: 48px; height: 48px; margin-right: 18px; background: #fff; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 2rem; font-weight: bold; color: #111; box-shadow: 0 2px 8px rgba(0,0,0,0.08); } .container { max-width: 900px; margin: 32px auto; padding: 24px; background: #fff; border-radius: 16px; box-shadow: 0 2px 16px rgba(0,0,0,0.07); } h2 { color: #111; margin-top: 32px; margin-bottom: 12px; font-size: 1.3rem; font-weight: 700; letter-spacing: 0.5px; } .stat-box, .ban-box { background: #f7f7f7; border-radius: 8px; padding: 16px; font-size: 1rem; margin-bottom: 24px; font-family: 'Fira Mono', 'Consolas', monospace; color: #222; overflow-x: auto; border: 1px solid #ccc; } .ban-box { border-left: 4px solid #111; } .refresh-btn { background: #111; color: #fff; border: none; border-radius: 6px; padding: 10px 22px; font-size: 1rem; font-weight: 600; cursor: pointer; margin-bottom: 18px; transition: background 0.2s; } .refresh-btn:hover { background: #333; } .unban-btn { background: #e53935; color: #fff; border: none; border-radius: 6px; padding: 6px 18px; font-size: 1rem; font-weight: 700; cursor: pointer; margin-left: auto; margin-bottom: 4px; transition: background 0.2s, color 0.2s; box-shadow: 0 2px 8px rgba(229,57,53,0.08); display: inline-block; } .unban-btn:hover { background: #b71c1c; color: #fff; } </style> </head> <body> <div class=\"header\"> <img class=\"logo\" src=\"https://wafguard.com/logo.png\" alt=\"WAFGuard Logo\" /> WAFGuard <span style=\"font-size:1.1rem;font-weight:400;margin-left:12px;opacity:0.7;\">Rate Limiter - Management Panel</span> </div> <div class=\"container\"> <button class=\"refresh-btn\" onclick=\"window.location.reload()\">Refresh</button> <h2>Statistics</h2> <div class=\"stat-box\">${Object.keys(stats.stats).length ? `<pre>${JSON.stringify(stats.stats, null, 2)}</pre>` : 'No data found.'}</div> <h2>Banned</h2> <div class=\"ban-box\"> ${bannedKeys.length ? bannedKeys.map(key => ` <div style=\"margin-bottom:8px;display:flex;align-items:center;justify-content:space-between;\"> <pre style=\"margin:0;display:inline-block;\">${key}: ${JSON.stringify(stats.banned[key], null, 2)}</pre> <button class=\"unban-btn\" onclick=\"unban('${key}')\">Unban</button> </div> `).join('') : 'There are no bans at the moment.'} </div> </div> <script> function unban(key) { fetch('/api/unban', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key }) }).then(() => window.location.reload()); } </script> </body> </html> `); }); app.listen(9222, () => { // eslint-disable-next-line no-console console.log('Rate Limiter Admin Panel is running at http://localhost:9222'); }); } async function getRateLimiterStats(store) { return { stats: await store.getStats(), banned: await store.getBanned(), }; }