Соглашение об именовании маршрутов API

#rest #api-design

#rest #api-дизайн

Вопрос:

Я работаю над API (вместе с SPA) для частного проекта, и я не могу выбрать между двумя соглашениями об именовании маршрутов.

Предположим, у меня в базе данных есть три таблицы: Users , Products и Orders . Если я хочу, чтобы пользователи могли заказывать продукты, какому из следующих соглашений я должен следовать?

  1. POST /orders с телом { "product": 1 }
  2. POST /products/{id}/order

Примечание: В обоих случаях user вывод был бы сделан на основе предоставленного токена доступа.

На мой взгляд, основное различие между двумя вышеупомянутыми решениями заключается в типе интерфейса, предоставляемого интерфейсному разработчику: предоставляю ли я маршруты к ресурсам (решение 1) или к действиям, которые необходимо выполнить (решение 2)?

Существуют ли реальные (dis) возможности использования одного метода поверх другого или это просто вопрос личного вкуса?

Поправьте меня, если я ошибаюсь, но, насколько я понимаю, решением 1 является REST («создать этот ресурс»), а решением 2 — нет («выполнить это действие»).

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

Комментарии:

1. Вы также могли бы сделать что-то вроде /products/1?action=order

Ответ №1:

TL; DR

Основываясь на моих исследованиях и конечных точках API GitHub и Instagram, для пользователя, заказывающего продукт, наиболее разумным является expose POST /users/123/orders {"product": 456} вместо POST /orders {"product": 456, "user": 123} . Идея здесь в том, чтобы подумать о контексте ресурса, если таковой существует.

Источники

Рекомендации по разработке прагматичного RESTful API

Обратите внимание, что нам не нужно использовать глагольную фразу ‘update’ в URL, потому что мы можем полагаться на HTTP-глагол для информирования об этой операции. Просто для пояснения, следующий URL ресурса является избыточным:

PUT http://api.example.com/customers/12345/update

Используя в запросе как PUT, так и ‘update’, мы предлагаем ввести в заблуждение потребителей наших услуг! Является ли ‘update’ ресурсом?

10 рекомендаций для улучшения RESTful API

4. Используйте вспомогательные ресурсы для отношений

Если ресурс связан с другим ресурсом, используйте вспомогательные ресурсы.

 GET /cars/711/drivers/ Returns a list of drivers for car 711
GET /cars/711/drivers/4 Returns driver #4 for car 711
  

API-интерфейсы GitHub и Instagram

API-интерфейсы GitHub и Instagram, похоже, тоже работают таким образом, то есть используют контекст ресурса, когда это уместно.

Например, если вы хотите получить список организаций пользователя, используя API GitHub, вы будете использовать GET /users/flawyte/orgs , а не GET /orgs {"username": "flawyte"} .

То же самое с API Instagram, если вы хотите поставить лайк медиа : POST /media/{media_id}/likes .

Ответ №2:

Существуют ли реальные (dis) возможности использования одного метода поверх другого или это просто вопрос личного вкуса?

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

Поправьте меня, если я ошибаюсь, но, насколько я понимаю, решением 1 является REST («создать этот ресурс»), а решением 2 — нет («выполнить это действие»).

Нет, но это распространенное заблуждение.

Архитектурный стиль REST гораздо больше интересуют вопросы типа «как клиент узнает, какому uri следовать» и «как клиент узнает, какой тип носителя следует использовать в полезной нагрузке», чем вопросы правописания.

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

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

Наоборот — когда вы хотите пересмотреть свою схему, вы предполагаете, что все клиенты должны быть переписаны? Или вы вместо этого намереваетесь отделить клиентов от деталей реализации домена?

Вспомните шаблон адаптера из Gang of Four — вы предоставляете своим клиентам хорошо спроектированный, стабильный API, с которым они могут взаимодействовать, и при реализации ваших ресурсов вы адаптируете запросы, которые получаете, к текущей реализации вашей модели.

Филдинг, 2008

REST — это разработка программного обеспечения в масштабе десятилетий: каждая деталь предназначена для обеспечения долговечности программного обеспечения и независимой эволюции.

Помните: если эти свойства для вас не важны, если они не поддерживают ваше текущее ценностное предложение, тогда вам нужно поменять эти ограничения на что-то более подходящее.