httpapi: точки метрики за период отдаются одним запросом
- `GET /api/v1/metrics/{name}?from&to&layer` — ряд точек за период; конверт
объявляет слой, измеренный род, его применимость к отданному ряду и границу
окна измерения, а сам ряд собирается из одного слоя, выбранного по охвату
точек внутри периода
- use-case вынесен в `internal/points`, чтение — одним входом `store.ReadSeries`
под одной транзакцией; правило выбора слоя остаётся в домене и приходит в
хранилище колбэком
- `writeJSON` перестал экранировать HTML-символы и перестал глушить отказ
записи: дословность содержимого точки иначе не удерживается, а оборванное
тело уходило под видом успешного `200`
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Сериализация ответа чтения не экранирует содержимое
|
||||
|
||||
Система SHALL сериализовать тела ответов читающих маршрутов **без экранирования
|
||||
HTML-символов**: `&`, `<` и `>` внутри значений MUST уезжать клиенту как есть и
|
||||
MUST NOT подменяться escape-последовательностями `&`, `<`, `>`.
|
||||
|
||||
Правило общее для всех читающих маршрутов, а не частное для точек, потому что
|
||||
общим является механизм: тело собирает один помощник сериализации, и умолчание
|
||||
`encoding/json` экранирует эти три символа молча. На маршруте, отдающем
|
||||
**дословно сохранённое** содержимое, это прямо ломает обещание дословности:
|
||||
имя источника приходит с телефона пользовательской строкой и законно содержит
|
||||
`&`. Хранилище этот же капкан уже проходило и обезвредило тем же способом —
|
||||
кодировщик с выключенным экранированием вместо `json.Marshal`.
|
||||
|
||||
Проверка обязана стоять на содержимом, реально несущем эти символы: набор
|
||||
фикстур, в котором их нет, зелен и будучи сломанным.
|
||||
|
||||
#### Scenario: Значение несёт символ, который сериализатор склонен экранировать
|
||||
|
||||
- **GIVEN** значение ответа читающего маршрута, содержащее `&`, `<` или `>`
|
||||
- **WHEN** маршрут отвечает
|
||||
- **THEN** эти символы присутствуют в теле ответа как есть
|
||||
|
||||
### Requirement: Ответ чтения непригоден для разделяемого кеша
|
||||
|
||||
Система SHALL помечать ответы читающих маршрутов заголовком
|
||||
`Cache-Control: private, no-cache`.
|
||||
|
||||
Правило общее, потому что цена у него одна на все маршруты чтения: с появлением
|
||||
валидатора ответ становится штатно кешируемым, а при выключенной проверке
|
||||
токенов — законной конфигурации для доверенной локальной сети — в запросе нет и
|
||||
`Authorization`. Тогда выгрузку истории здоровья вправе сохранить любой прокси
|
||||
на пути. Маршрут, решающий это заново, однажды решит иначе.
|
||||
|
||||
#### Scenario: Читающий маршрут ответил
|
||||
|
||||
- **WHEN** читающий маршрут отдаёт тело
|
||||
- **THEN** ответ несёт `Cache-Control: private, no-cache`
|
||||
Reference in New Issue
Block a user