Skip to content

Commit

Permalink
add API rate limiting and fix ambiguous regexp
Browse files Browse the repository at this point in the history
  • Loading branch information
kguzek committed Jun 10, 2024
1 parent 8bb250c commit 94353de
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 453 deletions.
1 change: 1 addition & 0 deletions api/v1/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"cron": "^3.1.7",
"dotenv": "^16.0.1",
"express": "^4.17.3",
"express-rate-limit": "^7.3.1",
"express-ws": "^5.0.2",
"jsonwebtoken": "^9.0.0",
"mysql2": "^3.9.8",
Expand Down
22 changes: 21 additions & 1 deletion api/v1/src/middleware/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import { Request, Response } from "express";
import { rateLimit } from "express-rate-limit";
import { authMiddleware } from "./auth";
import { headerMiddleware } from "./headers";
import { loggingMiddleware } from "./logging";
import { STATUS_CODES, logResponse } from "../util";

const code = 429;
const statusMessage = `${code} ${STATUS_CODES[code]}`;

export default function getMiddleware() {
return [loggingMiddleware, headerMiddleware, authMiddleware];
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 mins
limit: 100, // 100 requests per 15 mins
standardHeaders: true,
legacyHeaders: false,
statusCode: code,
message: (_req: Request, res: Response) => {
logResponse(res, statusMessage);
return {
[statusMessage]: "You have sent too many requests recently. Try again later."
};
},
});

return [loggingMiddleware, limiter, headerMiddleware, authMiddleware];
}
7 changes: 4 additions & 3 deletions api/v1/src/torrentClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,13 @@ export class TorrentClient {
method,
arguments: args,
},
headers: { [SESSION_ID_HEADER_NAME]: this.sessionId },
headers: { [SESSION_ID_HEADER_NAME]: this.sessionId ?? "" },
});
} catch (error) {
res = (error as AxiosError).response;
if (!res) {
throw new Error("Could not obtain a response from the torrent client.");
console.error("Could not obtain a response from the torrent client.");
throw error;
}
if (method !== "session-get") {
if (res.status === 409) {
Expand All @@ -124,7 +125,7 @@ export class TorrentClient {
logger.error(`Client response: ${res.status} ${res.statusText}`);
}
}
return res.data;
return res.data as TorrentResponse<T>;
}

async getTorrentInfo() {
Expand Down
13 changes: 8 additions & 5 deletions api/v1/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ const logger = getLogger(__filename);

const DOWNLOAD_STATUS_MAP = { 4: DownloadStatus.PENDING, 6: DownloadStatus.COMPLETE } as const;

const STATUS_CODES: { [code: number]: string } = {
export const STATUS_CODES: { [code: number]: string } = {
200: "OK",
201: "Created",
400: "Bad Request",
401: "Unauthorised",
403: "Forbidden",
404: "Not Found",
429: "Too Many Requests",
500: "Internal Server Error",
};
} as const;

type StatusCode = keyof typeof STATUS_CODES;

const TORRENT_NAME_PATTERN = /^(.+)(?:\.|\s|\+)S0?(\d+)E0?(\d+)/;

Expand All @@ -33,7 +36,7 @@ export async function updateEndpoint(endpointClass: ModelType) {
logger.debug(`Updated endpoint '${endpoint}'`);
}

const logResponse = (res: Response, message: string) =>
export const logResponse = (res: Response, message: string) =>
logger.response(message, {
ip: (res as any).ip,
});
Expand All @@ -42,7 +45,7 @@ const logResponse = (res: Response, message: string) =>
export function sendOK(
res: Response,
data: object | object[] | null,
code: number = 200
code: StatusCode = 200
) {
logResponse(res, `${code} ${STATUS_CODES[code] ?? STATUS_CODES[200]}`);
res.status(code).json(data);
Expand All @@ -54,7 +57,7 @@ export function sendOK(
*/
export function sendError(
res: Response,
code: number,
code: StatusCode,
error: { message: string } = { message: "Unknown error." }
) {
const codeDescription = `${code} ${STATUS_CODES[code] ?? STATUS_CODES[500]}`;
Expand Down
Loading

0 comments on commit 94353de

Please sign in to comment.