Сжатие и кэширование
Крупные публичные запросы на чтение, например GET /markets, возвращают мегабайты JSON. Запрашивайте сжатие и ориентируйтесь на заголовок Cache-Control в каждом ответе, чтобы понимать, насколько свежи данные.
Сжатие
Отправьте Accept-Encoding: gzip, и API вернёт тело ответа, сжатое gzip, с заголовком Content-Encoding: gzip. Ответ GET /markets уменьшается примерно с 4 МБ примерно до 0,6 МБ.
- Браузеры и
fetchв Node.js отправляют этот заголовок и распаковывают ответ автоматически. - Rust
hypercall-clientвключает gzip в своём HTTP-клиенте, поэтому каждый REST-вызов запрашивает сжатие и прозрачно его декодирует. - Python
requestsиhttpxпо умолчанию отправляют заголовок и распаковывают ответ. Обычныйurllibне делает ни того, ни другого, поэтому вы получите несжатое тело. - curl требует флага
--compressed.
Ответы размером менее примерно 1 КБ отправляются без сжатия. На кадры WebSocket это не распространяется; см. Сжатие WebSocket.
Cache-Control
Каждый ответ на запрос чтения сообщает, может ли общий кэш его сохранить.
| Заголовок ответа | Где встречается | Что означает |
|---|---|---|
public, max-age=N | Публичные рыночные данные: /markets, /instruments, /instrument-specs, /exchange-info, греки, сводки по опционам и экспирациям, исторические теоретические цены, данные пулов, /version | Любой кэш может повторно использовать тело ответа до N секунд. Обычно это от 1 до 15 секунд; для исторических данных срок может быть больше. |
public, max-age=N, stale-while-revalidate=M | Некоторые из перечисленных выше запросов | По истечении N секунд кэш может продолжать отдавать старое тело ещё до M секунд, параллельно запрашивая свежую версию в фоне. |
no-store | Запросы в разрезе кошелька и аутентифицированные запросы: портфель, открытые заявки, исполнения, сделки с фильтром по кошельку, конфигурация MMP и т. п. | Никогда не сохраняется ни одним кэшем. Каждый запрос доходит до API. |
| нет | Всё остальное, включая /orderbook и все запросы на запись | Не кэшируется. |
Считайте, что данные public-запроса могут быть старше на величину до max-age (плюс stale-while-revalidate, если задан) секунд. Если для торгового решения нужно актуальное состояние, получайте его из каналов WebSocket или через запрос в разрезе кошелька: они никогда не кэшируются.
Ответы с ошибками (4xx, 5xx) никогда не помечаются как public и никогда не кэшируются. Пока API возвращает ошибки, кэш не продолжает отдавать просроченное тело; вы получаете ошибку.
Запросы, которые всегда доходят до API
Кэшированное тело никогда не возвращается на запрос, содержащий любой из перечисленных ниже элементов, и ничего из полученного таким запросом не сохраняется:
AuthorizationилиCookieX-Hypercall-SignatureилиX-Hypercall-Expires-At-Ms(подписанные запросы на чтение, например конфигурация MMP)X-Hypercall-FenceилиX-Hypercall-Fence-Wait(согласованность чтения после записи, см. Защита маркетмейкера)X-Hypercall-Gateway-TokenилиX-Admin-Key- любой метод, кроме
GETилиHEAD, а также апгрейды до WebSocket
Барьеры согласованности чтения после записи и кэширование никогда не совмещаются. Маршрут, поддерживающий X-Hypercall-Fence, помечен как no-store, а public-маршрут никогда не ожидает барьера.
X-Cache-Status
Ответы, прошедшие через edge-кэш Hypercall, содержат заголовок X-Cache-Status:
| Значение | Смысл |
|---|---|
HIT | Отдан из edge-кэша в пределах max-age. |
MISS | Получен от API. Если ответ был public, теперь он закэширован. |
BYPASS | Запрос содержал заголовок из списка выше, поэтому ушёл напрямую в API, и ничего не было сохранено. |
EXPIRED | Срок жизни кэшированной копии истёк, поэтому API был запрошен повторно. |
STALE или UPDATING | Отдан из кэша в пределах окна stale-while-revalidate, пока запрашивается свежая копия. |
У запросов на запись и других запросов, отличных от GET, заголовка X-Cache-Status нет. Заголовок носит информационный характер: не стройте на нём торговую логику. Edge-кэш пока есть не во всех средах. Ответ без этого заголовка пришёл напрямую от API.