From 8df72c55e564b10e98102b12333e5d8322f9eaa6 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 26 Aug 2025 17:28:13 +0200 Subject: [PATCH 1/2] add support for CloudFront headers in getLocation --- src/lib/detect.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 2e6a067d..526ea2df 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -119,6 +119,19 @@ export async function getLocation(ip: string = '', headers: Headers, hasPayloadI city, }; } + + // CloudFront headers + if (headers.get('cloudfront-viewer-country')) { + const country = decodeHeader(headers.get('cloudfront-viewer-country')); + const region = decodeHeader(headers.get('cloudfront-viewer-country-region')); + const city = decodeHeader(headers.get('cloudfront-viewer-city')); + + return { + country, + region: getRegionCode(country, region), + city, + }; + } } // Database lookup From 58c2d068e7a2c4369f4bae848d5319df8b3f33ae Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 27 Aug 2025 17:47:24 +0200 Subject: [PATCH 2/2] refactor getLocation to use lookup array for cleaner header extraction --- src/lib/detect.ts | 69 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 526ea2df..ee9d2603 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -15,6 +15,27 @@ import { safeDecodeURIComponent } from '@/lib/url'; const MAXMIND = 'maxmind'; +const PROVIDER_HEADERS = [ + // Cloudflare headers + { + countryHeader: 'cf-ipcountry', + regionHeader: 'cf-region-code', + cityHeader: 'cf-ipcity', + }, + // Vercel headers + { + countryHeader: 'x-vercel-ip-country', + regionHeader: 'x-vercel-ip-country-region', + cityHeader: 'x-vercel-ip-city', + }, + // CloudFront headers + { + countryHeader: 'cloudfront-viewer-country', + regionHeader: 'cloudfront-viewer-country-region', + cityHeader: 'cloudfront-viewer-city', + }, +]; + export function getIpAddress(headers: Headers) { const customHeader = process.env.CLIENT_IP_HEADER; @@ -94,43 +115,19 @@ export async function getLocation(ip: string = '', headers: Headers, hasPayloadI } if (!hasPayloadIP && !process.env.SKIP_LOCATION_HEADERS) { - // Cloudflare headers - if (headers.get('cf-ipcountry')) { - const country = decodeHeader(headers.get('cf-ipcountry')); - const region = decodeHeader(headers.get('cf-region-code')); - const city = decodeHeader(headers.get('cf-ipcity')); + for (const provider of PROVIDER_HEADERS) { + const countryHeader = headers.get(provider.countryHeader); + if (countryHeader) { + const country = decodeHeader(countryHeader); + const region = decodeHeader(headers.get(provider.regionHeader)); + const city = decodeHeader(headers.get(provider.cityHeader)); - return { - country, - region: getRegionCode(country, region), - city, - }; - } - - // Vercel headers - if (headers.get('x-vercel-ip-country')) { - const country = decodeHeader(headers.get('x-vercel-ip-country')); - const region = decodeHeader(headers.get('x-vercel-ip-country-region')); - const city = decodeHeader(headers.get('x-vercel-ip-city')); - - return { - country, - region: getRegionCode(country, region), - city, - }; - } - - // CloudFront headers - if (headers.get('cloudfront-viewer-country')) { - const country = decodeHeader(headers.get('cloudfront-viewer-country')); - const region = decodeHeader(headers.get('cloudfront-viewer-country-region')); - const city = decodeHeader(headers.get('cloudfront-viewer-city')); - - return { - country, - region: getRegionCode(country, region), - city, - }; + return { + country, + region: getRegionCode(country, region), + city, + }; + } } }