REST: ресурсы, пагинация, фильтры, сортировка

↑ 1.2 HTTP и REST для не-разработчиков · ← Предыдущая

Обязательно~5 мин чтенияУровень: junior

Зачем это аналитику и PM

Экран списка — это контракт выборки: что считается ресурсом, какая страница, какой фильтр и в каком порядке. Без этого «покажите все заказы» превращается в случайные двадцать строк.

План темы

  • ресурсы и коллекции
  • вложенные ресурсы
  • limit/offset и cursor
  • поиск и фильтры
  • версии

Объяснение

В разговоре команды REST — стиль HTTP API, где адрес называет ресурс, а метод называет действие. Строгую теорию стиля здесь не проверяем. Ресурс — сущность, с которой работает сценарий: заказ, клиент, позиция. Коллекция — набор таких сущностей.

Как каталог библиотеки. Полка «заказы» — коллекция /orders. Карточка на полке — /orders/1042. Не просят «сделай мне функцию getAll», а называют полку, карточку и что с ней сделать. Экран при этом может звать несколько полок.

Ресурсы и вложенность

Коллекция и элемент отличаются адресом и телом ответа. Список обычно массив или объект с массивом и сведениями о странице. Элемент — один объект. Вложенный путь /orders/1042/items удобен, пока глубина мала и позиция без заказа не живёт. Длинные цепочки вроде отдела, года и статуса в path трудно менять: каждый новый срез ломает старые ссылки. Иногда позиция — отдельный ресурс, а номер заказа у неё в поле. Что из этого ваш случай, лучше решить до макета, а не по длине URL.

Страницы, фильтры, порядок

Отдать «все заказы» одним ответом опасно: их может быть слишком много. Пагинация режет список на порции.

limit и offset звучат как «верни 20, пропустив 40». Это легко объяснить на приёмке. На живом списке страница плывёт: пока человек листает, сверху вставили заказ, и строка повторится или пропадет. Курсор (cursor) звучит как «верни порцию после вот этого непрозрачного ярлыка». Ярлык не показывают человеку как номер страницы. Зато срез устойчивее, если договорён порядок.

Фильтры и сортировка обычно сидят в query: status=new&sort=createdAt&order=desc. Имена — часть контракта. Нужно заранее решить, что значит пустой фильтр, можно ли передать несколько статусов и какой порядок будет, если поле сортировки не прислали. Поиск по тексту — отдельный фильтр со своими правилами: по каким полям, с какого символа, учитывается ли регистр.

flowchart LR
    A["Коллекция заказов"] --> B{"Как режем список"}
    B -->|"номер страницы и размер"| C["limit и offset"]
    B -->|"ярлык следующей порции"| D["cursor"]
    C --> E["Плюс фильтр и порядок"]
    D --> E

Версии

Когда контракт меняют так, что старый экран сломается, появляется версия: кусок пути /v1 или отдельный заголовок. Какой способ ваш, в статье не выбирают. Важно другое: ломающее изменение без объявленной версии бьёт по уже выпущенным клиентам.

Примеры

Схема списка, не живой магазин. В ответе есть порция и признак, что дальше ещё есть данные. Имена полей у вас будут своими.

{
  "items": [
    {"id": "1042", "status": "new"}
  ],
  "limit": 20,
  "nextCursor": "eyJ..."
}

Адрес такой выборки:

https://api.example.com/v1/orders?status=new&limit=20&cursor=eyJ...

v1 здесь — пример версии в пути. cursor обрезан маской: живой ярлык бывает длинным и похожим на секрет, в тикет его целиком не кладут, если команда не сказала обратное.

Учебный список JSONPlaceholder тоже коллекция, только без вашего фильтра:

https://jsonplaceholder.typicode.com/todos?_limit=2

Нюансы и подводные камни

  • Страница без стабильного порядка прыгает. Сортировку по умолчанию фиксируют, даже если экран её не показывает.
  • Практика

Опишите список заказов для экрана: адрес коллекции, один фильтр, порядок по умолчанию и способ страницы, limit/offset или cursor.

Ожидаемый результат: есть пример query, размер порции и фраза, как клиент понимает, что страницы кончились. Если способ страницы неизвестен, он помечен вопросом к команде. Рядом не обещан «весь архив одним ответом».

Вопросы с ответами

Связано с блоком Developer

Связанные темы