Разработка REST API: одна конечная точка с логикой if / else или две отдельные конечные точки на основе ролей - PullRequest
1 голос
/ 05 ноября 2019

У меня есть загадка разработки / разработки API. Допустим, у меня есть конечная точка /api/customers, которая ПОЛУЧАЕТ всех клиентов (игнорируйте нумерацию страниц). Однако есть и поворот: если обычный user получает доступ к этой конечной точке, они получат только клиентов, созданных этим пользователем и никем другим (я могу проверить токен доступа и подполе, чтобы определить, кто отправил запрос). Другой вариант использования: если admin получает доступ к этой конечной точке, они должны получить ВСЕХ клиентов, независимо от того, кто их приобрел.

Теперь мой вопрос с точки зрения проектирования API: лучше ли иметь роль if/elseпроверьте в самом контроллере API, чтобы определить, должен ли я возвращать ВСЕХ (администраторов) клиентов или конкретных (пользовательских) клиентов, ИЛИ я должен различать конечные точки для пользователя и администратора? Т.е. единственной конечной точкой администратора для всех клиентов будет /api/admin/customers, а обычные пользователи могут по-прежнему иметь доступ к своим /api/customers?

Ответы [ 4 ]

3 голосов
/ 05 ноября 2019

Это зависит от вашего проекта.

  1. Если есть только 2 случая, как вы упомянули
    • , получают клиентов, созданных этим пользователем только для regular пользователей
    • получить всех клиентов для admin пользователей

тогда было бы лучше использовать 1 конечную точку, добавив промежуточное ПО для проверки роли текущего пользователя.

Если вы планируете расширить свой проект. например, если admin пользователи также необходимы для получения клиентов, созданных этим пользователем, лучше создать 2 конечные точки. один для всех клиентов, другой для клиентов текущего пользователя. как - api/customers/all, api/customers/me
2 голосов
/ 05 ноября 2019

В REST нормально иметь несколько ресурсов, которые совместно используют одни и те же представления.

Например, «предпочтительной версией авторов» научной статьи является отображение, значение которого меняется со временемтогда как сопоставление с «статьей, опубликованной в трудах конференции X», является статичным. Это два разных ресурса, даже если они оба отображаются в одно и то же значение в определенный момент времени. Различие необходимо для того, чтобы оба ресурса можно было идентифицировать и ссылаться независимо. Аналогичный пример из разработки программного обеспечения - это отдельная идентификация файла исходного кода с управлением версиями при обращении к «последней редакции», «редакции номер 1.2.7» или «редакции, включенной в выпуск Orange». - Fielding, 2000

Этот подход полностью соответствует тому, что у вас может быть один ресурс для «всех пользователей» и другой ресурс для «пользователей, созданных Бобом».

В тех случаях, когда все становится запутанным, это тот случай, когда вы хотите использовать тот же самый идентификатор ресурса для предоставления различных представлений. То есть, когда Алиса смотрит на «пользователей, созданных мной», она видит «пользователей, созданных Алисой», а когда Боб смотрит на «пользователей, созданных мной», он видит «пользователей, созданных Бобом».

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

В HTTP / 2 серверная отправка может избавить вас от некоторой боли в этом круговом цикле.

Правила для общих кэшей должны защищать вас от отправки взгляда Алисы на "я "ресурс для Боба, и наоборот, но полезно знать о значениях различных заголовков, чтобы вы случайно не отключили эту защиту.

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

В некоторых случаях имеет смысл рассмотреть подресурсы.

/api/customers
/api/customers#created-by-Alice
/api/customers#created-by-Bob

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

1 голос
/ 05 ноября 2019

Я думаю, что / api / Customers подходит для упомянутых случаев. Это аналогично запросу веб-страницы к index.html, возвращающему разное содержимое разным пользователям.

Если вы хотите расширить его (например, Алиса, запрашивающая список Боба), вы можете поддержать необязательные параметры запроса:

/api/customers?accessibleTo=bob
/api/customers?createdBy=bob

Для этого может потребоваться проверка авторизации (есть ли у Алисы доступ к списку Боба?), Возвращая 403 (или 404, в зависимости от вашей философии), когда не авторизован.

Также не забывайте о кэшировании,Избегайте возможности того, что два запроса к одному и тому же URL (/ api / customer) для разных пользователей приведут к тому, что один пользователь получит список другого.

0 голосов
/ 05 ноября 2019

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

...