← На главную

sula запускает Gemini-сервер на Scryer Prolog с rustls

05.08.2026 18:52 · hackernews

sula — это Gemini-сервер, написанный на Scryer Prolog. Работает он только с пропатченной версией интерпретатора из ветки js/fixes. Патчи добавляют несколько важных вещей: нативный '$copy_stream'/2 для потоковой передачи бинарных файлов TLS-клиентам без копирования в кучу Prolog; фикс в library(pio) (функция buffer_prepare_for_n/5), чтобы ленивое чтение из пайпов и других потоков не зацикливалось при EOF; неблокирующий цикл опроса в socket_server_accept/4, который проверяет флаг INTERRUPT и превращает SIGINT в перехватываемое исключение '$interrupt_thrown'; порт на rustls; а также доработку tls_server_negotiate для поддержки опционального клиентского сертификата.

Собирается всё так: git clone https://git.sagredo.dev/scryer-prolog -b js/fixes, затем cargo install --path .. Ещё нужен openssl в PATH — при старте сервер вызывает его, чтобы прочитать CN из сертификата и проверить, что он совпадает с переданным hostname.

Запуск: ./sula.pl --addr HOST:PORT --hostname NAME --content DIR --certs DIR. Файл устроен как polyglot-скрипт: bash сначала находит scryer-prolog в PATH, затем запускает его с целью sula:run, halt. Аргументы можно указывать в любом порядке, неизвестные молча игнорируются. Дефолты такие: адрес 127.0.0.1:1965, hostname localhost, контент из каталога ./site, а сертификаты лежат в ./certs и называются cert.pem и key.pem.

TLS работает через rustls, поддерживаются PKCS#12-файлы идентичности. При старте проверяется, что CN сертификата совпадает с --hostname, иначе запуск прерывается. MIME-типы назначаются по расширению через mime/2, таблица заполняется при старте из /etc/mime.types с помощью DCG в mime.pl, а для .gmi добавлен text/gemini. Текстовые ответы отправляются через format/3, бинарные — нативно через copy_stream/2 из файла прямо в TLS-сокет, минуя кучу Prolog. Ошибки соединений вроде сбоя TLS-хендшейка или обрыва от клиента логируются, и цикл продолжает работать. Ctrl+C останавливает сервер чисто: закрывается слушающий сокет, верхний уровень логирует Shutting down, процесс завершается с кодом 0.

Код разложен по модулям: sula.pl, config.pl, cert.pl, mime.pl, request.pl, gemini_uri.pl, ip.pl, response.pl, log.pl, banner.pl. Например, request.pl читает строку запроса, gemini_uri.pl разбирает Gemini URI, а ip.pl распознаёт IP-адреса, которые отвергаются как хосты.

Читать оригинал →