Skip to content

Commit

Permalink
implemented ratelimiting on submit
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalmishraa committed Jul 29, 2024
1 parent 104eab1 commit 7e1ca98
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 40 deletions.
14 changes: 13 additions & 1 deletion apps/web/app/api/submission/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { LANGUAGE_MAPPING } from "@repo/common/language";
import db from "@/app/db";
import { getServerSession } from "next-auth";
import { authOptions } from "../../lib/auth";
import { isRequestAllowed } from "@/app/lib/redis";


const JUDGE0_URI = process.env.JUDGE0_URI;
Expand All @@ -21,7 +22,18 @@ export async function POST(req: NextRequest) {
status: 401
}
);
}
};

//Check if user is allowed to submit
const allowed = await isRequestAllowed(session.user.id, 60);// 1 minute window for 2 requests
if (!allowed) {
return NextResponse.json(
{
message: "Rate limit exceeded",
status: 429
}
);
};


//get and check the submission input
Expand Down
14 changes: 13 additions & 1 deletion apps/web/app/components/ProblemSubmitBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,19 @@ function SubmitProblem({
activeContestId: contestId,
token: token,
});
console.log("response from proState : ",response.data);

if(response.status === 429){
setStatus(SubmitStatus.FAILED);
toast.error("Try again after sometime");
return;
};

if(response.status != 200){
setStatus(SubmitStatus.FAILED);
toast.error("Failed to submit");
return;
};

pollWithBackoff(response.data.id, 30);
} catch (e) {
//@ts-ignore
Expand Down
38 changes: 0 additions & 38 deletions apps/web/app/lib/rateLimit.ts

This file was deleted.

33 changes: 33 additions & 0 deletions apps/web/app/lib/redis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL!);

redis.on('connect', () => {
console.log('Connected to Redis');
});

redis.on('error', (error) => {
console.error('Redis error:', error);
});

export async function isRequestAllowed(userId: string,timeWindow:number): Promise<boolean> {
const currentTime = Math.floor(Date.now() / 1000);
const key = `rate_limit:${userId}`;

const maxRequests = 2;

const timestamps = await redis.lrange(key, 0, -1);
const validTimestamps = timestamps
.map(Number)
.filter(timestamp => timestamp > currentTime - timeWindow);

if (validTimestamps.length < maxRequests) {
await redis.multi()
.rpush(key, currentTime)
.expire(key, timeWindow)
.exec();
return true;
} else {
return false;
}
}
2 changes: 2 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@upstash/ratelimit": "^2.0.1",
"axios": "^1.7.2",
"bcrypt": "^5.1.1",
"class-variance-authority": "^0.7.0",
Expand All @@ -27,6 +28,7 @@
"react": "^18",
"react-dom": "^18",
"react-toastify": "^10.0.5",
"redis": "^4.7.0",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"vconcol": "^1.0.1"
Expand Down

0 comments on commit 7e1ca98

Please sign in to comment.