diff --git a/src/middleware.ts b/src/middleware.ts index bf28af1..f1b1bf5 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,23 +1,53 @@ import { authMiddleware, redirectToSignIn } from "@clerk/nextjs"; import { validateRequest } from "./server/unkey"; import { NextResponse } from "next/server"; +import { Ratelimit } from "@upstash/ratelimit"; +import { Redis } from "@upstash/redis"; +import { env } from "./env.mjs"; + +const rateLimit = new Ratelimit({ + redis: Redis.fromEnv(), + limiter: Ratelimit.slidingWindow( + Number(env.UPSTASH_RATELIMIT_REQUESTS), + `${Number(env.UPSTASH_RATELIMIT_SECONDS)}s` + ), + analytics: true, +}); export default authMiddleware({ publicRoutes: ["/", "/api/public/(.*)"], afterAuth: async (auth, req) => { if (!auth.userId && auth.isPublicRoute) { - return NextResponse.next(); + const { success } = await rateLimit.limit(req.ip || ""); + if (success) { + console.log(success); + return NextResponse.next(); + } + return new NextResponse("TOO MANY REQUESTS", { + status: 429, + statusText: "Too many requests!", + }); } if ( req.nextUrl.pathname.includes("/api/webhooks") || req.nextUrl.pathname.includes("/api/private") ) { + const { success } = await rateLimit.limit(req.ip || ""); + const isValid = await validateRequest(req); - if (isValid) { + if (isValid && success) { return NextResponse.next(); - } else { - return new NextResponse("UNAUTHORIZED", { status: 403 }); + } else if (!success) { + return new NextResponse("TOO MANY REQUESTS", { + status: 429, + statusText: "Too many requests!", + }); + } else if (!isValid) { + return new NextResponse("UNAUTHORIZED", { + status: 403, + statusText: "Unauthorized!", + }); } } if (!auth.userId && !auth.isPublicRoute) {