Skip to content
This repository was archived by the owner on Oct 5, 2024. It is now read-only.

Commit 122b785

Browse files
Improve rate limits
1 parent 357c7f4 commit 122b785

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

backend/src/lib/websocket.ts

+39-17
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ const messageSchema = z.object({
1313

1414
// TODO: Overhaul
1515

16-
const connections = new Map<string, any>();
17-
const limiter = {
18-
timeWindowMs: 60 * 1000,
19-
limit: 100,
16+
let connections = new Map<string, any>();
17+
18+
type RateLimit = {
19+
count: number;
20+
};
21+
22+
const generalRateLimit = {
23+
timeWindowMs: 10000,
24+
count: 10,
25+
};
26+
const globalChatRateLimit: RateLimit = {
27+
count: 1,
2028
};
2129

2230
function initWebsocket(wss: WebSocketServer) {
@@ -51,12 +59,15 @@ function initWebsocket(wss: WebSocketServer) {
5159

5260
ws.on("message", async (reqData: string) => {
5361
try {
54-
const exceededRateLimit = await checkRateLimit(connection!);
62+
const exceededRateLimit = await handleRateLimit(connection!);
5563
if (exceededRateLimit) {
56-
return ws.send(JSON.stringify({ error: { message: "Rate limit exceeded" } }));
64+
return ws.send(JSON.stringify({ error: { message: "Rate limit exceeded, slow down" } }));
5765
}
5866

59-
await validateSession(ws, sessionId);
67+
const sessionValid = await validateSession(sessionId);
68+
if (!sessionValid) {
69+
return ws.send(JSON.stringify({ error: { message: "Invalid session" } }));
70+
}
6071

6172
let reqJson = JSON.parse(reqData);
6273
let parsed = messageSchema.safeParse(reqJson);
@@ -68,7 +79,10 @@ function initWebsocket(wss: WebSocketServer) {
6879

6980
switch (type) {
7081
case "globalMessage": {
71-
// TODO: Add global chat rate limits
82+
const exceededRateLimit = await checkRateLimit(connection!, globalChatRateLimit);
83+
if (exceededRateLimit) {
84+
return ws.send(JSON.stringify({ error: { message: "Rate limit exceeded, slow down" } }));
85+
}
7286
handleGlobalMessage(ws, wss, data, user);
7387
break;
7488
}
@@ -149,26 +163,25 @@ async function handleChatMessage(ws: WebSocket, data: any, user: User) {
149163
}
150164
}
151165

152-
async function validateSession(ws: WebSocket, sessionId: string | string[]) {
166+
async function validateSession(sessionId: string | string[]): Promise<boolean> {
153167
if (Array.isArray(sessionId)) {
154-
ws.close();
155-
return;
168+
return false;
156169
}
157170
const { session, user } = await lucia.validateSession(sessionId);
158171
if (!session || !user) {
159-
ws.close();
160-
return;
172+
return false;
173+
} else {
174+
return true;
161175
}
162176
}
163177

164-
async function checkRateLimit(connection: any): Promise<boolean> {
165-
console.log(connection);
178+
async function handleRateLimit(connection: any): Promise<boolean> {
166179
const now = Date.now();
167180
const elapsedTime = now - connection.lastMessageTime;
168181

169-
if (elapsedTime < limiter.timeWindowMs) {
182+
if (elapsedTime < generalRateLimit.timeWindowMs) {
170183
connection.count++;
171-
if (connection.count > limiter.limit) {
184+
if (connection.count > generalRateLimit.count) {
172185
return true;
173186
}
174187
} else {
@@ -178,6 +191,15 @@ async function checkRateLimit(connection: any): Promise<boolean> {
178191
return false;
179192
}
180193

194+
async function checkRateLimit(connection: any, rateLimit: RateLimit): Promise<boolean> {
195+
console.log(connection.count > rateLimit.count);
196+
if (connection.count > rateLimit.count) {
197+
return true;
198+
} else {
199+
return false;
200+
}
201+
}
202+
181203
function broadcast(wss: WebSocketServer, data: any, skip: WebSocket | null) {
182204
wss.clients;
183205
wss.clients.forEach((client) => {

0 commit comments

Comments
 (0)