@@ -70,6 +70,7 @@ type ResolvedCountryAccess = Omit<
7070}
7171
7272const IPINFO_PRIVACY_CACHE_TTL_MS = 30 * 60 * 1000
73+ const IPINFO_PRIVACY_CACHE_MAX_ENTRIES = 5000
7374const ipinfoPrivacyCache = new Map <
7475 string ,
7576 { expiresAt : number ; privacy : FreeModeIpPrivacy | null }
@@ -80,7 +81,34 @@ export function extractClientIp(req: NextRequest): string | undefined {
8081 if ( forwardedFor ) {
8182 return forwardedFor . split ( ',' ) [ 0 ] . trim ( )
8283 }
83- return req . headers . get ( 'x-real-ip' ) ?? undefined
84+ return (
85+ req . headers . get ( 'cf-connecting-ip' ) ??
86+ req . headers . get ( 'x-real-ip' ) ??
87+ undefined
88+ )
89+ }
90+
91+ function setIpinfoPrivacyCache (
92+ ip : string ,
93+ privacy : FreeModeIpPrivacy | null ,
94+ ) : void {
95+ const now = Date . now ( )
96+ for ( const [ cachedIp , cached ] of ipinfoPrivacyCache ) {
97+ if ( cached . expiresAt <= now ) {
98+ ipinfoPrivacyCache . delete ( cachedIp )
99+ }
100+ }
101+
102+ while ( ipinfoPrivacyCache . size >= IPINFO_PRIVACY_CACHE_MAX_ENTRIES ) {
103+ const oldestIp = ipinfoPrivacyCache . keys ( ) . next ( ) . value
104+ if ( ! oldestIp ) break
105+ ipinfoPrivacyCache . delete ( oldestIp )
106+ }
107+
108+ ipinfoPrivacyCache . set ( ip , {
109+ expiresAt : now + IPINFO_PRIVACY_CACHE_TTL_MS ,
110+ privacy,
111+ } )
84112}
85113
86114function privacySignalsFromIpinfo (
@@ -123,10 +151,7 @@ export async function lookupIpinfoPrivacy(params: {
123151 const privacy = {
124152 signals,
125153 }
126- ipinfoPrivacyCache . set ( params . ip , {
127- expiresAt : Date . now ( ) + IPINFO_PRIVACY_CACHE_TTL_MS ,
128- privacy,
129- } )
154+ setIpinfoPrivacyCache ( params . ip , privacy )
130155 return privacy
131156}
132157
@@ -218,6 +243,18 @@ export async function getFreeModeCountryAccess(
218243 }
219244 }
220245
246+ if ( ! clientIp ) {
247+ return {
248+ allowed : false ,
249+ countryCode : null ,
250+ blockReason : 'missing_client_ip' ,
251+ cfCountry,
252+ geoipCountry : null ,
253+ ipPrivacy : null ,
254+ hasClientIp : false ,
255+ }
256+ }
257+
221258 const ipPrivacy = await getIpPrivacy ( clientIp , options )
222259 if ( ipPrivacy ?. signals . length ) {
223260 return {
0 commit comments