Skip to content

Commit c852919

Browse files
committed
fix: centralize ratelimiting
1 parent 39df914 commit c852919

File tree

5 files changed

+38
-27
lines changed

5 files changed

+38
-27
lines changed

claim-db-worker/app/api/analytics/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { NextRequest, NextResponse } from "next/server";
22
import { getEnv } from "@/lib/env";
3-
import { getClientIP } from "@/lib/utils";
3+
import { buildRateLimitKey } from "@/lib/server/ratelimit";
44

55
export async function POST(request: NextRequest) {
66
const env = getEnv();
77

88
const url = new URL(request.url);
9-
const key = `${getClientIP(request)}:${request.url}`;
9+
const key = buildRateLimitKey(request);
1010

1111
// --- Simple rate limiting ---
1212
const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key });

claim-db-worker/app/api/auth/callback/route.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NextRequest } from "next/server";
1+
import { NextRequest, NextResponse } from "next/server";
22
import { getEnv } from "@/lib/env";
33
import { exchangeCodeForToken, validateProject } from "@/lib/auth-utils";
44
import {
@@ -7,6 +7,7 @@ import {
77
getBaseUrl,
88
} from "@/lib/response-utils";
99
import { transferProject } from "@/lib/project-transfer";
10+
import { buildRateLimitKey } from "@/lib/server/ratelimit";
1011

1112
async function sendServerAnalyticsEvent(
1213
event: string,
@@ -46,21 +47,25 @@ async function sendServerAnalyticsEvent(
4647
export async function GET(request: NextRequest) {
4748
try {
4849
const env = getEnv();
49-
const { searchParams } = new URL(request.url);
50+
const url = new URL(request.url);
51+
const { searchParams } = url;
5052

5153
const code = searchParams.get("code");
5254
const state = searchParams.get("state");
5355
const projectID = searchParams.get("projectID");
5456

55-
// Rate limiting
56-
const rateLimitResult = await env.CLAIM_DB_RATE_LIMITER.limit({
57-
key: request.url,
58-
});
59-
if (!rateLimitResult.success) {
60-
return redirectToError(
61-
request,
62-
"Rate Limited",
63-
"We're experiencing high demand. Please try again later."
57+
const key = buildRateLimitKey(request);
58+
59+
// --- Simple rate limiting ---
60+
const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key });
61+
if (!success) {
62+
return NextResponse.json(
63+
{
64+
error: "rate_limited",
65+
message: "Rate limit exceeded. Please try again later.",
66+
path: url.pathname,
67+
},
68+
{ status: 429 }
6469
);
6570
}
6671

claim-db-worker/app/api/claim/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { NextRequest, NextResponse } from "next/server";
22
import { getEnv } from "@/lib/env";
33
import { sendAnalyticsEvent } from "@/lib/analytics";
4-
import { getClientIP } from "@/lib/utils";
4+
import { buildRateLimitKey } from "@/lib/server/ratelimit";
55

66
export async function GET(request: NextRequest) {
77
const env = getEnv();
8+
89
const url = new URL(request.url);
9-
const key = `${getClientIP(request)}:${request.url}`;
10+
const key = buildRateLimitKey(request);
1011

1112
// --- Simple rate limiting ---
1213
const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key });
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { NextRequest } from "next/server";
2+
3+
export function getClientIP(req: NextRequest): string {
4+
// OpenNext on CF Workers exposes the Request headers directly
5+
// Consider: prefer CF header in prod; only then fall back to XFF/X-Real-IP/Forwarded.
6+
return (
7+
req.headers.get("cf-connecting-ip") ||
8+
req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ||
9+
req.headers.get("x-real-ip") ||
10+
"unknown-ip"
11+
);
12+
}
13+
14+
export function buildRateLimitKey(req: NextRequest) {
15+
const url = new URL(req.url);
16+
return `${req.method}:${getClientIP(req)}:${url.pathname}`;
17+
}

claim-db-worker/lib/utils.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { NextRequest } from "next/server";
2-
31
export const cookieUtils = {
42
set: (name: string, value: string, days: number = 1) => {
53
const expires = new Date();
@@ -24,13 +22,3 @@ export const cookieUtils = {
2422
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;
2523
},
2624
};
27-
28-
export function getClientIP(req: NextRequest): string {
29-
// OpenNext on CF Workers exposes the Request headers directly
30-
return (
31-
req.headers.get("cf-connecting-ip") ||
32-
req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ||
33-
req.headers.get("x-real-ip") ||
34-
"unknown-ip"
35-
);
36-
}

0 commit comments

Comments
 (0)