forked from solana-foundation/explorer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmiddleware.ts
More file actions
57 lines (45 loc) · 2.02 KB
/
middleware.ts
File metadata and controls
57 lines (45 loc) · 2.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { isEnvEnabled } from '@utils/env';
import { checkBotId } from 'botid/server';
import { type NextRequest, NextResponse } from 'next/server';
import { Logger } from '@/app/shared/lib/logger';
const BOT_RESPONSE = { body: { error: 'Access denied: request identified as automated bot' }, status: 401 } as const;
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
if (!isEnvEnabled(process.env.NEXT_PUBLIC_BOTID_ENABLED)) {
return NextResponse.next();
}
// Allow requests without x-is-human header (direct API calls)
if (!request.headers.has('x-is-human')) {
Logger.info('[middleware] No x-is-human header, allowing', { pathname });
return NextResponse.next();
}
// Verify requests with x-is-human header (browser requests via BotIdClient)
const verification = await checkBotId({
developmentOptions: {
bypass: isEnvEnabled(process.env.NEXT_PUBLIC_BOTID_SIMULATE_BOT) ? 'BAD-BOT' : undefined,
},
});
Logger.info('[middleware] BotId verification', {
bypassed: verification.bypassed,
isBot: verification.isBot,
isHuman: verification.isHuman,
isVerifiedBot: verification.isVerifiedBot,
pathname,
});
// Block bots only when challenge mode is enabled
if (verification.isBot) {
Logger.warn('[middleware] Bot detected', { pathname });
if (isEnvEnabled(process.env.NEXT_PUBLIC_BOTID_CHALLENGE_MODE_ENABLED)) {
Logger.error(new Error('[middleware] Challenge mode enabled, blocking'), { pathname });
return NextResponse.json(BOT_RESPONSE.body, { status: BOT_RESPONSE.status });
}
} else {
Logger.info('[middleware] Human verified', { pathname });
}
return NextResponse.next();
}
export const config = {
matcher: ['/api/:path*'],
};
// BotIdClient protected routes - only API routes need protection
export const botIdProtectedRoutes: { path: string; method: string }[] = [{ method: '*', path: '/api/*' }];