DICT (RFC 2229)
DICT — отдельный способ читать словари экземпляра по протоколу RFC 2229 поверх TCP.
Словарный клиент подключается к порту 2628 и отправляет команды, например
DEFINE default hello. Сервер возвращает текстовые определения с источниками и лицензиями.
Чем это отличается от HTTP
| HTTP API | DICT | |
|---|---|---|
| Подключение | HTTP-запросы к адресу API | TCP-соединение с адресом и портом DICT |
| Пример | GET /api/v1/words/hello | DEFINE default hello |
| Ответ | JSON | Текст UTF-8 и коды ответов DICT |
| Клиент | Браузер, fetch, HTTP-клиент, SDK проекта | Словарный DICT-клиент или curl с поддержкой DICT |
| Доступность | Настройки существующего API | Выключен до установки DICT_ENABLED=true |
Сервер DICT работает внутри существующего backend-процесса (apps/server). Отдельное
приложение, контейнер или копия словаря не нужны: оба интерфейса читают те же установленные
датасеты. При этом протоколы, порты и переключатели включения у них разные. HTTP API продолжает
работать как раньше; настройка PUBLIC_API_ENABLED не управляет DICT.
DICT не является маршрутом /api. Открыть http://localhost:2628 в браузере или обратиться
к нему через fetch() не получится. Нужен клиент с поддержкой DICT — примеры ниже.
Включение и подключение
Для сервера, запущенного напрямую, задайте настройки и перезапустите его:
DICT_ENABLED=true
DICT_HOST=127.0.0.1
DICT_PORT=2628
Для Docker задайте DICT_ENABLED=true в .env и запустите обычный Compose:
docker compose up -d
Основной Compose-файл включает настройки DICT в серверном контейнере. Внутренний порт —
2628, адрес прослушивания внутри контейнера — 0.0.0.0. На хосте порт опубликован на всех
сетевых интерфейсах; DICT_PORT в .env позволяет изменить порт хоста. Новые обязательные
переменные и отдельный контейнер не нужны. При DICT_ENABLED=false слушатель выключен,
но публикация порта остаётся в конфигурации Compose.
Для удалённых клиентов разрешите входящие TCP-соединения на этот порт в файрволе хоста.
При подключении извне укажите домен сервера вместо 127.0.0.1, например:
curl 'dict://vocab-bloom-hub.com:2628/d:hello:default'
Примеры для словарного клиента dict:
# Список установленных словарей
dict -h 127.0.0.1 -p 2628 -D
# Определение слова в default
dict -h 127.0.0.1 -p 2628 -d default hello
# Поиск по префиксу во всех словарях
dict -h 127.0.0.1 -p 2628 -d '*' -s prefix -m hel
Можно использовать curl, если в выводе curl --version среди протоколов указан dict:
curl 'dict://127.0.0.1:2628/d:hello:default'
curl 'dict://127.0.0.1:2628/m:hel:!:prefix'
Первый запрос читает определение hello в default; второй ищет слова с началом hel в первом
словаре, где есть совпадения. Отсутствие слова — обычный результат поиска, а не ошибка подключения.
Имена установленных словарей можно узнать командой SHOW DB или через dict -D.
Это обычный TCP без HTTP. Настройки HTTP reverse proxy и его TLS-сертификаты автоматически на него не распространяются. Для удалённого доступа опубликуйте TCP-порт либо используйте SSH port forwarding или TCP-туннель. Аутентификация, SASL, TLS и PROXY protocol не реализованы. Через DICT доступны все установленные датасеты, как и через HTTP-метод чтения разных датасетов. Ограничения учитывают IP непосредственного подключения, а не HTTP-заголовки прокси.
Словари и определения
SHOW DB показывает установленные датасеты: сначала default, затем остальные по имени.
Этот порядок не зависит от активного датасета HTTP API. Имя базы — существующее имя датасета,
а краткое описание — его заголовок. Изменение заголовка не меняет имя базы. Установленный
датасет появляется при следующем запросе; удалённый исчезает. На SQLite доступен только default.
SHOW INFO имя возвращает описание датасета, язык, источник, версию, атрибуцию, уведомления
и полный текст лицензионных условий. Используются существующие метаданные. Датасет обозначает
словарь, а не язык. Сейчас словари содержат английские слова; переводы не становятся отдельными базами.
DEFINE имя слово возвращает текст UTF-8: отдельное определение для базового слова и части речи.
В него входят значения, примеры, цитаты, переводы, формы, альтернативные написания, этимологии
и произношения. Аудиозаписи представлены ссылками с собственными лицензионными условиями;
сервер не скачивает медиа. Источники слова и применимые авторские изменения сохраняют атрибуцию,
уведомления, версии, полный текст собственных лицензий и правила их совместного применения
или выбора. Ответ сообщает, изменено ли слово на этом экземпляре. Неизвестная лицензия не
подменяется лицензией принимающего датасета. Общие условия датасета доступны через SHOW INFO.
Поиск использует правила чтения словаря в native API: регистр не учитывается, но при наличии
нескольких написаний, различающихся регистром, точное написание получает приоритет. Форма слова
разрешается в базовую запись. Написание без собственной записи может обратиться к связанному
альтернативному написанию на один переход. Нечёткий поиск не применяется. MATCH выдаёт
доступные написания, а не пустые записи для ссылок синонимов. Переключение активного датасета
согласовано с текущими командами DICT тем же механизмом, что и с HTTP-запросами.
Команды и формат ответов
Поддерживаются DEFINE, MATCH, SHOW DB / SHOW DATABASES, SHOW STRAT / SHOW STRATEGIES,
SHOW INFO, SHOW SERVER, CLIENT, STATUS, HELP, QUIT и OPTION MIME.
Регистр имён команд не важен. Имена баз берутся из SHOW DB. Фразы и кавычки в аргументах
передаются с одинарными или двойными кавычками и экранированием обратной косой чертой.
Обе команды поиска принимают * для всех баз или ! для первой базы с результатами, в порядке
SHOW DB. В MATCH доступны стратегии exact и prefix: сравнение написания без учёта
регистра с сохранением пунктуации и пробелов. Символы шаблонов SQL воспринимаются буквально.
Стратегия по умолчанию . означает exact. Неизвестная база, неизвестная стратегия и отсутствие
совпадений имеют разные коды ответа. Нечёткие стратегии и аутентификация не объявляются.
Приветствие содержит возможность mime и уникальный идентификатор соединения. Строки разделены
CRLF. Текстовый блок завершается строкой с одной точкой; точка в начале исходной строки удваивается.
После OPTION MIME каждый текстовый блок в этом соединении содержит MIME-заголовки, включая
списки совпадений и метаданные. Формат — обычный текст UTF-8 с передачей 8bit. Несколько команд
подряд исполняются по порядку. QUIT завершает соединение. При остановке сервера приём новых
соединений прекращается, текущей работе даётся до пяти секунд на завершение, затем сокеты
закрываются до закрытия соединений с базами данных.
Настройки и ограничения
| Настройка | По умолчанию | Назначение |
|---|---|---|
DICT_ENABLED | false | Включение TCP-сервера: true / false |
DICT_HOST | 127.0.0.1 | Адрес прослушивания; Docker Compose задаёт 0.0.0.0 внутри контейнера |
DICT_PORT | 2628 | Порт от 1 до 65535; при использовании Docker Compose — порт хоста |
DICT_MAX_CONNECTIONS | 64 | Общее число соединений, от 1 до 4096 |
DICT_IDLE_TIMEOUT | 60 | Таймаут бездействия в секундах, от 1 до 3600 |
DICT_RATE_LIMIT | 100 | Команд на IP за 60 секунд, от 1 до 10000; переподключение не сбрасывает счётчик |
Дополнительные фиксированные пределы: восемь соединений на IP, 32 команды в очереди соединения, 1000 совпадений, 100 определений и 1 МиБ на ответ. При превышении размера результатов сервер возвращает временную ошибку целиком, без частичного успешного ответа. Уточните префикс или выберите одну базу. Лимиты независимы от HTTP-бюджета и внутреннего HTTP-токена. Учёт запросов ограничен 10 000 IP-адресами за интервал.
Команда может занимать до 1024 Unicode-символов вместе с CRLF; входной буфер — до 6144 байт. Превышение числа символов вызывает синтаксическую ошибку. Некорректный UTF-8 или отсутствие CRLF завершает соединение с синтаксической ошибкой после предыдущих полных команд. Переполнение буфера, очереди или лимитов соединений и запросов вызывает временную ошибку и закрытие соединения. Длинные строки текстовых ответов переносятся с учётом экранирования точек и CRLF, без разрыва Unicode-символов. Строки списков для машинного чтения не разбиваются на некорректные строки.
Протокол описан в RFC 2229. Реализация проверяется изолированными TCP-клиентами на SQLite и Postgres, включая разные датасеты, переключение, Unicode, MIME, экранирование, несколько команд подряд, завершение работы и лимиты ресурсов.