Overwatch Tournaments нужны функциональные cookie, чтобы сохранять вход и язык интерфейса. Аналитические cookie необязательны и только показывают, как используются страницы, — подробнее в политике конфиденциальности.

Перейти к содержимому

Обзор для разработчиков

Этот раздел — для тех, кто пишет код рядом с OWT: интеграторам, которые строят ботов, оверлеи, статистические сайты и инструменты поверх публичного HTTP API и WebSocket, и контрибьюторам, которые запускают и правят сам репозиторий. Пользовательские сценарии описаны в гайде игрока и гайде организатора; здесь — контракт и устройство.

Что платформа отдаёт наружу

  • Один вход. Go-шлюз — единственный процесс, который говорит HTTP и WebSocket наружу. Питоновские сервисы HTTP не слушают вообще.
  • Версии в пути. Каждый маршрут выглядит как /api/v{n}/<домен>/...: версия всегда второй сегмент, рядом с ней ничего нет. /api/v1/... отдаёт обычный JSON, /api/v2/... — те же пути, обработчики и статусы, но тело завёрнуто в конверт.
  • Справочник эндпоинтов. Scalar на /api/docs с переключателем v1/v2 в шапке; сами спецификации лежат на /api/openapi.json (v1) и /api/openapi.v2.json (v2).
  • Две учётки в одном заголовке. Authorization: Bearer принимает сессионный JWT либо API-ключ. Ключ привязан ровно к одному воркспейсу и не может быть шире прав своего владельца в нём.
  • Realtime. WebSocket на /api/v1/realtime/ws: подписка на топики и доигрывание событий, пропущенных во время обрыва.
GET /api/v1/tournaments?workspace_id=1 HTTP/1.1
Host: owt.craazzzyyfoxx.me
Authorization: Bearer <токен или API-ключ>

Полный список маршрутов не дублируется в статьях — он в справочнике эндпоинтов. Статьи объясняют модель и правила.

Как это устроено

Запрос приходит на шлюз через nginx, шлюз резолвит предъявленную учётку, применяет граничные политики — лимиты по IP, кэш анонимных публичных чтений, версионирование пути — и превращает REST-маршрут в типизированный вызов request/reply по RabbitMQ к нужному доменному воркеру, передавая с ним бюджет времени на ответ. Воркеры написаны на Python, работают без HTTP, делят одну базу PostgreSQL со схемой на домен и общаются с шлюзом и друг с другом только через RabbitMQ и Redis; фронтенд на Next.js живёт за тем же шлюзом на том же origin, поэтому браузер ходит в API относительными путями /api/.... Долгие расчёты (баланс команд, аналитика) не занимают HTTP-соединение: запрос ставит задачу в очередь и возвращает 202, а результат забирается отдельным чтением статуса.

КомпонентЧто это значит снаружи
Шлюз (Go)Единственный адрес: аутентификация, версии API, кэш ответов, лимиты, WebSocket-хаб, /api/docs
Доменные RPC-воркеры (Python)Вся бизнес-логика и все проверки прав; своего сетевого адреса у них нет
PostgreSQLОдна база, схема на домен — границы доменов видны в модели данных
RedisШина realtime-событий, инвалидация кэша ответов, счётчики активных пользователей
RabbitMQТранспорт всех RPC, доменных событий и очередей долгих задач
Фронтенд (Next.js)Сайт на том же хосте и origin, что и API

Домены разведены по воркерам: турниры, регистрация, сетка и pick/ban — в tournament-сервисе; аккаунты, RBAC, ключи и домены воркспейса — в identity; публичные чтения, статистика и справочники — в app; парсинг логов, ранги и достижения — в parser; баланс и драфт — в balancer; аналитика — в analytics; статусы трансляций — в stream. Для интегратора это один HTTP-контракт, но разделение объясняет, почему у разных разделов API разный темп и разные ошибки.

Мультиарендность

Корень аренды — воркспейс: хост запроса определяет сообщество (поддомен платформенной зоны либо подтверждённый собственный домен), и на собственном домене сообщества отвечают ровно те же пути /api/..., что и на платформенном. В самом запросе воркспейс называется явно параметром workspace_id, и доменные чтения без него отвечают 400: если у предъявленной сессии или ключа ровно один воркспейс, шлюз подставит его сам, но при нескольких он не угадывает.

Живая площадка — https://owt.craazzzyyfoxx.me. Всё, что описано в этом разделе, доступно на ней по тем же путям.

Куда дальше