diff --git a/src/index.ts b/src/index.ts index dea6c35f..fd455c2a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { startWorkerCapabilityPolling } from "./services/workerCapabilities"; import { join } from "path"; import { config } from "dotenv"; import { applyCors, isOriginAllowed, readAllowedOrigins } from "./config/cors"; -import { RL_HTTP_API, RL_HTTP_EMOJI_WRITE, RL_HTTP_FILE, RL_HTTP_OUTBOUND, RL_HTTP_PUBLIC, RL_HTTP_UPLOAD, httpRateLimit } from "./middleware/rateLimitHttp"; +import { RL_HTTP_API, RL_HTTP_CHAT_UPLOAD, RL_HTTP_EMOJI_WRITE, RL_HTTP_FILE, RL_HTTP_OUTBOUND, RL_HTTP_PUBLIC, RL_HTTP_UPLOAD, httpRateLimit } from "./middleware/rateLimitHttp"; config({ path: "config.env", override: false }); config({ override: false }); import { consola } from "consola"; @@ -342,7 +342,7 @@ app.use("/api/server", httpRateLimit("http:server", RL_HTTP_UPLOAD), serverRoute app.use("/api/messages", httpRateLimit("http:api", RL_HTTP_API), messagesRouter); // Reads and writes share a mount and need different budgets. Express runs every // matching mount, so without the skip a read is charged to the write budget. -const limitUploadWrites = httpRateLimit("http:upload", RL_HTTP_UPLOAD); +const limitUploadWrites = httpRateLimit("http:upload", RL_HTTP_CHAT_UPLOAD); app.use("/api/uploads/files", httpRateLimit("http:file", RL_HTTP_FILE)); app.use( "/api/uploads", diff --git a/src/middleware/rateLimitHttp.ts b/src/middleware/rateLimitHttp.ts index de5d3b86..4c8e85c9 100644 --- a/src/middleware/rateLimitHttp.ts +++ b/src/middleware/rateLimitHttp.ts @@ -46,6 +46,9 @@ export const RL_HTTP_OUTBOUND: RateLimitRule = { limit: 20, windowMs: 60_000, ba /** Writing bytes to disk, which costs storage rather than only time. */ export const RL_HTTP_UPLOAD: RateLimitRule = { limit: 30, windowMs: 60_000, banMs: 30_000 }; +/** Chat files. A Discord import sends hundreds of them in one go, and each is capped by size. */ +export const RL_HTTP_CHAT_UPLOAD: RateLimitRule = { limit: 300, windowMs: 60_000, banMs: 30_000 }; + /** An import is one gesture that becomes a request per emoji. No `banMs`: the ban is what took the emoji list down with the writes. */ export const RL_HTTP_EMOJI_WRITE: RateLimitRule = { limit: 150, windowMs: 60_000 };