2024-09-29 16:40:23 -05:00
|
|
|
import { NextResponse } from 'next/server';
|
|
|
|
import { Ratelimit } from '@upstash/ratelimit';
|
|
|
|
import { kv } from '@vercel/kv';
|
|
|
|
|
|
|
|
const ratelimit = new Ratelimit({
|
|
|
|
redis: kv,
|
|
|
|
limiter: Ratelimit.slidingWindow(5, '10 s'),
|
|
|
|
});
|
|
|
|
|
|
|
|
export const config = {
|
|
|
|
matcher: ['/api/:path*'],
|
|
|
|
};
|
|
|
|
|
|
|
|
export default async function combinedMiddleware(request) {
|
|
|
|
const ip = request.ip ?? '127.0.0.1';
|
2024-09-30 19:09:55 -05:00
|
|
|
const pathname = request.nextUrl.pathname;
|
2024-09-30 19:23:15 -05:00
|
|
|
|
2024-09-30 19:09:55 -05:00
|
|
|
// Allow access to .well-known paths
|
|
|
|
if (pathname.startsWith('/.well-known')) {
|
2024-09-29 16:40:23 -05:00
|
|
|
const { success } = await ratelimit.limit(ip);
|
|
|
|
return success
|
|
|
|
? NextResponse.next()
|
|
|
|
: NextResponse.redirect(new URL('/blocked', request.url));
|
|
|
|
}
|
|
|
|
|
2024-09-30 19:28:03 -05:00
|
|
|
// Check if the request is internal
|
|
|
|
if (!isInternalRequest(request)) {
|
2024-09-30 19:09:55 -05:00
|
|
|
return new NextResponse(JSON.stringify({ error: 'Forbidden' }), {
|
|
|
|
status: 403,
|
|
|
|
headers: { 'Content-Type': 'application/json' }
|
|
|
|
});
|
2024-09-29 16:40:23 -05:00
|
|
|
}
|
|
|
|
|
2024-09-30 19:23:15 -05:00
|
|
|
// Apply rate limiting for allowed requests
|
2024-09-29 16:40:23 -05:00
|
|
|
const { success } = await ratelimit.limit(ip);
|
|
|
|
return success
|
|
|
|
? NextResponse.next()
|
|
|
|
: NextResponse.redirect(new URL('/blocked', request.url));
|
2024-09-30 19:28:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function isInternalRequest(request) {
|
|
|
|
// Check if the request is from the same origin
|
|
|
|
const requestHost = request.headers.get('host');
|
|
|
|
const requestProtocol = request.headers.get('x-forwarded-proto') || 'http';
|
|
|
|
const requestOrigin = `${requestProtocol}://${requestHost}`;
|
|
|
|
|
|
|
|
// Check if the request has a referer from the same origin
|
|
|
|
const referer = request.headers.get('referer');
|
|
|
|
|
|
|
|
// Allow requests with no referer (direct API calls from your app)
|
|
|
|
if (!referer) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the referer matches the request origin
|
|
|
|
return referer.startsWith(requestOrigin);
|
2024-09-29 16:40:23 -05:00
|
|
|
}
|