REST API DESIGN - Отримання ресурсу через REST з різними параметрами, але однаковою схемою url


92

У мене є питання, пов’язане з дизайном URL-адреси REST. Тут я знайшов кілька відповідних публікацій: Різні представлення одного і того ж ресурсу RESTful і тут: URL-адреса RESTful для ОТРИМАННЯ за різними полями, але відповіді не зовсім зрозумілі, які найкращі практики є і чому. Ось приклад.

У мене є URL-адреси REST для представлення ресурсу "користувачі". Я можу ОТРИМАТИ користувача з ідентифікатором або адресою електронної пошти, але подання URL-адреси залишається незмінним для обох. Переглядаючи багато блогів та книг, я бачу, що люди робили це різними способами. Наприклад

прочитайте цю практику в книзі і десь на stackoverflow (здається, я не можу знайти посилання знову)

GET /users/id={id}
GET /users/email={email}

прочитайте цю практику у багатьох блогах

GET /users/{id}
GET /users/email/{email}

Параметри запитів зазвичай використовуються для фільтрації результатів ресурсів, представлених URL-адресою, але я бачив, що ця практика також використовується

GET /users?id={id}
GET /users?email={email}

Моє питання полягає в тому, що з усіх цих практик, який із них мав би найбільший сенс для розробників, які споживають apis, і чому? Я вважаю, що не існує жодних правил, що стосуються дизайну URL-адрес REST та конвенцій про імена, але я просто хотів знати, яким маршрутом я маю піти, щоб допомогти розробникам краще зрозуміти apis.

Вся допомога оцінена!


1
Я знаю, що це трохи старе, але шукаючи подібні ресурси, я натрапляю на це питання та те, яке ви шукали. Я вважаю, що це один stackoverflow.com/a/9743414/468327
Джоел Бергер

Відповіді:


104

На моєму досвіді, GET /users/{id} GET /users/email/{email}це найпоширеніший підхід. Я також би очікував, що методи повернуть 404 Not Found, якщо користувач не існує із наданими idабо email. Я б не здивувався, побачивши GET /users/id/{id}це (хоча, на мою думку, це зайве).

Коментарі щодо інших підходів

  1. GET /users/id={id} GET /users/email={email}
    • Я не думаю, що я бачив це, і якби я це бачив, це було б дуже заплутано. Це майже як намагається імітувати параметри запиту з параметрами шляху.
  2. GET /users?id={id} GET /users?email={email}
    • Думаю, ви вдарили цвях по голові, коли згадали про використання параметрів запиту для фільтрації.
    • Чи було б сенсом коли-небудь викликати цей ресурс як за допомогою, такid і за допомогою email(наприклад GET /users?id={id}&email={email})? Якщо ні, я б не використовував такий метод ресурсів.
    • Я би очікував, що цей метод отримує список користувачів із необов’язковими параметрами запиту для фільтрації, але я не очікував id, emailщо серед параметрів буде якийсь унікальний ідентифікатор. Наприклад: GET /users?status=BANNEDможе повернути список заборонених користувачів.

Перевірте цю відповідь із відповідного запитання.


Дякуємо за вступ. Насправді ти маєш рацію. Здається, я прочитав №1 у книзі "RESTful java with Jax-rs", але дещо поза контекстом. Але я дуже чітко пам’ятаю, що читав це як відповідь на одне із запитань щодо самого stackoverflow (повірте, коли я кажу, що дуже намагаюся знайти це посилання, щоб довести його своїм колегам :)) і №2 - це саме те, чим я був шукаю. Деякі відгуки про дизайн. Дякую!
shahshi15

PS: Я не впевнений, що розміщення цього повідомлення суперечить правилу тут, але ви, мабуть, можете також пролити світло на одне з моїх інших питань? будь ласка? :) stackoverflow.com/questions/20508008 / ...
shahshi15

просто щоб пояснити вашу заяву про надмірність для /users/id/{id}, це дозволяє розширити функціональність, просто дозволяє отримати доступ до одного ресурсу через кілька ідентифікаторів (id, guide, name). також відповів тут
Даніель Дубовський

4
Я відповів би, що відповідним способом посилання на конкретного Користувача, наприклад, буде / users / {id}. Якщо ви хотіли знайти користувачів за певною адресою електронної пошти, яка не є унікальним ідентифікатором для користувачів, яких я б зробив / users? Email = {email}, оскільки це спосіб фільтрувати колекцію користувачів, а не ідентифікувати один конкретний ресурс за його ресурсом ідентифікатор як / users / {id}.
Kevin M

Чудова відповідь! Thumbsup за це. Єдине, що я б рекомендував зробити, це також трохи змінити свій API, оскільки REST має бути орієнтованим на імена, щоб ваші відображення ресурсів мали бути приблизно такими: GET /user/1234а неGET /users/123
Семмі

38

Дивлячись на це прагматично, у вас є колекція користувачів:

/users   # this returns many

Кожен користувач має спеціальне розташування ресурсу:

/users/{id}    # this returns one

Ви також отримали кілька способів пошуку користувачів:

/users?email={email}
/users?name=*bob*

Оскільки це всі параметри запиту для / users, всі вони повинні повертати списки .. навіть якщо це список із 1.

Я написав допис у блозі про прагматичний дизайн RESTful API тут, де про це, серед іншого, йдеться тут: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


Дякую за відповідь vinay. Але якщо ми подумаємо про це з іншої точки зору, {email} так само, як і {id}, ЗАВЖДИ збирається повернути один результат назад. Якщо ми справді шукаємо, чому б не використовувати? Id = {id} так само, як для електронної пошти? Мені було цікаво, чи є такий спосіб бути послідовним. PS: нове для stackoverflow, не знав, що можу отримати лише одну відповідь. Але дякую за вашу відповідь! Цінуйте це. Може бути , ви можете мені допомогти з цим , а також: stackoverflow.com/questions/20508008 / ...
shahshi15

7
Тут набуває значення "дизайнерський" аспект дизайну API. Ваш ресурс повинен мати спеціальне місце розташування. Де місце? Місцезнаходження за ідентифікатором? Якщо так, то ви не "шукаєте" за ідентифікатором, ви "отримуєте" за ідентифікатором. Але ви шукаєте все інше. Звичайно, тут немає жорсткого правила. Це просто перспектива :)
Vinay Sahni

6
Я б також стверджував, що таким чином ваш API є стабільнішим. Ви дійсно знаєте, що ваш ідентифікатор унікальний, але чи справді ви впевнені в електронній адресі? Навіть якщо він унікальний, він, мабуть, не є постійним, оскільки користувач може його змінити. Отже / users? Email = {email} дає зрозуміти, що це справді запит, а не доступ до ресурсу з ідентифікатором постійного стану.
lex82

Я вважаю, що насправді це більш правильна відповідь. Фільтрування колекції за адресою електронної пошти може базуватися на підстановочних знаках, тому вона не завжди повертає лише один результат.
Kevin M

@VinaySahni Що б ви сказали про такий шаблон: /user?by=email&email="abc@pqr.com "/ user? By = id & id =" xashkhx "/ users? FilterA =" a "& filterB =" b "(множина для кількох користувачів)
Шасак,

2

Про користувацькі ресурси

на шляху /usersви завжди отримуватимете колекцію повернутих користувацьких ресурсів.

на шляху /users/[user_id]можна очікувати декількох речей:

  1. ви повинні отримати одиночний ресурс, що представляє ресурс користувача з його ідентифікатором [user_id] або
  2. відповідь не знайдено 404, якщо не існує користувача з ідентифікатором [user_id] або
  3. заборонений 401, якщо ви не маєте доступу до запитуваного ресурсу користувача.

Кожен синглтон однозначно ідентифікується за своїм шляхом та ідентифікатором, і ви використовуєте їх для пошуку ресурсу. Неможливо використовувати кілька шляхів для одиночного.

Ви можете запитати шлях за /usersдопомогою параметрів запиту ( GETParameters). Це поверне колекцію з користувачами, які відповідають запитаним критеріям. Колекція, що повертається, повинна містити користувацькі ресурси, усі з відповідним шляхом ідентифікації ресурсу у відповіді.

Параметрами може бути будь-яке поле, наявне в ресурсах колекції; firstName, lastName,id

Про електронний лист

Електронна пошта може бути як ресурсом, так і властивістю / полем ресурсу користувача.

- Електронна пошта як власність користувача:

Якщо поле є властивістю користувача, відповідь користувача буде виглядати приблизно так:

{ 
  id: 1,
  firstName: 'John'
  lastName: 'Doe'
  email: 'john.doe@example.com'
  ...
}

Це означає , що не існує ніяких спеціальних кінцевих точок для електронної пошти, але тепер ви можете знайти користувача за його електронною поштою, надіславши наступний запит: /users?email=john.doe@example.com. Який (припускаючи, що електронні адреси унікальні для користувачів) поверне колекцію з одним користувацьким елементом, який відповідає електронній пошті.

- Електронна пошта як ресурс:

Але якщо електронні листи від користувачів також є ресурсами. Тоді ви можете створити API, де /users/[user_id]/emailsповертається колекція адрес електронної пошти для користувача з ідентифікатором user_id. /users/[user_id]/emails/[email_id]повертає електронну адресу користувача з user_id та ['email_id']. Те, що ви використовуєте як ідентифікатор, залежить від вас, але я дотримуюся цілого числа. Ви можете видалити електронне повідомлення від користувача, надіславши DELETEзапит на шлях, який ідентифікує електронне повідомлення, яке потрібно видалити. Так, наприклад, DELETEon /users/[user_id]/emails/[email_id]видалить електронний лист із email_id, який належить користувачеві з user_id. Швидше за все, лише користувачеві дозволено виконувати цю операцію видалення. Інші користувачі отримають відповідь 401.

Якщо користувач може мати лише одну адресу електронної пошти, ви можете дотримуватися /users/[user_id]/email цього. Це повертає синглтон-ресурс. Користувач може оновити свою адресу електронної пошти, PUTвказавши адресу електронної пошти за цією адресою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.