11import { setRateLimitHeaders } from "@arcjet/decorate" ;
2- import { isDevelopment } from "@arcjet/env" ;
3- import ip from "@arcjet/ip" ;
2+ import type { ArcjetDecision } from "@arcjet/next" ;
43import { type NextRequest , NextResponse } from "next/server" ;
5- import type { Session } from "next-auth" ;
64import arcjet , { fixedWindow , shield } from "@/lib/arcjet" ;
75import { auth } from "@/lib/auth" ;
86
@@ -18,47 +16,42 @@ const aj = arcjet.withRule(
1816 } ) ,
1917) ;
2018
21- // Returns ad-hoc rules depending on whether the session is present. You could
22- // inspect more details about the session to dynamically adjust the rate limit.
23- function getClient ( session : Session | null ) {
24- if ( session ?. user ) {
25- return aj . withRule (
26- fixedWindow ( {
27- mode : "LIVE" ,
28- max : 5 ,
29- window : "60s" ,
30- } ) ,
31- ) ;
32- } else {
33- return aj . withRule (
34- fixedWindow ( {
35- mode : "LIVE" ,
36- max : 2 ,
37- window : "60s " ,
38- } ) ,
39- ) ;
40- }
41- }
19+ // Define an augmented client for rate limiting users
20+ const ajForUser = aj . withRule (
21+ fixedWindow ( {
22+ // fingerprint requests by user ID
23+ characteristics : [ "userId" ] ,
24+ mode : "LIVE" ,
25+ max : 5 ,
26+ window : "60s" ,
27+ } ) ,
28+ ) ;
29+
30+ // Define an augmented client for rate limiting guests
31+ const ajForGuest = aj . withRule (
32+ fixedWindow ( {
33+ // fingerprint requests by ip address (default unless set globally)
34+ characteristics : [ "ip.src" ] ,
35+ mode : "LIVE " ,
36+ max : 2 ,
37+ window : "60s" ,
38+ } ) ,
39+ ) ;
4240
4341export async function POST ( req : NextRequest ) {
4442 // Get the session
4543 const session = await auth ( ) ;
4644
4745 console . log ( "Session: " , session ) ;
4846
49- // Next.js 15 doesn't provide the IP address in the request object so we use
50- // the Arcjet utility package to parse the headers and find it. If we're
51- // running in development mode, we'll use a local IP address.
52- const userIp = isDevelopment ( process . env ) ? "127.0.0.1" : ip ( req ) ;
47+ let decision : ArcjetDecision ;
5348
5449 // Use the user ID if the user is logged in, otherwise use the IP address
55- const fingerprint = session ?. user ?. id ?? userIp ;
56-
57- // The protect method returns a decision object that contains information
58- // about the request.
59- const decision = await getClient ( session ) . protect ( req , {
60- fingerprint,
61- } ) ;
50+ if ( session ?. user ?. id ) {
51+ decision = await ajForUser . protect ( req , { userId : session . user . id } ) ;
52+ } else {
53+ decision = await ajForGuest . protect ( req ) ;
54+ }
6255
6356 console . log ( "Arcjet decision: " , decision ) ;
6457
0 commit comments