mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-08 02:37:46 +08:00
feat(api): count the quota by the CDN's client IP and refuse direct calls
Two optional settings for deployments behind a CDN such as Cloudflare. CLIENT_IP_HEADER names the header that holds the visitor's real IP (cf-connecting-ip on Cloudflare). The per-IP daily quota used the first X-Forwarded-For entry, which visitors can set to anything, so a made-up IP on every request got a fresh quota. ORIGIN_SECRET makes proxy.ts refuse /api requests whose X-Origin-Secret header does not match. The CDN adds the header, so a call that skips the CDN, and could fake the IP header, gets 403. Pages are not checked, which keeps health checks on / working. Both are unset by default, and nothing changes then.
This commit is contained in:
@@ -27,9 +27,19 @@ function getLocale(request: NextRequest): string | undefined {
|
||||
export function proxy(request: NextRequest) {
|
||||
const pathname = request.nextUrl.pathname
|
||||
|
||||
// Skip API routes, static files, and Next.js internals
|
||||
if (pathname.startsWith("/api/")) {
|
||||
// With ORIGIN_SECRET set, API calls must come through the CDN that
|
||||
// adds this header. A call straight to the origin could fake the
|
||||
// CLIENT_IP_HEADER and get a fresh quota for every made-up IP.
|
||||
const secret = process.env.ORIGIN_SECRET
|
||||
if (secret && request.headers.get("x-origin-secret") !== secret) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 })
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Skip static files and Next.js internals
|
||||
if (
|
||||
pathname.startsWith("/api/") ||
|
||||
pathname.startsWith("/_next/") ||
|
||||
pathname.startsWith("/drawio") ||
|
||||
pathname.includes("/favicon") ||
|
||||
@@ -58,6 +68,9 @@ export function proxy(request: NextRequest) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
// Matcher ignoring `/_next/` and `/api/`
|
||||
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
|
||||
// API routes (for ORIGIN_SECRET), and pages without `/_next/` assets
|
||||
matcher: [
|
||||
"/api/:path*",
|
||||
"/((?!api|_next/static|_next/image|favicon.ico).*)",
|
||||
],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user