From a4a9d6c227bdd93c4e260b73027adeb3fa01238a Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 16 Sep 2025 21:23:08 -0700 Subject: [PATCH] Added stripPort function. Reorganized constants. --- src/lib/constants.ts | 47 --------------------------- src/lib/detect.ts | 75 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index bb2c62c0..136f8511 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -215,41 +215,12 @@ export const SHARE_ID_REGEX = /^[a-zA-Z0-9]{8,50}$/; export const DATETIME_REGEX = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{3}(Z|\+[0-9]{2}:[0-9]{2})?)?$/; -export const DESKTOP_SCREEN_WIDTH = 1920; -export const LAPTOP_SCREEN_WIDTH = 1024; -export const MOBILE_SCREEN_WIDTH = 479; - export const URL_LENGTH = 500; export const PAGE_TITLE_LENGTH = 500; export const EVENT_NAME_LENGTH = 50; export const UTM_PARAMS = ['utm_campaign', 'utm_content', 'utm_medium', 'utm_source', 'utm_term']; -export const DESKTOP_OS = [ - 'BeOS', - 'Chrome OS', - 'Linux', - 'Mac OS', - 'Open BSD', - 'OS/2', - 'QNX', - 'Sun OS', - 'Windows 10', - 'Windows 2000', - 'Windows 3.11', - 'Windows 7', - 'Windows 8', - 'Windows 8.1', - 'Windows 95', - 'Windows 98', - 'Windows ME', - 'Windows Server 2003', - 'Windows Vista', - 'Windows XP', -]; - -export const MOBILE_OS = ['Amazon OS', 'Android OS', 'BlackBerry OS', 'iOS', 'Windows Mobile']; - export const OS_NAMES = { 'Android OS': 'Android', 'Chrome OS': 'ChromeOS', @@ -289,24 +260,6 @@ export const BROWSERS = { yandexbrowser: 'Yandex', } as const; -// The order here is important and influences how IPs are detected by lib/detect.ts -// Please do not change the order unless you know exactly what you're doing - read https://developers.cloudflare.com/fundamentals/reference/http-headers/ -export const IP_ADDRESS_HEADERS = [ - 'x-client-ip', - 'x-forwarded-for', - 'cf-connecting-ip', // This should be *after* x-forwarded-for, so that x-forwarded-for is respected if present - 'do-connecting-ip', - 'fastly-client-ip', - 'true-client-ip', - 'x-real-ip', - 'x-cluster-client-ip', - 'x-forwarded', - 'forwarded', - 'x-appengine-user-ip', - 'x-nf-client-connection-ip', - 'x-real-ip', -]; - export const SOCIAL_DOMAINS = [ 'bsky.app', 'facebook.com', diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 897ebe6b..2a8b5c8d 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -3,18 +3,57 @@ import { browserName, detectOS } from 'detect-browser'; import isLocalhost from 'is-localhost-ip'; import ipaddr from 'ipaddr.js'; import maxmind from 'maxmind'; -import { - DESKTOP_OS, - DESKTOP_SCREEN_WIDTH, - IP_ADDRESS_HEADERS, - LAPTOP_SCREEN_WIDTH, - MOBILE_OS, - MOBILE_SCREEN_WIDTH, -} from './constants'; import { safeDecodeURIComponent } from '@/lib/url'; const MAXMIND = 'maxmind'; +export const DESKTOP_OS = [ + 'BeOS', + 'Chrome OS', + 'Linux', + 'Mac OS', + 'Open BSD', + 'OS/2', + 'QNX', + 'Sun OS', + 'Windows 10', + 'Windows 2000', + 'Windows 3.11', + 'Windows 7', + 'Windows 8', + 'Windows 8.1', + 'Windows 95', + 'Windows 98', + 'Windows ME', + 'Windows Server 2003', + 'Windows Vista', + 'Windows XP', +]; + +export const MOBILE_OS = ['Amazon OS', 'Android OS', 'BlackBerry OS', 'iOS', 'Windows Mobile']; + +export const DESKTOP_SCREEN_WIDTH = 1920; +export const LAPTOP_SCREEN_WIDTH = 1024; +export const MOBILE_SCREEN_WIDTH = 479; + +// The order here is important and influences how IPs are detected by lib/detect.ts +// Please do not change the order unless you know exactly what you're doing - read https://developers.cloudflare.com/fundamentals/reference/http-headers/ +export const IP_ADDRESS_HEADERS = [ + 'x-client-ip', + 'x-forwarded-for', + 'cf-connecting-ip', // This should be *after* x-forwarded-for, so that x-forwarded-for is respected if present + 'do-connecting-ip', + 'fastly-client-ip', + 'true-client-ip', + 'x-real-ip', + 'x-cluster-client-ip', + 'x-forwarded', + 'forwarded', + 'x-appengine-user-ip', + 'x-nf-client-connection-ip', + 'x-real-ip', +]; + const PROVIDER_HEADERS = [ // Cloudflare headers { @@ -36,6 +75,24 @@ const PROVIDER_HEADERS = [ }, ]; +function stripPort(ip) { + if (ip.startsWith('[')) { + const endBracket = ip.indexOf(']'); + if (endBracket !== -1) { + return ip.slice(0, endBracket + 1); + } + } + + const idx = ip.lastIndexOf(':'); + if (idx !== -1) { + if (ip.includes('.') || /^[a-zA-Z0-9.-]+$/.test(ip.slice(0, idx))) { + return ip.slice(0, idx); + } + } + + return ip; +} + export function getIpAddress(headers: Headers) { const customHeader = process.env.CLIENT_IP_HEADER; @@ -140,7 +197,7 @@ export async function getLocation(ip: string = '', headers: Headers, hasPayloadI ); } - const result = globalThis[MAXMIND]?.get(ip?.split(':')[0]); + const result = globalThis[MAXMIND]?.get(stripPort(ip)); if (result) { const country = result.country?.iso_code ?? result?.registered_country?.iso_code;