около 40 полей · ограничения сверены с src/core/config.h

Справочник полей xs.json

Загрузка конфигурации — fail-fast: любое недопустимое поле прерывает старт, называя поле по имени. Неперечисленные поля ошибкой не считаются — они попадают в Custom, откуда их читает приложение (см. xsConfigRoot в справочнике xsapi).

Корневые поля (2)

ПолеТип / умолчаниеОграничения и пояснения
engine.workersuint · 00–1024; 0 = умолчание xrt. Неизменяемо при горячей перезагрузке, изменения отвергаются
servicesмассив · обязательноеотсутствует или не массив: field 'services' expect array, старт провален

Сервисные поля (services[i], 13)

ПолеТип / умолчаниеОграничения и пояснения
enabledbool · trueвключатель сервиса
classstring · обязательноебелый список http / ws / tcp / udp / custom / app, остальное — fail-fast (app = http-узел с фронтом, см. узел app)
namestring · обязательноеглобально уникально (повтор даёт duplicate name); ключ xsServerFind
ipstring · 0.0.0.0адрес прослушивания; класс app по умолчанию 127.0.0.1 (привязка к loopback не вызывает диалог брандмауэра Windows)
portuint · —1–65535; для не-custom обязательно (missing port); 0 = автоназначение ОС, только класс app (остальные дают port 0 (auto) is only supported for class app); фактический порт считывается через XS_ServerInfo.PortBound
tlsbool · falseвключает TLS-порт; на udp запрещено (tls on udp)
port_tlsuint · 443при конфликте с открытым портом на том же IP старт отвергается
ip_tlsstring · как ipадрес прослушивания TLS
backloguint32 · —напрямую в конфигурацию прослушивания xrt; с проверкой диапазона
recv_limitsize · —≤SIZE_MAX; на udp ≤65535 (recv limit out of range)
path / devlang / devfilestring · —сервисные умолчания скриптов, синтезируются в DefaultHost
dev_inc / dev_libstring · —каталоги поиска include / библиотек для скриптов (через точку с запятой, относительно appPath)
остальные полялюбыепопадают в server->Custom (приложение читает их через XS_CustomReadUInt и аналогичные функции)

Узел app (только class: "app", 9 полей window)

class: "app" — не шестой протокол, а http-узел с фронтом: внутри он проходит прежний путь сборки http (host_default / hosts / static / TLS / горячая перезагрузка значат то же), добавляя лишь дескриптор window и жизненный цикл фронта — при старте показывается окно загрузки → по готовности сервиса автоматически открывается window.url → закрытие окна останавливает процесс корректно по семантике close. Окно — слой отображения, сервис — суть: любой сбой потока окна деградирует в строку лога и никогда не уводит сборку двигателя и цепочку остановки на путь fail.

поле windowтип / умолчаниеограничения и пояснения
titlestring · "xs app"заголовок окна
width / heightuint · 1280 / 800начальный размер в пикселях; диапазон 200–32767
min_width / min_heightuint · 0минимальный размер; 0 = без ограничения
urlstring · "/"открываемая при готовности страница; относительный путь собирается с фактическим портом как http://<ip>:<PortBound>/…; абсолютные URL разрешены
devtoolsbool · falseвключить инструменты разработчика WebView2
closestring · "stop"stop = закрытие окна корректно останавливает весь процесс; hide = скрыть окно, сервис продолжает (повторный запуск будит существующее окно через обнаружение единственного экземпляра; остановка — по сигнальному пути)
install_fallbackstring · "ask"поведение при отсутствии Runtime (значения ниже); любая неудача — headless
значение install_fallbackсмысл
"ask"спросить диалогом, ставить ли WebView2 Runtime (умолчание для конечных пользователей)
"silent"скачать и поставить молча, сценарии без присмотра
"headless"не пытаться ставить, сразу деградировать в headless-сервис

автоназначение port: 0: разрешено только классу app (остальные fail-fast); ядро выделяет порт атомарно, затем значение считывается назад (без «проверить→закрыть→перепривязать», что исключает гонку TOCTOU). Горячая перезагрузка прилипает по имени сервиса (стабильно сквозь поколения — открытые окна не замечают); для стабильности между перезапусками задайте фиксированный порт. Полная матрица деградации по платформам и вариантам — на странице справки webview.

Хостовые поля (host_default / hosts[i], 9)

ПолеТип / умолчаниеОграничения и пояснения
enabledbool · trueвключатель хоста
namestring · обязательноеуникально в пределах server и непусто (повтор / пустое — оба fail-fast)
hoststring · —домены через точку с запятой; для включённого vhost http/ws обязательно непустое
pathstring · —корень статических ресурсов; отсутствие каталога — fail-fast
devlangstring · —static чистая статика / c скрипты TCC / своё приложение
devfilestring · —входной скрипт; отсутствие файла — провал компиляции
tls_ca / tls_cert / tls_keystring · —пути PEM; сертификаты уровня host → источник данных таблицы SNI
dev_inc / dev_libstring · —пути поиска скриптов уровня host
остальные полялюбыепопадают в host->Custom (ручки static.* см. ниже)

host_default существует всегда (при отсутствии конфигурации синтезируется из сервисных полей скрипта); количество hosts[] не ограничено, непопавший vhost откатывается к default.

Ручки Custom (уровень server, читает приложение)

ПолеТип / умолчаниеПояснение
header_limituint · —потолок заголовков запроса (превышение → 431)
path_limituint · 2048потолок длины пути (превышение → 414)
body_limituint · —потолок тела запроса (превышение → 413)
idle_timeoutuint · —тайм-аут простоя в мс (http/ws/tcp); по истечении сервер закрывает
ws_message_limituint · —потолок сообщения WS; превышение — close 1009
ws_protocolstring · —принудительный подпротокол; корректность проверяется на старте, ошибка типа — fail-fast

Как читаются: конфигурация попадает в server->Custom (xvalue); demo разбирает строго неотрицательные значения через XS_CustomReadUInt.

Ручки статического слоя (Custom уровня host)

ПолеТип / умолчаниеОграничения и пояснения
static.headersобъект · —≤8 полей; запрещены 8 зарезервированных заголовков (включая Transfer-Encoding, Connection) — нарушение fail-fast
static.indexмассив · index.htmlкандидаты индекса каталога, перебор с откатом
static.error_pagesобъект · —ключи 400–599 (вне диапазона — fail-fast); значения — пути страниц ошибок относительно path
static.deny_dotfilesbool · trueфайлы с точкой в начале отвергаются всегда (включая попытки обхода)

Правила разбора путей

  • Все файловые пути превращаются в абсолютные относительно каталога файла конфигурации — каталог конфигурации самодостаточен и переносится целиком
  • Запущенный без аргументов, XServer ищет xs.json в каталоге исполняемого файла; аргумент может указать его явно
  • Относительные пути dev_inc отсчитываются от appPath; помните про границу «ловушечного заголовка» из главы 6

Узел acme (автопродление сертификатов, требует расширения xacme)

Корневой узел acme включает встроенный демон ACME: ежедневная проверка по расписанию, автоматическое продление DNS-01 при падении остатка жизни ниже порога и горячая замена (соединения не рвутся). Все креденциалы живут в отдельных файлах (никогда в xs.json): ключ аккаунта, креденциалы DNS, EAB, якоря доверия.

ПолеТип / умолчаниеОграничения и пояснения
enabledbool · falseглавный выключатель; false — демон не запускается
account_key_filestring · —ключ аккаунта PEM (ES256); пусто = каждый CA саморегистрируется при первом использовании. Один ключ может открыть аккаунты в нескольких CA
emailstring · —контактный email аккаунта ACME
dns_key_filestring · обязательноеJSON креденциалы DNS-01: {"access_key_id":"…","access_key_secret":"…"} (сейчас поддержан alidns)
renew_before_daysuint · 301–89; продление запускается при остатке жизни меньше этого числа дней
check_timestring · —фиксированное ежедневное время проверки "HH:MM" (00:00–23:59); взаимоисключающе с check_interval_hours
check_interval_hoursuint · 12интервальный режим (1–720); первая проверка через 5 минут после старта, затем по интервалу
certs[]массив · обязательноегруппы сертификатов: {name, domains[], out_dir} — одна группа = один tls-каталог; продукт продления пишется в раскладке acme.sh (cert.pem=лист / ca.pem=цепочка / key.pem / fullchain.pem)

directories[] (цепочка отказоустойчивости CA)

ПолеОбязательноеПояснения
nameнетотображаемое имя; пусто = домен из URL
urlдаадрес ACME directory; дубликаты URL — fail-fast
ca_fileнетякорь доверия PEM этого CA; пусто = системное хранилище
eab_kid_file / eab_hmac_fileпаройдля CA с регистрацией EAB (например litessl); только один из двух — fail-fast

Совместимость: одиночное поле directory (плюс корневой ca_file) равно одноэлементной цепочке; вместе с directories — ошибка. Семантика выполнения: побеждает первый успешный — CA пробуются по порядку, сбой падает на следующий; при действующем локальном сертификате ни один CA не опрашивается; продление всегда retry с головы цепочки (автоматический возврат к основному CA после восстановления). Поток демона владеет своим сетевым движком и снимает конфигурацию при старте (применение после перезапуска).

Решение о продлении читает сертификат в acme-store/ (не каталог tls хоста); принуденная переподписка = удалить acme-store/certs/<основной домен>/ и перезапустить (первая проверка через 5 минут). Варианты без xacme: имеющаяся конфигурация печатает уведомление и игнорируется; демон остаётся инертным.