From de90f392a457cb564d9501cd32080849265f1a38 Mon Sep 17 00:00:00 2001 From: Chris Funderburg Date: Sun, 18 Oct 2026 01:16:42 +0100 Subject: [PATCH] fix(server): stop rate limiting page and folder reads as writes fileOperationLimiter (30/min) was mounted on all of /api/pages and /api/folders, so every read shared the write budget and writes counted twice. Normal browsing hit 429 and the client showed 'Failed to load pages from folder'. Each route now has one limiter: readLimiter for reads, fileOperationLimiter for writes. GET /api/folders gets readLimiter, as it had no route-level limiter. --- server/src/index.ts | 6 +++--- server/src/routes/folders.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/index.ts b/server/src/index.ts index 3064b2d..c6539f2 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -17,7 +17,6 @@ import { staticFileLimiter, aiLimiter, readLimiter, - fileOperationLimiter, searchLimiter, fileTransferLimiter, authLimiter, @@ -267,8 +266,9 @@ app.get("/api", (req: Request, res: Response) => { // Routes app.use("/api/auth", authLimiter, authRoutes); // Auth routes (public, rate limited) -app.use("/api/folders", fileOperationLimiter, requireAuth, folderRoutes); // Protected -app.use("/api/pages", fileOperationLimiter, requireAuth, pageRoutes); // Protected +// Folder and page routes set their own limiters per route (read vs write) +app.use("/api/folders", requireAuth, folderRoutes); // Protected +app.use("/api/pages", requireAuth, pageRoutes); // Protected app.use("/api/templates", readLimiter, requireAuth, templatesRoutes); // Protected app.use("/api/search", searchLimiter, requireAuth, searchRoutes); // Protected app.use("/api/attachments", fileTransferLimiter, requireAuth, attachmentRoutes); // Protected diff --git a/server/src/routes/folders.ts b/server/src/routes/folders.ts index 5861d10..c4ad3ad 100644 --- a/server/src/routes/folders.ts +++ b/server/src/routes/folders.ts @@ -1,10 +1,10 @@ import { Router } from "express"; import * as folderController from "../controllers/folderController"; -import { fileOperationLimiter } from "../middleware/rateLimiters"; +import { fileOperationLimiter, readLimiter } from "../middleware/rateLimiters"; const router = Router(); -router.get("/", folderController.getFolderTree); +router.get("/", readLimiter, folderController.getFolderTree); router.post("/", fileOperationLimiter, folderController.createFolder); router.delete("/*path", fileOperationLimiter, folderController.deleteFolder); router.put("/rename", fileOperationLimiter, folderController.renameFolder);