- Next 16.4 и Payload 3.91 в одном приложении, PostgreSQL с UUID, TypeScript 6, ESLint 9, Prettier, Vitest - Payload: администраторы с ролями, multi-tenant по сайтам, локализация en/ru/de/fr/es, интерфейс админки ru/en, языки сайта (sites.locales) - Коллекции sites, domains, currencies, countries, locations, tags, tariffs, payment-systems (manual), media и начальные данные (pnpm seed) - Proxy: хост → домен, язык и валюта, внутренние маршруты по хосту; /admin и /api закрыты на доменах брендов - Токены и темы брендов, оболочки сайта и кабинета, переключатели языка, валюты и темы, заглушки страниц - /svc/health, юнит systemd veilix-dev.service - Документация: решения D-022…D-024, команды в CLAUDE.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
D-022. Proxy: внутренние маршруты по хосту, домены из внутреннего эндпоинта
Статус: принято, 21.10.2026. Уточняет D-005, пункт 3.
Контекст
- Языки, валюты, основной домен и индексация заданы у домена, а не у сайта. Страница, собранная на весь сайт, не знает, на каком зеркале её открыли: у зеркала со своим набором языков переключатель,
hreflangиcanonicalбыли бы чужими. - Proxy в Next 16 работает отдельно от кода страниц, и документация Next запрещает полагаться на общие с ним модули и глобальные переменные. Payload внутри proxy создал бы второй экземпляр поверх общего
global._payload.
Решение
- Во внутреннем маршруте — хост:
/m/{хост}/{язык}/{валюта}/…— сайт,/c/{хост}/{язык}/…— кабинет,/t/{хост}/…— MiniApp. Сайт и настройки страница берёт из записи домена. - Proxy получает список активных доменов у
/svc/internal/domains(заголовокx-vx-internal-tokenсINTERNAL_TOKENиз.env) и держит его в памяти 15 секунд. Устаревший список отдаётся сразу и обновляется в фоне. Правка домена в админке применяется в пределах 15 секунд. - Proxy свой, а не middleware next-intl: тот не умеет брать домены из базы, класть хост и валюту в путь и учитывать
X-Geo-Country. next-intl используется для сообщений, форматирования и ссылок. Ботов определяет библиотекаisbot. skipProxyUrlNormalize: trueвnext.config.ts. Без него адрес запроса в proxy строится отlocalhost, а роутер Next слушает127.0.0.1, и любое переписывание считается внешним.
Рассмотренные варианты
- Код сайта во внутреннем маршруте, как было в 02 — ломается, как только у зеркала свой набор языков или валют.
- Local API Payload прямо в proxy — второй экземпляр Payload и пул соединений в отдельной сборке, конфликт по
global._payload. - Сброс кэша proxy из хука Payload — хук срабатывает до фиксации транзакции, и proxy мог бы перечитать старые данные; при кэше в 15 секунд выигрыш не нужен.
Последствия
- Статических вариантов страниц столько, сколько сочетаний «домен × язык × валюта»; сейчас у сайта по одному домену каждого типа.
- Если эндпоинт недоступен, proxy работает по последнему полученному списку, а без него отвечает 503.