около 40 полей · ограничения сверены с src/core/config.h
Справочник полей xs.json
Загрузка конфигурации — fail-fast: любое недопустимое поле прерывает старт, называя поле по имени. Неперечисленные поля ошибкой не считаются — они попадают в Custom, откуда их читает приложение (см. xsConfigRoot в справочнике xsapi).
Корневые поля (2)
Поле
Тип / умолчание
Ограничения и пояснения
engine.workers
uint · 0
0–1024; 0 = умолчание xrt. Неизменяемо при горячей перезагрузке, изменения отвергаются
services
массив · обязательное
отсутствует или не массив: field 'services' expect array, старт провален
Сервисные поля (services[i], 13)
Поле
Тип / умолчание
Ограничения и пояснения
enabled
bool · true
включатель сервиса
class
string · обязательное
белый список http / ws / tcp / udp / custom / app, остальное — fail-fast (app = http-узел с фронтом, см. узел app)
name
string · обязательное
глобально уникально (повтор даёт duplicate name); ключ xsServerFind
ip
string · 0.0.0.0
адрес прослушивания; класс app по умолчанию 127.0.0.1 (привязка к loopback не вызывает диалог брандмауэра Windows)
port
uint · —
1–65535; для не-custom обязательно (missing port); 0 = автоназначение ОС, только класс app (остальные дают port 0 (auto) is only supported for class app); фактический порт считывается через XS_ServerInfo.PortBound
tls
bool · false
включает TLS-порт; на udp запрещено (tls on udp)
port_tls
uint · 443
при конфликте с открытым портом на том же IP старт отвергается
ip_tls
string · как ip
адрес прослушивания TLS
backlog
uint32 · —
напрямую в конфигурацию прослушивания xrt; с проверкой диапазона
recv_limit
size · —
≤SIZE_MAX; на udp ≤65535 (recv limit out of range)
path / devlang / devfile
string · —
сервисные умолчания скриптов, синтезируются в DefaultHost
dev_inc / dev_lib
string · —
каталоги поиска 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
тип / умолчание
ограничения и пояснения
title
string · "xs app"
заголовок окна
width / height
uint · 1280 / 800
начальный размер в пикселях; диапазон 200–32767
min_width / min_height
uint · 0
минимальный размер; 0 = без ограничения
url
string · "/"
открываемая при готовности страница; относительный путь собирается с фактическим портом как http://<ip>:<PortBound>/…; абсолютные URL разрешены
devtools
bool · false
включить инструменты разработчика WebView2
close
string · "stop"
stop = закрытие окна корректно останавливает весь процесс; hide = скрыть окно, сервис продолжает (повторный запуск будит существующее окно через обнаружение единственного экземпляра; остановка — по сигнальному пути)
install_fallback
string · "ask"
поведение при отсутствии Runtime (значения ниже); любая неудача — headless
значение install_fallback
смысл
"ask"
спросить диалогом, ставить ли WebView2 Runtime (умолчание для конечных пользователей)
"silent"
скачать и поставить молча, сценарии без присмотра
"headless"
не пытаться ставить, сразу деградировать в headless-сервис
автоназначение port: 0: разрешено только классу app (остальные fail-fast); ядро выделяет порт атомарно, затем значение считывается назад (без «проверить→закрыть→перепривязать», что исключает гонку TOCTOU). Горячая перезагрузка прилипает по имени сервиса (стабильно сквозь поколения — открытые окна не замечают); для стабильности между перезапусками задайте фиксированный порт. Полная матрица деградации по платформам и вариантам — на странице справки webview.
Хостовые поля (host_default / hosts[i], 9)
Поле
Тип / умолчание
Ограничения и пояснения
enabled
bool · true
включатель хоста
name
string · обязательное
уникально в пределах server и непусто (повтор / пустое — оба fail-fast)
host
string · —
домены через точку с запятой; для включённого vhost http/ws обязательно непустое
path
string · —
корень статических ресурсов; отсутствие каталога — fail-fast
devlang
string · —
static чистая статика / c скрипты TCC / своё приложение
devfile
string · —
входной скрипт; отсутствие файла — провал компиляции
tls_ca / tls_cert / tls_key
string · —
пути PEM; сертификаты уровня host → источник данных таблицы SNI
dev_inc / dev_lib
string · —
пути поиска скриптов уровня host
остальные поля
любые
попадают в host->Custom (ручки static.* см. ниже)
host_default существует всегда (при отсутствии конфигурации синтезируется из сервисных полей скрипта); количество hosts[] не ограничено, непопавший vhost откатывается к default.
Ручки Custom (уровень server, читает приложение)
Поле
Тип / умолчание
Пояснение
header_limit
uint · —
потолок заголовков запроса (превышение → 431)
path_limit
uint · 2048
потолок длины пути (превышение → 414)
body_limit
uint · —
потолок тела запроса (превышение → 413)
idle_timeout
uint · —
тайм-аут простоя в мс (http/ws/tcp); по истечении сервер закрывает
ws_message_limit
uint · —
потолок сообщения WS; превышение — close 1009
ws_protocol
string · —
принудительный подпротокол; корректность проверяется на старте, ошибка типа — 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_dotfiles
bool · true
файлы с точкой в начале отвергаются всегда (включая попытки обхода)
Правила разбора путей
Все файловые пути превращаются в абсолютные относительно каталога файла конфигурации — каталог конфигурации самодостаточен и переносится целиком
Запущенный без аргументов, XServer ищет xs.json в каталоге исполняемого файла; аргумент может указать его явно
Относительные пути dev_inc отсчитываются от appPath; помните про границу «ловушечного заголовка» из главы 6
Узел acme (автопродление сертификатов, требует расширения xacme)
Корневой узел acme включает встроенный демон ACME: ежедневная проверка по расписанию, автоматическое продление DNS-01 при падении остатка жизни ниже порога и горячая замена (соединения не рвутся). Все креденциалы живут в отдельных файлах (никогда в xs.json): ключ аккаунта, креденциалы DNS, EAB, якоря доверия.
Поле
Тип / умолчание
Ограничения и пояснения
enabled
bool · false
главный выключатель; false — демон не запускается
account_key_file
string · —
ключ аккаунта PEM (ES256); пусто = каждый CA саморегистрируется при первом использовании. Один ключ может открыть аккаунты в нескольких CA
1–89; продление запускается при остатке жизни меньше этого числа дней
check_time
string · —
фиксированное ежедневное время проверки "HH:MM" (00:00–23:59); взаимоисключающе с check_interval_hours
check_interval_hours
uint · 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: имеющаяся конфигурация печатает уведомление и игнорируется; демон остаётся инертным.