From a755bf352b3462fb8c4116b5b87030d56a35000e Mon Sep 17 00:00:00 2001 From: Nimatstar Date: Sun, 10 May 2026 20:58:05 +0100 Subject: [PATCH 1/2] feat: add ThrottleMiddleware --- .../throttle/throttle.middleware.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/middleware/throttle/throttle.middleware.ts diff --git a/src/middleware/throttle/throttle.middleware.ts b/src/middleware/throttle/throttle.middleware.ts new file mode 100644 index 00000000..ea75ebd1 --- /dev/null +++ b/src/middleware/throttle/throttle.middleware.ts @@ -0,0 +1,25 @@ +import { Injectable, NestMiddleware, HttpException, HttpStatus } from '@nestjs/common'; +import { Request, Response, NextFunction } from 'express'; + +const hits = new Map(); +const LIMIT = 100; +const WINDOW_MS = 60_000; + +@Injectable() +export class ThrottleMiddleware implements NestMiddleware { + use(req: Request, res: Response, next: NextFunction): void { + const key = (req.headers['x-forwarded-for'] as string)?.split(',')[0].trim() ?? req.ip ?? 'unknown'; + const now = Date.now(); + const entry = hits.get(key); + if (!entry || now > entry.reset) { + hits.set(key, { count: 1, reset: now + WINDOW_MS }); + return next(); + } + if (entry.count >= LIMIT) { + res.setHeader('Retry-After', Math.ceil((entry.reset - now) / 1000)); + throw new HttpException('Too Many Requests', HttpStatus.TOO_MANY_REQUESTS); + } + entry.count++; + next(); + } +} \ No newline at end of file From 44e6d3ecf4ec2660e279aa3387bc9ffe8689b1a1 Mon Sep 17 00:00:00 2001 From: Nimatstar Date: Sun, 10 May 2026 20:58:06 +0100 Subject: [PATCH 2/2] chore: add branch-rules.yml --- .github/branch-rules.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/branch-rules.yml diff --git a/.github/branch-rules.yml b/.github/branch-rules.yml new file mode 100644 index 00000000..e7ec3469 --- /dev/null +++ b/.github/branch-rules.yml @@ -0,0 +1,8 @@ +# Branch protection rules +rules: + - pattern: main + required_status_checks: + - CI + required_approving_review_count: 1 + dismiss_stale_reviews: true + restrict_pushes: true \ No newline at end of file