RESTful API разные способы сделать одно и то же - PullRequest
0 голосов
/ 22 января 2019

RESTful API дизайн кажется несколько субъективным, но я хотел бы получить некоторые отзывы о подходах, приведенных ниже, и о любых плюсах / минусах, которые у них есть. Прав ли один? все не так? Могут ли быть предоставлены оба (хотя это обеспечит частично дублирующуюся функциональность)?

GET отфильтрован по нескольким идентификаторам ...

Вот некоторые подходы, которые кажутся вполне нормальными (? F = просто иллюстрирует необязательное использование параметров фильтра / поиска):

GET /supplier/{supplierId}/products?f=...
GET /oem/{oemId}/products?f=...

Должно ли быть более 1 URL для получения продуктов? Кроме того, что, если я хотел бы фильтровать как по поставщику, так и по oem? Должен ли я просто иметь конечную точку / products и все это фильтр, или продукты должны быть доступны только от одного поставщика / oem, но не от обоих, или иметь все их вместе?:

GET /products?supplier={supplierId}&oem={oemId}&f=...
GET /supplier/{supplierId}/products?oem={oemId}&f=...
GET /oem/{oemId}/products?supplier={supplierId}&f=...

ПОЛУЧИТЬ дочернюю коллекцию без фильтрации по родительскому идентификатору ...

Вот подход, который кажется вполне нормальным:

GET /customers/{customerId}/addresses?f=...

Но что, если мне нужны заказы для ВСЕХ клиентов. Будет ли что-то из этого разумным?

GET /customers/addresses?f=...
GET /addresses?f=...

URL / customer / address (без {customerId}), по-видимому, имеет концептуальный смысл, но я не вижу схемы, используемой в документах по дизайну RESTful, которые я обнаружил (всегда присутствует {id}) , URL-адреса достаточно просты, но нарушают иерархию адресов клиентов.

Я полагаю, что это на самом деле не имеет большого значения, поскольку это имеет смысл для всех, кто использует API и является последовательным, но я хотел бы знать, как другие подошли к этим видам вопросы в «отраслевом стандарте». Спасибо.

Ответы [ 4 ]

0 голосов
/ 22 января 2019

Я также собираюсь дать немного другую точку зрения на это.

Вы в основном говорите о коллекциях ресурсов, а не об отдельных ресурсах, которые есть в этой коллекции.

Как правило, я хотел бы убедиться, что каждый отдельный ресурс (например, продукт) имеет свой уникальный URL-адрес. Например /products/1234

Однако продукт может появиться в нескольких коллекциях. Коллекция на самом деле не «владеет» или «не содержит» элемент в коллекции, она просто ссылается на него. Так что один из способов думать об этом состоит в том, что может быть много коллекций, содержащих один и тот же продукт.

Как узнать, что это один и тот же продукт, который появляется в нескольких коллекциях? Вы заключаете URI встраиваемого продукта, поэтому всегда очень ясно, что эти коллекции действительно связаны с одним и тем же.

Это действительно похоже на файловые системы. Многие каталоги могут содержать один и тот же (жесткий или мягкий) файл.

Источники:

0 голосов
/ 22 января 2019

У меня нет большого опыта в этом, потому что я только написал несколько сервисов. Однако при их разработке я всегда считаю, что лучше всего делать это с учетом потребностей потребителя. Что интересует потребителя? В вашем первом примере это выглядит как продукты, и я бы рассматривал поставщика и oem как специальные фильтры. Лично я бы, вероятно, пошел с чем-то вроде:

  • GET: / продукты? Фильтры (включая поставщика и / или oem)

Что касается второй части, снова я бы предложил поработать с потребителем, чтобы выяснить, что важно и что будет для них работать. Заинтересованы ли они именно в заказах или они больше заинтересованы в клиентах, и им необходимо получить подробную информацию о заказах и адреса для конкретных клиентов?

Если предположить, что последнее, то я бы, вероятно, сказал что-то вроде:

  • GET: / Customers - получает базовую информацию для всех клиентов (идентификатор, имя и т. Д.)
  • GET: / Customers / {customerId} - получает базовую информацию для конкретного клиента (идентификатор, имя и т. Д.)
  • GET: / customer / {customerId} / orders - получает базовую информацию о заказе (номер заказа, может быть, дата создания?)
  • GET: / Customers / {customerId} / orders / {orderId} - получает подробную информацию о конкретном заказе.
  • GET: / Customers / {customerId} / address - получает все адреса, связанные с клиентом.
  • GET: / Customers / {customerId} / address / {addressId} - получает конкретный адрес, связанный с клиентом.

Вы всегда можете иметь несколько маршрутов к одному и тому же ресурсу, в зависимости от контекста:

  • GET: / Customers / {customerId} / address / 123 - Возвращает адрес с идентификатором 123
  • GET: / address / 123 - возвращает адрес с идентификатором 123

В конечном итоге все сводится к тому, как потребитель API хочет получить информацию, и что для них имеет смысл.

0 голосов
/ 22 января 2019

Не существует строгих правил для REST, поэтому решения в некотором смысле субъективны.Я хотел бы посмотреть, как это решается с некоторыми из крупных провайдеров API REST.Я уверен, что изучение REST API Etsy или Fitbit приведет вас к некоторым идеям.

GET, отфильтрованный по нескольким идентификаторам

Для вашего первого случая я бы посмотрел на создание агрегациисервис, который выполняет 2 параллельных вызова /supplier/{supplierId}/products?f= и /oem/{oemId}/products?f= и объединяет наборы результатов.Он основан на том, что Etsy делает с их концепцией "связок" .

. Вы можете заставить его принимать список фильтров в виде filters=[key=value,key=value], но, естественно, это будет поддерживать только соединениефильтров

ПОЛУЧИТЬ дочернюю коллекцию без фильтрации по родительскому идентификатору

Google и другие используют «-» в качестве понятия для всех.

Например:

/customers/{customerId}/addresses - это все адреса для одного клиента

/customers/-/addresses - это все адреса для всех клиентов

Это полезно, если вы хотите сохранить иерархиюструктура (например, в вашем домене есть сотрудники и клиенты, а в обеих группах есть адреса).Тогда вы можете сказать:

/customers/-/addresses
/employees/-/addresses

Если вам не нужна иерархическая характеристика, то вы можете просто предоставить выделенную конечную точку для ВСЕХ адресов (просто /addresses).

0 голосов
/ 22 января 2019

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

Лично мне нравится думать о конечных точках с точки зрения ресурсов и применять соответствующие фильтры на GET для фильтрации результатов. Иногда, когда это имеет смысл, я бы включал GET /search/<sub-resource> для облегчения поиска подресурсов в более широком контексте.

Что касается вашего первого примера, если вашим основным ресурсом является product, тогда как oem и supplier являются просто свойством продукта (существуют исключительно по отношению к продукту), тогда используйте /product?supplier=..&oem=... для фильтрации продукты на основе oem и / или supplier будут работать. Вы можете использовать GET /supplier и GET /oem для возврата сведений о поставщике (-ях) и oem (-ах) соответственно, но не обязательно о самих продуктах.

В качестве альтернативы, если вы считаете, что оба являются только подресурсами, вы можете использовать GET /search/oem?product_id=...&customer_id=.. для поиска oem на основе корневых ресурсов, таких как product или customer.

Что касается получения orders для клиента, GET /customers/{customerId}/orders?f=... имеет смысл для отдельного клиента. Чтобы вернуть заказы для всех клиентов, вы можете использовать /orders?customerId=....

Опять же, в качестве альтернативы, вы можете использовать GET /search/orders?customerId=.., если order считается только подресурсом клиента.

Опять же, вышесказанное - всего лишь предложения. То, что вы предложили, тоже может сработать.

...