API - Множественные запросы против разделения ролей пользователей
-
22-12-2019 - |
Вопрос
Я работаю над интерфейсом одностраничного приложения, и мне нужно перечислить несколько студентов.Каждый студент привязан к определенному user_id
Это то, что API возвращает для всех ролей пользователей (суперадмин, администратор, профессор, студент), когда я выполняю GET /students
:
{
address: null
class_id: 184
class_name: "I B"
date_of_birth: null
first_name: "first"
gender: null
grade: 1
id: 192
last_name: "last"
nationality: null
place_of_birth: null
ranking_by_class: 0
ranking_by_school: 0
registration_number: null
user_id: 238
}
В данный момент я работаю над ролью суперадмина, когда мне нужны дополнительные данные от каждого студента (subscription_type
), который доступен только на GET /users/:id
Итак, когда я перечисляю 20-30 студентов на странице через GET /students/
, для того , чтобы получить subscription_type
, Мне также нужно будет выполнить 20-30 дополнительных запросов, по одному для каждого студента.
Я поговорил об этом с разработчиком API, и мне сказали, что включение дополнительных данных в students
"это не самый надежный способ сделать это", "это еще больше замедлит время отклика" и что "30 дополнительных запросов весят меньше, чем большой кусок".
Я ничего не знаю о работе с API, поэтому не могу ничего сказать, но неужели я сумасшедший, думая, что 30 запросов при загрузке страницы - это смехотворно?
Так что же дальше?Должен ли я идти дальше и выполнять дополнительные запросы?Должен ли он разделить ответы для каждой роли пользователя и включить только то, что мне нужно для каждой роли?Что такое правильный способ о том, чтобы справиться с этим?
Решение
Хотя, строго говоря, специалист по API прав, слишком строгое следование евангелию RESTful может привести к неэффективности, подобной проблеме 1 + N, созданной реализацией purist.Ключевая концепция в RESTful design заключается в том, что ресурсы не обязательно должны напрямую соотноситься с объектами домена.При проектировании ресурсов необходимо учитывать сценарии использования.В сценарии super admin это звучит так, как если бы клиент запрашивал коллекцию students
и ему также обычно или всегда нужны данные из users
, в частности subscription_type
.Объектная модель явно нормализована, как и должно быть, но это не говорит о том, что ресурсы должны быть или должны быть всегда.
Есть пара различных шаблонов, которые я использовал, чтобы сделать подобные сценарии более эффективными.Какие из них (если таковые имеются) применяются, зависит от того, как ресурсы потребляются клиентами.
Составной ресурс
Это комбинация всех или части двух или более объектов домена (например, student
и user
) в единый ресурс.
Поскольку все students
предположительно , также users
, вы могли бы включить все или часть пользовательских данных в студенческий ресурс по мере необходимости.
GET /students
{
address: null
class_id: 184
class_name: "I B"
date_of_birth: null
first_name: "first"
gender: null
grade: 1
id: 192
last_name: "last"
nationality: null
place_of_birth: null
ranking_by_class: 0
ranking_by_school: 0
registration_number: null
user_id: 238
subscription_type: "foo"
}
Связанные Ресурсы
(Аналогично другому ответу) Это метод, при котором клиент может указать, что он хочет, чтобы связанный ресурс был включен в ответ.Это особенно полезно в отношении типа "имеет" в модели предметной области.Это позволяет клиенту существенно отложенная нагрузка или нетерпеливая нагрузка ресурс.
GET /students
{
address: null
class_id: 184
class_name: "I B"
date_of_birth: null
first_name: "first"
gender: null
grade: 1
id: 192
last_name: "last"
nationality: null
place_of_birth: null
ranking_by_class: 0
ranking_by_school: 0
registration_number: null
user_id: 238
}
GET /students?include_user=true
{
address: null
class_id: 184
class_name: "I B"
date_of_birth: null
first_name: "first"
gender: null
grade: 1
id: 192
last_name: "last"
nationality: null
place_of_birth: null
ranking_by_class: 0
ranking_by_school: 0
registration_number: null
user_id: 238
user:
{
id: 238
subscription_type: "foo"
...
}
}
Другие советы
Здесь у вас есть две проблемы, которые не должны быть связаны друг с другом - Один - это данные, возвращаемые для каждого пользователя при индексном вызове (/students), а другой - процесс авторизации, который должен определить, к каким данным может быть открыт определенный пользователь.
Что касается проблемы с данными - я не думаю, что существует какое-то конкретное правило, которому следует следовать.Это полностью зависит от требований вашего приложения.Если поле subscription_type обычно не требуется, вы можете рассмотреть возможность передачи параметра запроса (например, 'include_extra_data=1'), чтобы указать, что оно вам нужно в конкретном запросе, где по умолчанию оно не будет возвращено.
Что касается проблемы с авторизацией - это должно быть полностью отключено от данных, которые вы запрашиваете в своем запросе.Сервер должен быть в состоянии определить, какие данные видны пользователю, в соответствии с идентификатором пользователя.(вы можете ознакомиться с Драгоценный камень КанКан][1] в качестве возможного решения).
Таким образом, объединяя эти две проблемы, пользователь любого типа должен иметь возможность отправлять запрос '/ students' с флагом 'include_extra_data' или без него.Если сервер обнаружит, что пользователь не имеет права просматривать дополнительные данные, вы можете выбрать один из 2 вариантов - либо вернуть только те данные, которые пользователю разрешено видеть, либо вернуть ответ "401 несанкционированный".
Оба способа допустимы и влияют на то, как вы обрабатываете ответ в вашем клиентском приложении.(Лично я предпочитаю более поздний вариант, поскольку он более нагляден для клиента).
Надеюсь, это поможет :)