Если мы начинаем рассматривать любую архитектуру/рекомендации в стиле 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”