iac/apps/mapper/ENDPOINTS.md

96 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Эндпоинты сервиса mapper
Документ описывает HTTP-интерфейс сервиса `mapper` (flows mapper): собственные эндпоинты, которые сервис публикует, и внешние эндпоинты сервисов Sarex, к которым он обращается для сборки ответа.
## Как устроено взаимодействие
`mapper` — асинхронный FastAPI-прокси-агрегатор. Каждый входящий запрос:
1. проходит аутентификацию (`app/dependensies.py:get_user_data`) — из заголовков `Authorization` и опционального `Identity` извлекается `user_id` (подпись JWT не проверяется);
2. создаёт httpx-клиенты к нужным внешним сервисам (`app/config.py`, базовые хосты — из `*_HOST`, `verify=False`, заголовки авторизации пробрасываются);
3. параллельно-последовательно запрашивает 2 внешних сервиса через `ServiceManager.get_response()` (`app/utils.py`);
4. при `REDIS_USE=True` кеширует успешные (200) ответы в Redis по ключу `"{user_id}_{url}"`, а при ошибке апстрима возвращает данные из кеша;
5. объединяет ответы (`modify_pdm_data` / `modify_notes_data`) и отдаёт результат.
Если любой из двух апстримов вернул `None` (ошибка и нет кеша) — роутер отвечает `400 Bad Request`.
## Собственные эндпоинты (что публикует mapper)
Базовый префикс — `API_PREFIX` (по умолчанию `/api/v1`). Оба эндпоинта требуют заголовок `Authorization``Identity` для режима Zitadel).
| Метод | Путь | Назначение | Ответ |
| --- | --- | --- | --- |
| GET | `/api/v1/disks/{disk}/documents/` | Документы диска, обогащённые review-данными из сервиса процессов | `object` (`{"documents": [...]}`) |
| GET | `/api/v1/notes/{service}/{entity}/{instance_id}/` | Заметки сущности, обогащённые target-links из Django-бэкенда | `array` (список заметок) |
### `GET /api/v1/disks/{disk}/documents/`
Параметры пути: `disk` (string).
Логика (`routers.py:get_documents`):
- запрос к **documentations**: `GET /disks/{disk}/documents` → берётся поле `documents`;
- запрос к **flows**: `GET /documents/?full=true`;
- `modify_pdm_data` матчит по `document_id`/`bundle_id` и добавляет `review_data` в соответствующие бандлы документов.
### `GET /api/v1/notes/{service}/{entity}/{instance_id}/`
Параметры пути: `service`, `entity`, `instance_id` (string). Дополнительно **все query-параметры запроса пробрасываются** в сервис заметок (к ним добавляется `full=true`).
Логика (`routers.py:get_notes`):
- запрос к **notes**: `GET /notes/{service}/{entity}/{instance_id}/?full=true&<проброшенные query>`;
- запрос к **Django**: `GET /core/target-links/` (полный путь — `{DJANGO_HOST}/core/target-links/`);
- `modify_notes_data` заменяет id-ссылки в поле `links` каждой заметки на объекты target-links.
Полное описание схем — в `openapi.yaml`.
## Внешние сервисы и базовые хосты по окружениям
Базовые хосты берутся из `*_HOST` (`app/config.py`). Итоговый URL = `<HOST>` + путь ниже. Значения по окружениям — из `.helm/values.yaml` (деплой из репозитория сервиса) и overlay'ов инфра-репозитория.
| Сервис | Переменная | Дефолт в коде (stage) | preprod | production | brusnika-stage | brusnika-prod |
| --- | --- | --- | --- | --- | --- | --- |
| documentations | `DOCUMENTATION_HOST` | `https://stage-api.sarex.io/documentations/api/v1` | `https://api.preprod.sarex.io/documentations/api/v1` | `https://api.sarex.io/documentations/api/v1` | `https://test.sarex.brusnika.tech/documentations/api/v1` | `https://cde.brusnika.ru/documentations/api/v1` |
| flows | `FLOW_HOST` | `https://stage-api.sarex.io/flows/api/v1` | `https://api.preprod.sarex.io/flows/api/v1` | `https://api.sarex.io/flows/api/v1` | `https://test.sarex.brusnika.tech/flows/api/v1` | `https://cde.brusnika.ru/flows/api/v1` |
| django (sarex-backend) | `DJANGO_HOST` | `https://stage.sarex.io/api` | `https://preprod.sarex.io/api` | `https://lk.sarex.io/api` | `https://test.sarex.brusnika.tech/api` | `https://cde.brusnika.ru/api` |
| notes | `NOTE_HOST` | `https://stage-api.sarex.io/notes/api/v1` | `https://api.preprod.sarex.io/notes/api/v1` | `https://api.sarex.io/notes/api/v1` | `https://test.sarex.brusnika.tech/notes/api/v1` | `https://cde.brusnika.ru/notes/api/v1` |
## Эндпоинты внешних сервисов (что вызывает mapper)
### `documentations`
| Метод | Путь | Параметры | Назначение | Где используется |
| --- | --- | --- | --- | --- |
| GET | `/disks/{disk}/documents` | `disk` (path) | Документы диска (поле `documents` в ответе) | `get_documents` |
### `flows`
| Метод | Путь | Параметры | Назначение | Где используется |
| --- | --- | --- | --- | --- |
| GET | `/documents/` | `full=true` (query) | Документы процессов с review-данными | `get_documents` |
### `notes`
| Метод | Путь | Параметры | Назначение | Где используется |
| --- | --- | --- | --- | --- |
| GET | `/notes/{service}/{entity}/{instance_id}/` | `service`, `entity`, `instance_id` (path); `full=true` + проброшенные query | Заметки сущности | `get_notes` |
### `django` (sarex-backend)
| Метод | Путь | Параметры | Назначение | Где используется |
| --- | --- | --- | --- | --- |
| GET | `/core/target-links/` | — | Связи (target-links); из ответа берётся `results`, если ответ — объект | `get_notes` |
## Заголовки и аутентификация
- `Authorization: <token>` — обязателен для обоих эндпоинтов; пробрасывается во все внешние запросы как есть.
- `Identity: <token>` — опционален; при наличии включается режим Zitadel, заголовок также пробрасывается во внешние запросы.
- Ответы при ошибках: `401 Unauthorized` (нет `Authorization`), `400 Bad Request` (ошибка апстрима без кеша), `422 Unprocessable Entity` (ошибка валидации параметров пути, стандартный ответ FastAPI).
## Замечания
- В коде клиент к сервису заметок называется `NoteSettings`/`note`, к Django — `DjangoSettings`/`django`. Пути `/documents/` (flows) и `/notes/.../` (notes) содержат завершающий слэш — важно для совпадения с маршрутами апстрима.
- Кеш ключуется по `user_id` + URL, поэтому проброшенные query-параметры в `get_notes` не входят в ключ кеша (URL берётся без query). При включённом Redis это стоит учитывать.
- Healthcheck-эндпоинта у сервиса нет.