Рубрики
Без рубрики

Разработка поискового API в REST

Простые операции CRUD легко моделировать. Это поиск, на который трудно решиться. С тегами rest, api, java, design.

Если мы начинаем рассматривать любую архитектуру/рекомендации в стиле REST, в них всегда говорится о ресурсах и ПОЛУЧИТЬ , ПОЛОЖИТЬ ,/| пост , УДАЛИТЬ операции вокруг него. Однако поиск ресурса всегда является спорным вопросом. Наиболее распространенной нотацией является использование GET с /<ресурс>?<параметры поиска> подход. Этот подход прост в реализации, удовлетворяет требованиям проектирующих архитекторов и достаточно гибок. В этой статье я попытаюсь упомянуть некоторые проблемы и возможные подходы к тому, как это может быть реализовано другим и расширяемым способом.

Давайте начнем с перечисления некоторых основных проблем, связанных с этим подходом.

Утечка Личной Информации

ВВП 😉 , мне не нужно ничего говорить. В большинстве корпоративных систем включено ведение журнала доступа, и они регистрируют запрошенный URL-адрес (с параметрами запроса). Теперь, если URL-адрес начинает содержать конфиденциальную или личную информацию, решение недостаточно хорошо.

Ограничение фильтра

С параметрами запроса существует ограничение на количество фильтров, которые могут быть добавлены. Теперь, если ваш набор данных содержит много числовых значений и требуется поддержка нескольких вариантов поиска, вы получите такие поля, как amount_less_than , сумма_большая_ , чем , amount_equals для всех полей. Что делать, если требование состоит в том, чтобы внезапно добавить “меньше и равно” вариант также 😁 .

Одна из вещей, которая пришла на ум, – это обеспечить поиск по запросу POST . Все это хорошо, но как будет выглядеть тело?.

Никакого мозгового подхода

Подход без мозга – самый простой. Все фильтры запросов могут быть сделаны частью объекта поискового запроса. Пример

{
  "amount_greater_than": 10,
  "amount_less_than": 20,
  "active": true
}

Вы уже знаете мое мнение по этому поводу, так что давайте перейдем к следующему.

Универсальный фильтр

Самая простая альтернатива – просто принять набор общих фильтров. Что-то вроде

{
  "filters": [
    {
      "field": "AMOUNT",
      "operation": "LT",
      "value": "20"
    },
    {
      "field": "ACTIVE",
      "operation": "EQ",
      "value": "true"
    }
  ]
}

Отметьте галочкой Это довольно обширно и может быть использовано для новых фильтров без внесения каких-либо изменений для потребителей. ❌ Одним из недостатков является то, что информация о типе поля теряется. Все – это Строка. ❌ Другим недостатком является то, что также может быть запрошен неподдерживаемый фильтр. Поэтому сообщить, какие все поддерживаются для каждого типа поля, довольно сложно. ❌ Другая проблема заключается в том, что можно использовать несколько похожих фильтров, что приводит к путанице в ответах API. например, можно запросить 10 литов (сумма меньше 10) и 20 литов. Никакого вреда, но сбивает с толку.

Фильтры для каждого поля

Небольшое изменение приведенного выше подхода, но устраняющее основной недостаток, заключается в наличии фильтров для каждого типа поля. Таким образом, информация о типе сохраняется. Пример запроса API может быть следующим

{
  "active": {
    "operation": "EQ",
    "value": true
  },
  "amount": [
    {
      "operation": "LT",
      "value": 20
    }
  ]
}

✔️ Информация о типе поля сохраняется и передается должным образом. Отметьте галочкой Большая гибкость в выборе операций, поддерживаемых для каждого типа поля. Кроме того, API будет взаимодействовать с потребителем, если поле поддерживает несколько фильтров (например, количество) или только один (например, активный). ❌ Тем не менее, существует вероятность того, что вызывающий может использовать один и тот же фильтр для поля дважды.

Фильтр типа DSL для каждого поля

Сделав еще один шаг, что, если мы определим операции для каждого поля как возможные поля в json? Пример запроса для такого фильтра может быть смоделирован следующим образом

{
  "active": {
    "eq": true
  },
  "amount": {
    "eq": 0,
    "ge": 0,
    "gt": 0,
    "le": 0,
    "lt": 0
  }
}

Отметьте галочкой Чистый/хорошо документированный API с перечислением всех возможных возможностей. Требуется Расширяемый, если ne для поля требуется фильтр (не равный), его можно просто добавить. ✔️ Последовательность и простота выполнения запроса.

Пример Java

В Java это можно смоделировать с помощью дженериков следующим образом

@Data
class FilterEQ { //Class for EQ filter
    private T eq;
}
@Data
class Filter extends FilterEQ { //Filter extending EQ 
    private T lt;
    private T le;
    private T gt;
    private T ge;
}
@Data
public class Filters { //Request Object
    private Filter amount;
    private FilterEQ active;
}

Предоставление поискового API в REST-дизайне непросто, и для действительно расширяемых вариантов использования GraphQL – лучший подход. Однако не всегда возможно получить лучший письменный стол в офисе 😊 . Мы должны выбрать лучшее место из доступных.

Здесь я дал несколько идей о том, как разработать и улучшить поисковый API. По моему мнению, фильтр типа DSL для каждого поля очень близок к тому, как можно было бы разработать API поиска в GraphQL. Но, возможно, есть лучший подход. Пожалуйста, дайте мне знать ваши мысли по этому поводу. Пожалуйста, поставьте лайк и поделитесь с друзьями, если вы видите какие-то достоинства в процессе и аргументах, которые я перечислил.

Оригинал: “https://dev.to/vtapadia/designing-search-api-in-rest-5cj5”