Как встроить быстрый IP-to-Country lookup в ваш стек
Практическое руководство по определению страны в веб-приложении: где делать запрос, как кэшировать результат и как не поставить геолокацию на критический путь.
# Как встроить быстрый IP-to-Country lookup в ваш стек
Определение страны по IP не должно добавлять к запросу больше нескольких миллисекунд. Разберём, как удержать задержку в этих пределах.
Сначала корректно получите IP клиента
Если перед приложением стоит proxy или CDN, адрес сокета будет указывать на ваш собственный edge, а не на пользователя. Читайте тот заголовок, который действительно проставляет ваша инфраструктура, и доверяйте ему только внутри своей сети:
- Cloudflare:
CF-Connecting-IP - Большинство балансировщиков: крайняя левая недоверенная запись в
X-Forwarded-For - Прямое подключение: адрес peer-сокета
Слепо разбирать X-Forwarded-For опасно: клиент может дописать в начало всё что угодно, и это превращается в дыру для spoofing.
Вызывайте lookup один раз за сессию, а не на каждый запрос
Определяйте страну при создании сессии, сохраняйте страну и классификацию в сессии или в подписанной cookie, а затем переиспользуйте результат. Повторяйте lookup только при смене IP. Так тысячи обращений превращаются в одно.
Кэшируйте с разумным TTL
Геолокация для конкретного /24 обычно остаётся стабильной часами. In-memory cache на один час с ключом по IP снимает большую часть повторного трафика. Негативные результаты тоже стоит кэшировать, но с более коротким TTL: так временный сбой не превратится в шторм запросов.
Не блокируйте рендеринг
Задайте для lookup жёсткий timeout в несколько сотен миллисекунд и заранее определённый fallback:
ts const geo = await Promise.race([ lookup(ip), timeout(300).then(() => null), ]); const country = geo?.country ?? defaultCountry;
Страница, открывшаяся не в той валюте, — неприятность. Страница, которая не открылась вовсе, — потерянная выручка.
Делайте это на edge, когда есть такая возможность
Если приложение работает в edge runtime, lookup выполняется географически ближе к пользователю, а дополнительная задержка становится практически незаметной. Определите страну там, добавьте результат в request context и дайте приложению читать его как обычные данные.
Храните решение, а не исходные данные
Сохраняйте не полный location record, а тот результат, который важен бизнесу: показанную валюту, применённое правило, выбранный сценарий. Это дешевле, проще объясняется privacy reviewer и почти наверняка именно это вам потом понадобится в запросах.
