Skip to content

feat(happ): подстановка geo-URL и LastUpdated в переопределении routing - #22

Open
tony-adamson wants to merge 2 commits into
howdeploy:mainfrom
tony-adamson:feat/geo-url-placeholders-2
Open

feat(happ): подстановка geo-URL и LastUpdated в переопределении routing#22
tony-adamson wants to merge 2 commits into
howdeploy:mainfrom
tony-adamson:feat/geo-url-placeholders-2

Conversation

@tony-adamson

Copy link
Copy Markdown

Проблема

_happ_default_routing_json() подставляет в профиль ссылки вида <base>/sub/<token>/geoip.dat
они привязаны к конкретному подписчику. При этом HAPP_ROUTING_JSON_FILE один на всех.

Получается тупик. Оператор, которому нужен свой профиль, должен либо зашить в общий файл токен
одного из подписчиков и раздать его всем остальным, либо поднимать раздачу geo-баз отдельно. Второй
путь работает, но это лишняя инфраструктура ради двух ссылок.

Что в PR

Три подстановки, которые subhttp.sh разрешает на каждый запрос:

Подстановка Значение
{{GEOIP_URL}} <base>/sub/<token>/geoip.dat запрашивающего подписчика
{{GEOSITE_URL}} <base>/sub/<token>/geosite.dat запрашивающего подписчика
{{LAST_UPDATED}} самое свежее mtime среди xrayebator и двух geo-баз

Замена идёт до проверки схемы. Поэтому неразрешённая подстановка не проходит https_url, и
клиенту уходит управляемый профиль по умолчанию, а не сломанный, — в том числе в local-only режиме,
где публичного base URL просто нет.

{{LAST_UPDATED}} заодно снимает ручной шаг: HAPP переимпортирует профиль только когда значение
выросло.

Поверх #21.

Проверено

  • bash -n на xrayebator, install.sh, update.sh
  • bash -n на сгенерированном subhttp.sh
  • подстановка проверена в трёх случаях: обычный, файл без плейсхолдеров (не меняется), пустой base
    URL (профиль отбраковывается, отдаётся дефолтный)

🤖 Generated with Claude Code

https://claude.ai/code/session_0121QZ51XSKaiKcRrtoVQTDg

tony-adamson and others added 2 commits September 7, 2026 13:18
The subscription endpoint ships a client-side routing profile in the routing:
response header, and the managed default tunnels everything. The override file
that changes it was mentioned in one line of the architecture docs, without a
schema, an example, or the difference from server-side bypass routing.

Bypass routing only changes where the server sends a request; the client still
tunnels it, so a Russian site keeps seeing the VPS address. On a node without a
cascade the catch-all outbound is already direct, so bypass cannot help there.
Split routing is only reachable through the client profile, which made this the
most common thing operators had to rediscover on their own.

Adds a Configuration section in en/ru/zh-CN covering the two environment
variables, GlobalProxy semantics, a complete split-tunnel example, and the three
mistakes that are easy to make: Telegram matching by IP rather than domain,
LastUpdated needing to grow, and geo database URLs being per-subscriber.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0121QZ51XSKaiKcRrtoVQTDg
… request

The managed routing profile points HAPP at /sub/<token>/geoip.dat, which is
scoped to one subscriber. HAPP_ROUTING_JSON_FILE, in contrast, is served to
every subscriber, so an operator who wants a custom profile has to either embed
one subscriber's token in a file everyone receives, or host the geo databases
somewhere else entirely.

Adds {{GEOIP_URL}}, {{GEOSITE_URL}} and {{LAST_UPDATED}} placeholders that
subhttp.sh resolves per request. Substitution runs before schema validation, so
an unresolved placeholder fails the https_url check and the managed default is
served rather than a broken profile — including the local-only case where no
public base URL exists.

{{LAST_UPDATED}} resolves to the newest mtime among xrayebator and the two geo
databases, which removes the manual step of raising the value after every edit;
HAPP re-imports a profile only when it grows.

Verified: bash -n on xrayebator and on the generated subhttp.sh; substitution
checked for the resolved, no-placeholder and empty-base-url cases.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0121QZ51XSKaiKcRrtoVQTDg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant