Как спроектировать конечные точки API для публикации дочернего объекта и для получения всех детей всех родителей?

12

Например, у меня есть объекты: Клиент, Отчет. У клиента может быть много отчетов, и я думаю, что конечная точка для управления одним отчетом должна быть вложена следующим образом:

/clients/{client_id}/reports/{report_id}

Что касается всех отчетов одного клиента, ожидается, что enpoint:

/clients/{client_id}/reports

Но как должна выглядеть конечная точка для получения всех отчетов всех клиентов, чтобы API был согласованным и хорошо спроектированным.

Мои подходы:

  1. (Я видел это в некоторых API Google) используйте вместо него "-" и проанализируйте его как "все":

/clients/-/reports

Это сохраняет формат конечной точки таким же, но выглядит немного необычно, не может найти ни одного rfc, предлагающего этот способ.

  1. Создайте отдельную конечную точку только для всех отчетов:

/reports

Но чтобы получить Отчеты Клиента, это все равно:

/clients/{client_id}/reports

  1. Рефакторинг конечных точек, чтобы сделать «клиента» не родителем, а просто параметром фильтра:

/reports?client={client_id} - отчеты одного клиента

/reports - отчеты всего клиента

В случае добавления новой конечной точки для публикации отчета для конкретного клиента, это может выглядеть некрасиво, потому что это будет POST-запрос с параметром в URL.

Есть ли другие предложения идей?

Yann
источник
2
Вас может заинтересовать вопрос
Laiv

Ответы:

3

Но как должна выглядеть конечная точка для получения всех отчетов всех клиентов, чтобы API был согласованным и хорошо спроектированным.

Прежде всего, помните, что нет золотых правил для моделирования API RESTful. Все, что у нас есть, это лучшие практики и соглашения. При этом вероятный ответ - как обычно - выберите тот, который лучше всего соответствует вашим требованиям, и в этом случае тот, который лучше всего отражает вашу модель.

Так что проверь три варианта из выразительности.

# 1 Запись "-"

Это блестящая идея. Это позволяет нам выразить состояние всего, reportsчто принадлежитclients . Это сужает «запрос» к определенному набору отчетов (расположенных внутри clientsграницы).

Он постоянно поддерживает понятие иерархии (принадлежности), поэтому, если reportsего можно найти в разных местах, эта запись имеет большое значение. Например:

  • Все отчеты, которые принадлежат клиентам /clients/-/reports
  • Все отчеты, которые принадлежат отделам /departments/-/reports
  • Все отчеты, которые принадлежат сотрудникам /employees/-/reports

Однако для получения всех доступных отчетов в системе сохранение иерархии не дает какого-либо ценного преимущества перед следующей опцией.

# 2 Различные URI

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

Новый URI ( /reports) также оставляет открытой возможность управления отчетами . Однако нам не нужно предоставлять полную поддержку RESTful, если мы не считаем это необходимым. Например, вы заявили Make a separate endpoint just for all the reports. Это нормально, вам нужно только внедрить GETи, возможно, некоторые фильтры для запросов и все.

Обратите внимание, что вы все еще можете сделать это /reports?client={client_id}. Хорошо иметь разные URI для одного и того же ресурса. Некоторые статьи, которые я прочитал, назвали бы эту надежность .

# 3 Возвращение иерархии

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

Выводы

Обратите внимание, что # 1 и # 2 не являются взаимоисключающими. Мы можем реализовать оба. Учитывая реальную ситуацию и в соответствии с условиями ОП, я бы реализовал только № 2.


1: это эквивалентно /clients/-/reportsя думаю

LAIV
источник
0

Шаблоны проектирования API Google предлагают использовать «-» в этом сценарии.

GET /clients/-/reports

Источник:

https://cloud.google.com/apis/design/design_patterns#list_sub-collections

wfg4
источник
2
Я не согласен со всемогущим Google, но думаю, что предпочел бы что-то вроде /client/{client_id}/report/{report_id}и/clients/report/{report_id}
Роберт Харви
2
@RobertHarvey, почему не просто /reports?
17
@Laiv: Это подразумевало бы все отчеты. Обновить вашу страницу; Я сделал ниндзя редактировать.
Роберт Харви
@RobertHarvey Я имею в виду, почему бы не 2 разные конечные точки /clients...и /reports.
Laiv
1
@Laiv: Хорошо, но это только поднимает вопрос "Какие параметры мне следует указать в теле запроса?"
Роберт Харви