Skip to content

Commit ee1a4fe

Browse files
committed
feat: rate-limit /request and /subscribe
1 parent 59a6e9b commit ee1a4fe

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

src/lib/utils/ratelimit.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Ratelimit } from "@upstash/ratelimit";
2+
import { kv } from "@vercel/kv";
3+
4+
// Rate limiter for AI Upload (5 requests per 15 minutes)
5+
export const aiUploadRatelimit = new Ratelimit({
6+
redis: kv,
7+
limiter: Ratelimit.slidingWindow(5, "900 s"),
8+
});
9+
10+
// Rate limiter for Paper Requests (5 requests per 15 minutes)
11+
export const paperRequestRatelimit = new Ratelimit({
12+
redis: kv,
13+
limiter: Ratelimit.slidingWindow(5, "900 s"),
14+
});
15+
16+
// Rate limiter for Subscriptions (3 requests per hour)
17+
export const subscribeRatelimit = new Ratelimit({
18+
redis: kv,
19+
limiter: Ratelimit.slidingWindow(3, "1 h"),
20+
});

src/middleware.ts

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,48 @@
11
import { type NextRequest, NextResponse } from "next/server";
2-
import { Ratelimit } from "@upstash/ratelimit";
3-
import { kv } from "@vercel/kv";
4-
5-
const ratelimit = new Ratelimit({
6-
redis: kv,
7-
limiter: Ratelimit.slidingWindow(100, "900 s"),
8-
});
2+
import {
3+
aiUploadRatelimit,
4+
paperRequestRatelimit,
5+
subscribeRatelimit,
6+
} from "./lib/utils/ratelimit";
97

108
export const config = {
11-
matcher: "/api/upload",
9+
matcher: ["/api/upload", "/api/request", "/api/subscribe"],
1210
};
1311

1412
export default async function middleware(request: NextRequest) {
1513
const ip = request.ip ?? "127.0.0.1";
16-
const { success } = await ratelimit.limit(ip);
17-
return success
18-
? NextResponse.next()
19-
: NextResponse.json(
14+
const { pathname } = request.nextUrl;
15+
16+
if (pathname === "/api/upload") {
17+
const { success } = await aiUploadRatelimit.limit(ip);
18+
if (!success) {
19+
return NextResponse.json(
2020
{ message: "You can upload a maximum of 5 papers every 15 minutes" },
2121
{ status: 429 },
2222
);
23+
}
24+
}
25+
26+
if (pathname === "/api/request") {
27+
const { success } = await paperRequestRatelimit.limit(ip);
28+
if (!success) {
29+
return NextResponse.json(
30+
{ message: "You can submit a maximum of 5 requests every 15 minutes" },
31+
{ status: 429 },
32+
);
33+
}
34+
}
35+
36+
if (pathname === "/api/subscribe") {
37+
const { success } = await subscribeRatelimit.limit(ip);
38+
if (!success) {
39+
return NextResponse.json(
40+
{ message: "Maximum of 3 newsletter subscriptions per hour" },
41+
{ status: 429 },
42+
);
43+
}
44+
}
45+
46+
return NextResponse.next();
2347
}
48+

0 commit comments

Comments
 (0)