К основному содержимому
SharX Connect

HTTP-запрос подписки

Реализация: SubscriptionFetcher в SharXCore. Тип запроса — GET через URLSession.shared.data(for:), таймаут 60 секунд, HTTPS ожидается (но не принуждается; TLS выполняет OC).


Заголовки запроса

Все заголовки, которые клиент присылает панели:

Заголовок Значение Кто задаёт Обязателен?
Accept */* SubscriptionFetcher.fetchDetails да
User-Agent SharXConnect/<version>/<platform>/<build> SubscriptionFetcher.defaultUserAgent да
x-hwid Стабильный ID устройства (hex, 32 симв.) SubscriptionDeviceHeaders да
x-device-os iOS | macOS | Unknown SubscriptionDeviceHeaders да
x-ver-os Версия ОС (18.2, 26.0.1) SubscriptionDeviceHeaders да
x-device-model Маркетинговое имя (iPhone 14 Pro Max, iPad Pro 11-inch (M4)), на симуляторе — из SIMULATOR_MODEL_IDENTIFIER; если идентификатор не опознан — сам hw.machine SubscriptionDeviceHeaders.deviceModelName да
X-SharX-Refresh-Planned-Seconds Секунды до следующего автообновления SubscriptionRefreshService.refresh только если на подписке включено автообновление

Accept: */*

Клиент намеренно не просит text/html: многие панели при таком Accept отдают SPA вместо сырого списка узлов. Если тело начинается с <!DOCTYPE / <html, клиент отвергает ответ ошибкой receivedMarkupInsteadOfSubscription.

User-Agent

Формат: SharXConnect/<shortVersion>/<platform>/<build>.

  • <shortVersion>CFBundleShortVersionString (fallback 1.0).
  • <platform>ios | macos | tvos | watchos | apple.
  • <build>CFBundleVersion (fallback 1).

Пример: SharXConnect/1.0/ios/42.

Рекомендация для панелей: подставляйте шаблон по префиксу SharXConnect/, не по полной строке — версии и билды меняются с релизами.

x-hwid и HWID-заголовки

Стандартное поле панелей с HWID-лимитом (Remnawave и совместимые). Идентификатор создаётся один раз и хранится в Keychain; сохраняется при переустановке приложения и шэрится между таргетами (main app, PacketTunnel, виджеты) через Access Group.

Документация Remnawave: HWID device limit.

Ответ панели при превышении лимита. Remnawave 2.7.5+ возвращает HTTP 200, но ставит заголовок x-hwid-max-devices-reached: truex-hwid-limit: true для обратной совместимости с v2RayTun). SubscriptionFetcher распознаёт это до кода ответа и бросает SubscriptionFetchError.deviceLimitReached, а UI показывает локализованное сообщение с подсказкой удалить одно из устройств в личном кабинете панели или попросить администратора увеличить лимит. REST-эндпоинт самой панели при попытке добавить новое устройство возвращает код ошибки A099 («User hwid device limit reached», HTTP 400) — SharX этим эндпоинтом не пользуется, но в логах панели эта ошибка коррелирует с теми же флагами.

X-SharX-Refresh-Planned-Seconds

Оповещение панели о предполагаемом интервале до следующего запроса (в секундах). Помогает панели планировать rate-limit. Значение совпадает с entity.effectiveAutoRefreshIntervalSeconds. Заголовок не отправляется, если пользователь выключил автообновление на подписке.


Заголовки ответа

Клиент читает заголовки без учёта регистра имён и извлекает значения, перечисленные в SubscriptionBodyDirectives.knownKeys. Тот же набор ключей одновременно поддерживается как #key: value-директивы в начале тела подписки — см. subscription-body-and-routing.md.

Приоритет: если один и тот же ключ пришёл и в HTTP-заголовке, и в body-директиве — побеждает HTTP-заголовок (он более авторитетный для клиента; SubscriptionRefreshService.refresh делает merged = body.merging(headers) { $1 }).

Панель → клиент: тема интерфейса (sharx-color-scheme, sharx-accent-palette)

Панель может передать в приложение светлую/тёмную схему и акцентную палитру при каждом успешном обновлении подписки:

  • В заголовках ответа (имена регистронезависимы): sharx-color-scheme, sharx-accent-palette.
  • Либо в начале тела как директивы: #sharx-color-scheme: … / #sharx-accent-palette: … (те же правила, что у остальных #key: value — см. subscription-body-and-routing.md).

Допустимые значения (в нижнем регистре; сравнение без учёта регистра):

  • sharx-color-scheme: automatic, light, dark.
  • sharx-accent-palette: system, aurora, midnight, sakura, sunset, graphite, matrix, crimson.

Они записываются в UserDefaults.standard под ключами sharxColorSchemePreference и sharxAccentPalette (как @AppStorage в Theme.swift), интерфейс подхватывает при следующем отображении. Невалидное значение игнорируется. Если ключа нет, клиент не сбрасывает эту настройку (остаётся прежний выбор пользователя или прошлое значение с панели).

Для inline-подписки (вставка share-body без http) ведущие строки #sharx-… тоже разбираются и применяются.

Реализация: SubscriptionPanelThemeDirectives.applyFromMergedDirectives.


Типичные ошибки

Ошибка Когда
SubscriptionFetchError.invalidURL sourceURLString не парсится как URL
SubscriptionFetchError.httpFailure(code) HTTP-статус ≠ 2xx
SubscriptionFetchError.emptyResponseBody HTTP 200 и 0 байт тела (пустой шаблон на панели, Fallback без XRAY_BASE64 и т.п.)
SubscriptionFetchError.deviceLimitReached Remnawave прислал x-hwid-max-devices-reached: true или x-hwid-limit: true — превышен лимит HWID
SubscriptionFetchError.network(error) Транспорт: таймаут, DNS, нет сети и т.д.
SubscriptionParseError.receivedMarkupInsteadOfSubscription Тело начинается с HTML (<!DOCTYPE, <html)

См. также

English version