Розуміння REST: Дієслова, коди помилок та автентифікація


602

Я шукаю спосіб обернути API навколо функцій за замовчуванням у моїх веб-додатках, базі даних та CMS.

Я оглянувся і знайшов декілька "скелетних" каркасів. Окрім відповідей на моє запитання, є Tonic , рамка REST, яка мені подобається, тому що вона дуже легка.

Мені подобається REST найкраще за його простоту і хотів би створити на його основі архітектуру API. Я намагаюся обвести голову навколо основних принципів і ще не до кінця зрозумів це. Тому ряд питань.

1. Чи правильно я це розумію?

Скажіть, у мене ресурс "користувачі". Я можу встановити ряд таких URI, як так:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

це правильне представлення архітектури RESTful досі?

2. Мені потрібно більше дієслів

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

Серед прикладів користувача, які приходять на думку, є:

activate_login
deactivate_login
change_password
add_credit

як я можу виражати такі дії, як ті, що в архітектурі RESTful URL?

Мій інстинкт полягав би в тому, щоб зробити дзвінок GET на таку URL-адресу

/api/users/1/activate_login 

і очікуйте повернення коду статусу.

Однак це відхиляється від ідеї використання дієслів HTTP. Як ти гадаєш?

3. Як повернути повідомлення про помилки та коди

Значна частина краси REST пов'язана з використанням стандартних методів HTTP. У разі помилки я випускаю заголовок з кодом статусу помилки 3xx, 4xx або 5xx. Для детального опису помилки я можу використовувати тіло (правда?). Все йде нормально. Але яким би був спосіб передачі власного коду помилки, який більш детально описує те, що пішло не так (наприклад, "не вдалося підключитися до бази даних" або "помилка входу в базу даних")? Якщо я вкладу його в тіло разом із повідомленням, я мушу потім розібрати його. Чи є стандартний заголовок для подібних речей?

4. Як зробити аутентифікацію

  • Як виглядатиме аутентифікація на основі ключа API за принципами REST?
  • Чи є сильні моменти проти використання сеансів при автентифікації клієнта REST, окрім того, що це кричуще порушення принципу REST? :) (лише половина жартую тут, аутентифікація на основі сеансу чудово відповідає моїй існуючій інфраструктурі.)

13
@Daniel, дякую за редагування "Я більше дієслів" був навмисним каламбуром, але я залишаю це так, як є, зараз його легше читати. :)
Pekka

1
До речі, про опис помилок. Нарешті я розмістив опис помилки у заголовку відповіді. Просто додайте заголовок під назвою "Опис помилки".
Андрій Музичук

Це більше схоже на питання безпеки програми. Безпека програм - це не те, про що REST.
Назар Мерза

@NazarMerza Як виникають питання безпеки 1., 2. та 3. програми?
Pekka

Відповіді:


620

Я зауважив це запитання на пару днів, але відчуваю, що можу додати трохи розуміння. Я сподіваюся, що це може бути корисним у вашій ВІДПОВІДНОЙ задумі.


Пункт 1: Я правильно це розумію?

Ви правильно зрозуміли. Це правильне зображення архітектури RESTful. Наступна матриця з Вікіпедії може бути дуже корисною для визначення ваших іменників та дієслів:


У роботі з URI колекції, наприклад:http://example.com/resources/

  • Отримати : Список членів колекції та URI, що входять до них, для подальшої навігації. Наприклад, перерахуйте всі автомобілі на продаж.

  • PUT : Значення, визначене як «замінити всю колекцію на іншу колекцію».

  • POST : Створіть новий запис у колекції, де ідентифікатор автоматично призначається колекцією. Створений ідентифікатор зазвичай включається як частина даних, повернених цією операцією.

  • DELETE : Значення, визначене як "видалити всю колекцію".


При роботі з URI члена, наприклад:http://example.com/resources/7HOU57Y

  • GET : Отримайте подання адресованого члена колекції, виражене у відповідному MIME-типі.

  • PUT : оновіть адресований член колекції або створіть його із вказаним ідентифікатором.

  • POST : трактує адресованого члена як колекцію самостійно і створює нового підлеглого.

  • DELETE : Видаліть адресованого учасника колекції.


Точка 2: мені потрібно більше дієслів

Взагалі, якщо ви думаєте, що вам потрібно більше дієслів, це може означати, що ваші ресурси потрібно повторно ідентифікувати. Пам'ятайте, що в REST ви завжди працюєте на ресурсі або на колекції ресурсів. Те, що ви обираєте як ресурс, є досить важливим для визначення API.

Активувати / деактивувати вхід : Якщо ви створюєте новий сеанс, можливо, ви хочете розглянути "сеанс" як ресурс. Щоб створити новий сеанс, використовуйте POST для http://example.com/sessions/з обліковими записами в тілі. Щоб закінчити термін його використання, використовуйте PUT або DELETE (можливо, залежно від того, чи плануєте ви зберігати історію сеансу) http://example.com/sessions/SESSION_ID.

Змінити пароль: на цей раз ресурс є "користувачем". Вам знадобиться PUT http://example.com/users/USER_IDзі старими та новими паролями в корпусі. Ви працюєте на ресурсі "користувача", і пароль на зміну - це просто запит на оновлення. Він досить схожий на оператор UPDATE у реляційній базі даних.

Мій інстинкт полягав би в тому, щоб зробити дзвінок GET на таку URL-адресу /api/users/1/activate_login

Це суперечить дуже суттєвому принципу REST: Правильне використання HTTP-дієслів. Будь-який запит GET ніколи не повинен залишати жодних побічних ефектів.

Наприклад, GET-запит ніколи не повинен створювати сеанс в базі даних, повертати файли cookie з новим ідентифікатором сесії або залишати залишки на сервері. Дієслово GET - це як оператор SELECT в двигуні бази даних. Пам'ятайте, що відповідь на будь-який запит з дієсловом GET має бути кешована, коли запитуються з тими ж параметрами, як і коли ви запитуєте статичну веб-сторінку.


Пункт 3: Як повернути повідомлення про помилки та коди

Розгляньте коди статусу HTTP 4xx або 5xx як категорії помилок. Ви можете розробити помилку в організмі.

Не вдалося підключитися до бази даних: / Неправильний вхід у базу даних : Загалом, для цих типів помилок слід використовувати помилку 500. Це помилка на стороні сервера. Клієнт нічого поганого не зробив. 500 помилок зазвичай вважаються "повторними". тобто клієнт може повторити той самий точний запит і очікувати, що він вдасться, коли проблеми сервера будуть вирішені. Вкажіть деталі в тілі, щоб клієнт міг надати певний контекст для нас, людей.

Іншою категорією помилок була б сім'я 4xx, яка загалом вказує на те, що клієнт зробив щось не так. Зокрема, ця категорія помилок зазвичай вказує клієнтові, що не потрібно повторювати запит таким, яким він є, оскільки він буде постійно відмовлятися. тобто клієнту потрібно щось змінити перед тим, як повторити цей запит. Наприклад, в цю категорію потрапляють помилки "Ресурс не знайдено" (HTTP 404) або "Неправильний запит" (HTTP 400).


Пункт 4: Як зробити аутентифікацію

Як зазначено в пункті 1, замість того, щоб перевірити автентифікацію користувача, ви можете подумати над створенням сеансу. Вам буде повернуто новий "Ідентифікатор сесії" разом з відповідним кодом статусу HTTP (200: Доступ надано або 403: Заборонено доступ).

Тоді ви запитаєте ваш сервер RESTful: "Чи можете ви отримати мені ресурс для цього ідентифікатора сесії?".

Не існує автентифікованого режиму - REST не має статусу: Ви створюєте сеанс, ви просите сервер надати вам ресурси, використовуючи цей ідентифікатор сесії як параметр, а при виході ви скасовуєте або закінчуєте сеанс.


6
Дуже добре, однак ваше використання PUTдля зміни пароля, ймовірно, неправильне; PUTпотрібен весь ресурс, тому вам доведеться надіслати всі атрибути користувача, щоб відповідати HTTP (і, отже, HATEOAS REST). Скоріше, просто змінити пароль, який слід використовувати PATCHабо POST.
Лоуренс Дол

1
Я думаю, що ця публікація була б ідеальною, якби ви більше розширили те, що "POST: трактує адресованого члена як колекцію самостійно і створює нового підлеглого для нього". засоби. - Я знайшов, що означає «Гуглінг» - це виняток з вашої інакше чудової відповіді.
Мартін Конечний

6
Я не згоден з останнім реченням. Ви пояснюєте, як REST без громадянства. Увійти, щоб створити сеанс, а потім вийти з системи, щоб закінчити сеанс після виконання певної роботи, є найкращим прикладом значущого API.
Брендон

1
"Це суперечить дуже суттєвому принципу REST: Правильне використання HTTP-дієслів. Будь-який GET-запит ніколи не повинен залишати жодних побічних ефектів." - Що робити, якщо ви хочете підтримувати кількість звернень до ресурсу?
bobbyalex

1
Ця стаття повинна відповісти на ваші запитання. saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices
java_geek

79

Простіше кажучи, ви робите це зовсім назад.

Ви не повинні підходити до цього з тих URL-адрес, які ви повинні використовувати. URL-адреси будуть ефективно "безкоштовно", коли ви вирішите, які ресурси необхідні вашій системі І як ви представлятимете ці ресурси та взаємодію між ресурсами та станом програми.

Цитувати Роя Філдінга

API REST повинен витратити майже всі свої описові зусилля для визначення типів медіа (ів), які використовуються для представлення ресурсів та керування станом програми, або для визначення розширених імен відношень та / або розмітки з підтримкою гіпертексту для існуючих стандартних типів медіа. Будь-які зусилля, витрачені на опис того, які методи використовувати для цікавих URI, повинні бути повністю визначені в межах правил обробки для медіа-типу (і, в більшості випадків, вже визначені існуючими типами медіа). [Невдача тут означає, що інформація про позадіапазон є рушійною взаємодією замість гіпертексту.]

Люди завжди починають з URI і думають, що це рішення, і тоді вони, як правило, пропускають ключове поняття в архітектурі REST, зокрема, як було сказано вище, "Невдача тут означає, що інформація про позадіапазон викликає взаємодію замість гіпертексту. "

Якщо чесно, багато хто бачить купу URI та деякі GET та PUT та POST та вважають, що REST - це легко. REST непростий. RPC через HTTP - це легко, переміщення кропив даних назад і назад, що проксі через HTTP корисні навантаження, дуже легко. Однак REST виходить за рамки цього. REST - протокольний агностик. HTTP просто дуже популярний і підходить для систем REST.

REST живе у типах засобів масової інформації, їх визначеннях та тому, як програма керує діями, доступними для цих ресурсів, за допомогою гіпертексту (посилання, ефективно).

Існує різний погляд на типи носіїв у системах REST. Деякі віддають перевагу конкретним корисним навантаженням для додатків, а іншим подобається підняти існуючі типи медіа до ролей, що підходять для програми. Наприклад, з одного боку, у вас є конкретні XML-схеми, розроблені відповідно до вашої програми, порівняно з використанням чогось на зразок XHTML в якості представлення, можливо, через мікроформати та інші механізми.

Обидва підходи мають своє місце, я думаю, XHTML дуже добре працює в сценаріях, які перетинаються як з керованою людиною, так і з машинною мережею, тоді як колишні, більш конкретні типи даних, які я вважаю, краще полегшують взаємодію машини з машиною. Я вважаю, що підвищення продуктових форматів може ускладнити переговори щодо змісту. "application / xml + yourresource" набагато конкретніше як тип медіа, ніж "application / xhtml + xml", оскільки остання може застосовуватися до багатьох корисних навантажень, які можуть або не можуть бути чимось зацікавленим клієнтом машини, а також не можуть. визначити без самоаналізу.

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

Ваша програма допоможе вам приймати такі рішення.

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

Нагадаємо, що кожне представлення ресурсу в гіпертекстовій системі поєднує як фактичне представлення ресурсу, так і переходи стану, доступні ресурсу. Розглянемо кожен ресурс вузлом у графі, при цьому посилання є рядками, що залишають цей вузол до інших станів. Ці посилання інформують клієнтів не тільки про те, що можна зробити, але і те, що потрібно зробити для них (як хороша посилання поєднує URI та необхідний тип носія).

Наприклад, у вас можуть бути:

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

У вашій документації буде говоритися про поле rel з назвою "користувачі" та тип носія "application / xml + youruser".

Ці посилання можуть здатися зайвими, всі вони спілкуються з одним і тим самим URI. Але їх немає.

Це пов’язано з тим, що для відношення "користувачі" це посилання говорить про колекцію користувачів, і ви можете використовувати єдиний інтерфейс для роботи з колекцією (GET, щоб отримати їх усіх, DELETE видалити їх усіх тощо)

Якщо ви відправляєте POST на цю URL-адресу, вам потрібно буде передати документ "application / xml + usercollection", який, ймовірно, містить лише один екземпляр користувача в документі, щоб ви могли додати користувача, чи ні, можливо, додати кілька у один раз. Можливо, ваша документація підкаже, що ви можете просто передати один тип користувача замість колекції.

Ви можете побачити, що потрібно додатку, щоб здійснити пошук, як це визначено посиланням "пошук" і це медіатип. Документація для типу пошукових носіїв розповість про те, як це поводиться, і що можна очікувати як результати.

Однак, саме тут є URI, які в основному не мають значення. Додаток контролює URI, а не клієнтів. Крім кількох "точок входу", ваші клієнти повинні розраховувати на URI, надані додатком для його роботи.

Клієнт повинен знати, як маніпулювати та інтерпретувати типи засобів масової інформації, але не дуже потрібно дбати про те, куди він іде.

Ці два посилання семантично однакові в очах клієнтів:

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

Отже, зосередьтеся на своїх ресурсах. Зосередьтеся на їх переходах у стані програми та на те, як це найкраще досягти.


1
Дякую Віллу за цю дуже глибоку відповідь. Кілька взятих пунктів. Я усвідомлюю, що планування з "того, що виглядає URL" робить це навпаки, і я планую також з боку ресурсу. Наявність URL-адрес, з якими просто грати, полегшує розуміння поняття. Це може бути , що мої вимоги можуть бути задоволені за допомогою системи , яка не 100% принципи подальшої REST , як ви визначаєте його тут. Я оформитиму повний перелік вимог до кожного типу ресурсів, я думаю, тоді зможу визначитися. Ура.
Пекка

30

re 1 : Це виглядає добре зараз. Не забудьте повернути URI новоствореного користувача у заголовку "Місцезнаходження:" як частину відповіді на POST разом із кодом статусу "201 Створено".

повторно 2: Активація через GET - погана ідея, і включення дієслова в URI - це дизайнерський запах. Ви можете розглянути можливість повернення форми на GET. У веб-додатку це буде форма HTML із кнопкою подання; у випадку використання API ви можете повернути представлення, яке містить URI, на PUT, щоб активувати акаунт. Звичайно, ви можете включити цей URI у відповідь на POST на / користувачів також. Використання PUT забезпечить ваш запит ідентичним, тобто його можна буде надійно відправити знову, якщо клієнт не впевнений в успіху. Загалом, подумайте над тим, на які ресурси ви можете перетворити свої дієслова (свого роду "ноніфікація дієслів"). Запитайте себе, який метод вашої конкретної дії найбільш тісно узгоджується. Наприклад, change_password -> PUT; деактивувати -> ймовірно, ВИДАЛИТИ; add_credit -> можливо POST або PUT.

re 3. Не вигадуйте нові коди статусу, якщо ви не вважаєте, що вони настільки загальні, що вони заслуговують на стандартизацію в усьому світі. Постарайтеся використати найбільш підходящий доступний код стану (прочитайте про них у RFC 2616). Включіть додаткову інформацію в орган відповіді. Якщо ви справді, дійсно впевнені, що хочете винайти новий код статусу, подумайте ще раз; якщо ви все ще вірите в це, переконайтесь, що принаймні виберіть потрібну категорію (1xx -> ОК, 2xx -> інформаційна, 3xx -> перенаправлення; 4xx-> помилка клієнта, 5xx -> помилка сервера). Чи згадував я, що придумувати нові коди статусу - це погана ідея?

re 4. Якщо будь-яким способом можливо, використовуйте структуру аутентифікації, вбудовану в HTTP. Ознайомтеся з способом аутентифікації Google у GData. Як правило, не кладіть ключі API у свої URI. Постарайтеся уникати сеансів для підвищення масштабованості та кешування підтримки - якщо відповідь на запит відрізняється через те, що відбулося раніше, зазвичай ви прив’язуєте себе до конкретного екземпляра серверного процесу. Набагато краще перетворити стан сеансу в стан клієнта (наприклад, зробити його частиною подальших запитів) або зробити це явним, перетворивши його в стан сервера (тобто сервер), тобто надати йому власний URI.


Чи можете ви обговорити, чому б не ввести ключі API в URL-адреси? Це тому, що вони помітні в журналах проксі-серверів? Що робити, якщо клавіші перехідні, залежні від часу? Що робити, якщо використовується HTTPS?
MikeSchinkel

4
Крім порушення духу (URI повинні визначати речі), головним наслідком є ​​те, що воно руйнує кешування.
Стефан Тілков

22

1. Ви отримали правильне уявлення про те, як створити свої ресурси, ІМХО. Я б нічого не змінив.

2. Замість того, щоб намагатися розширити HTTP на більше дієслів, подумайте, до чого запропоновані дієслова можна звести з точки зору основних методів та ресурсів HTTP. Наприклад, замість activate_loginдієслова ви можете встановити ресурси типу: /api/users/1/login/activeщо є простим булевим. Щоб активувати вхід, просто PUTдокумент там із написом "true" або 1 або будь-що інше. Щоб відключити,PUT там документ, який порожній, або говорить 0 або неправдивий.

Аналогічно, щоб змінити або встановити паролі, просто виконайте PUTце/api/users/1/password .

Щоразу, коли вам потрібно щось додати (наприклад, кредит), подумайте з точки зору POSTs. Наприклад, ви можете зробити POSTресурс на зразок /api/users/1/creditsоргану, що містить кількість кредитів, які потрібно додати. A PUTна тому ж ресурсі може використовуватися для заміни значення, а не для додавання. А POSTз від’ємним числом у тілі віднімається тощо.

3. Настійно рекомендую не поширювати основні коди статусу HTTP. Якщо ви не можете знайти той, який точно відповідає вашій ситуації, виберіть найближчий та введіть реквізити помилки в тіло відповіді. Також пам’ятайте, що заголовки HTTP є розширюваними; ваш додаток може визначити всі власні заголовки, які вам подобаються. Наприклад, одна програма, над якою я працював, може повернутись 404 Not Foundза кількох обставин. Замість того, щоб змусити клієнта проаналізувати орган відповіді з причини, ми просто додали новий заголовок X-Status-Extended, який містив наші розширення коду власного статусу. Тож ви можете побачити відповідь на зразок:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

Таким чином, HTTP-клієнт, як веб-браузер, все одно буде знати, що робити зі звичайним кодом 404, а більш досконалий HTTP-клієнт може вибрати для X-Status-Extendedзаголовка більш конкретну інформацію.

4. Для аутентифікації я рекомендую використовувати автентифікацію HTTP, якщо можете. Але в IMHO немає нічого поганого в тому, щоб використовувати автентифікацію на основі файлів cookie, якщо це простіше для вас.


4
Акуратна ідея використання "розширених" ресурсів для того, щоб робити речі меншими частинами більшого ресурсу.
жіночий

1
Файли cookie дійсні в HTTP / REST, але сервер не повинен зберігати файли cookie як стан (а не як сеанс). Файл cookie може зберігати таке значення, як HMAC, однак його можна розібрати, не шукаючи стан в іншому місці.
Брюс Олдерсон

14

Основи REST

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

Отже, між клієнтом REST та службою REST існує контракт. Якщо ви використовуєте HTTP як базовий протокол, то наступні стандарти є частиною договору:

  • HTTP 1.1
    • визначення методу
    • визначення коду статусу
    • кеш-заголовки керування
    • прийняти та контент-заголовки
    • автентичні заголовки
  • IRI (utf8 URI )
  • корпус (виберіть одне)
    • зареєстрований тип програми MIME, наприклад, лабіринт + xml
    • тип MIME, визначений для продавця, наприклад vnd.github + json
    • загальний тип MIME с
      • RDF vocab, наприклад, ld + json & hydra , schema.org
      • специфічний профіль програми, наприклад, hal + json & param link link (я думаю)
  • гіперпосилання
    • що має містити їх (виберіть один)
      • відправлення заголовків посилань
      • надсилання відповіді на гіпермедіа, наприклад, html, atom + xml, hal + json, ld + json & hydra тощо.
    • семантика
      • використовувати зв'язки IANA і, ймовірно, власні відносини
      • використовувати специфічний для RDF vocab

REST має обмеження без громадянства, яке заявляє, що зв'язок між службою REST та клієнтом має бути без громадянства. Це означає, що служба REST не може підтримувати стани клієнта, тому ви не можете мати сховище сеансу на сервері. Ви повинні автентифікувати кожен запит. Так, наприклад, HTTP базовий auth (частина стандарту HTTP) добре, оскільки він надсилає ім'я користувача та пароль при кожному запиті.

Щоб відповісти на запитання

  1. Так, це може бути.

    Зазначимо, клієнтів не цікавить структура IRI, вони піклуються про семантику, тому що вони слідують за посиланнями, що мають зв'язки зв’язків або атрибути пов'язаних даних (RDF).

    Єдине, що важливо в IRI, це те, що один IRI повинен ідентифікувати лише один ресурс. Дозволено одному ресурсу, як користувачеві, мати багато різних IRI.

    Це досить просто, чому ми використовуємо приємні ІРІ на зразок /users/123/password; набагато простіше написати логіку маршрутизації на сервері, коли ти розумієш IRI, просто прочитавши її.

  2. У вас більше дієслів, таких як PUT, PATCH, OPTIONS і навіть більше, але більше їх вам не потрібно ... Замість додавання нових дієслів ви повинні навчитися додавати нові ресурси.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (Вхід не має сенсу з точки зору REST через обмеження без громадянства.)

  3. Ваших користувачів не хвилює, чому проблема існує. Вони хочуть знати, чи є успіх чи помилка, і, ймовірно, повідомлення про помилку, яке вони можуть зрозуміти, наприклад: "Вибачте, але ми не змогли зберегти вашу публікацію." Тощо.

    Заголовки статусу HTTP - це ваші стандартні заголовки. Все інше повинно бути в тілі, я думаю. Одного заголовка недостатньо, щоб описати, наприклад, докладні багатомовні повідомлення про помилки.

  4. Обмеження без громадянства (поряд з кешем і шаруватими обмеженнями в системі) гарантує, що служба добре масштабується. Ви точно не хочете підтримувати мільйони сеансів на сервері, коли ви можете робити те ж саме на клієнтах ...

    Сторонній клієнт отримує маркер доступу, якщо користувач надає доступ до нього за допомогою основного клієнта. Після цього сторонній клієнт надсилає маркер доступу з кожним запитом. Є більш складні рішення, наприклад, ви можете підписати кожен запит і т. Д. Детальнішу інформацію можна знайти в посібнику OAuth.

Супутня література


11

Для наведених вами прикладів я використовую наступне:

activate_login

POST /users/1/activation

деактивація_логін

DELETE /users/1/activation

change_password

PUT /passwords (це передбачає, що користувач має автентифікацію)

add_credit

POST /credits (це передбачає, що користувач має автентифікацію)

Якщо ви отримаєте помилки, ви повернете помилку в тілі у форматі, до якого ви отримали запит, тож якщо ви отримаєте:

DELETE /users/1.xml

Ви надішлете відповідь ще в XML, те саме було б і для JSON тощо.

Для аутентифікації слід використовувати http-аутентифікацію.


1
Я б не використовував createяк частину URI (пам’ятайте, що URI повинні бути іменниками, а методи HTTP повинні бути дієсловами, які оперують цими іменниками.) Натомість я мав би ресурс, /users/1/activeякий може бути простим булевим, і це може бути встановити шляхом Введення на цей ресурс 1 або 0.
friedo

Ви маєте рацію, я вийняв / створити. Це має бути просто посада на ресурс синглтон.
jonnii

3
Я також не використовував activationби URI, якщо ви явно не маніпулюєте та керуєте ресурсом на ім'я /users/1/activation. Що робить GET на цьому? Що робить PUT? Мені напевно здається, що Ви багатослівно визначаєте URI. Крім того, що стосується переговорів щодо типу вмісту, то це також найкраще залишати поза URI та вставляти в заголовки, як Accept.
Чесо

6
  1. Використовуйте публікацію, коли ви не знаєте, як виглядатиме новий URI ресурсу (ви створюєте нового користувача, додаток призначить новому користувачеві його ідентифікатор), PUT для оновлення або створення ресурсів, які ви знаєте, як вони будуть представлені (приклад : PUT /myfiles/thisismynewfile.txt)
  2. повернути опис помилки в тілі повідомлення
  3. Ви можете використовувати автентифікацію HTTP (якщо її достатньо) Веб-сервіси повинні бути державними

5

Я б запропонував (як перший пропуск), який PUTслід використовувати лише для оновлення існуючих об'єктів. POSTслід використовувати для створення нових. тобто

/api/users     when called with PUT, creates user record

не відчуває мене правильно. Однак решта вашого першого розділу (повторне використання дієслів) виглядає логічно.


певно, хтось подумав, що це насправді не відповідь на його запитання
lubos hasko

6
Я приймаю PUT проти POST для створення нових сутностей - використовувати PUT, коли абонент контролює ім'я ресурсу, тож ви можете PUT на точний ресурс та POST, коли виклик керує новим іменем ресурсу (наприклад, у прикладі тут).
SteveD

5

Докладний, але скопійований із специфікації методу HTTP 1.1 за адресою http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9.3 Отримати

Метод GET означає отримати будь-яку інформацію (у формі сутності), ідентифіковану URI-запитом. Якщо запит-URI посилається на процес створення даних, саме отримані дані повертаються як суб'єкт у відповіді, а не вихідний текст процесу, якщо тільки цей текст не є результатом процесу.

Семантика методу GET змінюється на "умовний GET", якщо повідомлення запиту включає в себе заголовок If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match або If-Range. Умовний метод GET вимагає перенесення об'єкта лише за обставин, описаних полями (умовами) умовного заголовка. Умовний метод GET призначений для зменшення зайвого використання мережі, дозволяючи оновити кешовані об'єкти, не потребуючи декількох запитів або передачі даних, які вже зберігаються клієнтом.

Семантика методу GET змінюється на "часткове GET", якщо повідомлення запиту включає поле заголовка діапазону. Часткове GET вимагає передати лише частину об'єкта, як описано в розділі 14.35. Частковий метод GET призначений для зменшення зайвого використання мережі, дозволяючи частково витягнутим об'єктам завершитись без передачі даних, які вже утримуються клієнтом.

Відповідь на запит GET є кешованим, якщо і лише якщо він відповідає вимогам щодо кешування HTTP, описаних у розділі 13.

Див. Розділ 15.1.3 щодо міркувань безпеки при використанні форм.

9.5 POST

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

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

Фактична функція, що виконується методом POST, визначається сервером і зазвичай залежить від запиту-URI. Опублікована особа підпорядковується цьому URI так само, як файл підпорядковується директорії, що містить його, стаття новин підпорядковується групі новин, до якої вона розміщена, або запис підпорядковується базі даних.

Дія, виконана методом POST, може не призвести до ресурсу, який можна ідентифікувати за допомогою URI. У цьому випадку або 200 (ОК), або 204 (Без вмісту) є відповідним статусом відповіді, залежно від того, включена у відповідь сутність, яка описує результат.

Якщо ресурс створено на початковому сервері, відповідь ДОЛЖЕН би бути 201 (Створено) і містити сутність, яка описує статус запиту та посилається на новий ресурс, та заголовок Location (див. Розділ 14.30).

Відповіді на цей метод не підлягають кешуванню, якщо тільки відповідь не включає відповідні поля заголовка кеша або закінчується. Однак відповідь 303 (див. Інше) може бути використана для спрямування агента користувача на отримання кешованого ресурсу.

POST-запити ОБОВ'ЯЗКОВО дотримуватися вимог передачі повідомлень, викладених у розділі 8.2.

З міркувань безпеки див. Розділ 15.1.3.

9.6 PUT

Метод PUT вимагає, щоб вкладений об'єкт зберігався під наданим URI-запитом. Якщо Request-URI посилається на вже існуючий ресурс, додане об'єкт ДОЛЖНЕ розглядатися як модифікована версія тієї, що знаходиться на сервері походження. Якщо Uquest-URI не вказує на існуючий ресурс і URI може бути визначений як новий ресурс запитуючим агентом користувача, сервер-джерело може створити ресурс з цим URI. Якщо створений новий ресурс, сервер-джерело ОБОВ'ЯЗКОВО повідомить про це агента користувача через відповідь 201 (Створено). Якщо існуючий ресурс модифікований, або відповідатимуть коди відповідей 200 (ОК) або 204 (Без вмісту), щоб вказати на успішне завершення запиту. Якщо ресурс не вдалося створити або змінити за допомогою URI-запиту, ПОВИНЕН бути наданий відповідний відповідь на помилку, який відображає природу проблеми. Одержувач сутності НЕ МОЖЕ Ігнорувати будь-які заголовки вмісту * (наприклад, Контент-Діапазон), які він не розуміє та не реалізує, і ОБОВ'ЯЗКОВО повертати відповідь 501 (Не реалізовано) у таких випадках.

Якщо запит проходить через кеш, і Request-URI ідентифікує одну або більше поточно кешованих об'єктів, ці записи ОБОВ'ЯЗКОВО трактуються як застарілі. Відповіді на цей метод не є кешованими.

Принципова відмінність запитів POST від PUT відображається в різному значенні Request-URI. URI у запиті POST ідентифікує ресурс, який буде обробляти додану сутність. Цей ресурс може бути процесом прийняття даних, шлюзом до якогось іншого протоколу або окремим об'єктом, який приймає примітки. На відміну від цього, URI у запиті PUT ідентифікує об'єкт, укладений із запитом - агент користувача знає, для чого призначений URI, і сервер НЕ МОЖЕ намагатися застосувати запит до якогось іншого ресурсу. Якщо сервер бажає, щоб запит було застосовано до іншого URI,

ОБОВ'ЯЗКОВО надіслати відповідь 301 (постійно переміщена); користувальницький агент МОЖЕ приймати власне рішення щодо перенаправлення запиту чи ні.

Один ресурс МОЖЕ бути ідентифікований багатьма різними URI. Наприклад, стаття може мати URI для ідентифікації "поточної версії", яка є окремою від URI, що ідентифікує кожну конкретну версію. У цьому випадку запит PUT на загальному URI може призвести до того, що декілька інших URI визначаються сервером походження.

HTTP / 1.1 не визначає, як метод PUT впливає на стан початкового сервера.

Запити PUT ОБОВ'ЯЗКОВО виконувати вимоги щодо передачі повідомлення, викладені в розділі 8.2.

Якщо інше не вказано для конкретного заголовка об'єкта, заголовки сутностей у запиті PUT ДОЛЮються застосовуватися до ресурсу, створеного або модифікованого PUT.

9.7 ВИДАЛИТИ

Метод DELETE вимагає, щоб сервер-джерело видалив ресурс, ідентифікований URI-запитом. Цей метод МОЖЕ бути відмінений втручанням людини (або іншими способами) на початковий сервер. Клієнту не можна гарантувати, що операція була здійснена, навіть якщо код статусу, повернутий з початкового сервера, вказує на те, що дія успішно завершена. Однак сервер НЕ повинен вказувати на успіх, якщо під час надання відповіді він не має наміру видалити ресурс або перемістити його в недоступне місце.

Успішна відповідь повинна бути 200 (ОК), якщо відповідь включає суб'єкт, що описує статус, 202 (Прийнято), якщо дія ще не здійснено, або 204 (Немає вмісту), якщо дія було введено, але відповідь не включає суб'єкт господарювання.

Якщо запит проходить через кеш, і Request-URI ідентифікує одну або більше поточно кешованих об'єктів, ці записи ОБОВ'ЯЗКОВО трактуються як застарілі. Відповіді на цей метод не є кешованими.


2

Про коди повернення REST: неправильно змішувати коди протоколу HTTP та результати REST.

Однак я бачив, що багато реалізацій змішують їх, і багато розробників можуть не погодитися зі мною.

Коди повернення HTTP пов'язані з самим HTTP Requestсобою. Виклик REST виконується за допомогою запиту протоколу передачі гіпертексту, і він працює на нижчому рівні, ніж викликається самим методом REST. REST - це концепція / підхід, а її результат - діловий / логічний результат, тоді як код результату HTTP - це транспорт .

Наприклад, повернення "404 не знайдено" під час дзвінка / користувачів / плутає, бо це може означати:

  • URI неправильний (HTTP)
  • Користувачів не знайдено (REST)

"403 заборонено / заборонено доступ" може означати:

  • Потрібен спеціальний дозвіл. Браузери можуть це впоратися, запитуючи користувача / пароль. (HTTP)
  • Неправильні дозволи доступу, налаштовані на сервері. (HTTP)
  • Вам потрібно пройти автентифікацію (REST)

І список може продовжуватися "500 помилками сервера" (помилка Apache / Nginx HTTP, викинута помилками або помилка обмеження бізнесу в REST) ​​або іншими помилками HTTP тощо ...

З коду важко зрозуміти, що було причиною відмови, помилкою HTTP (транспорту) або REST (логічним) збоєм.

Якщо запит HTTP фізично був виконаний успішно, він завжди повинен повертати 200 код, незалежно від того, знайдено чи ні запис. Оскільки ресурс URI знайдений та обробляється http-сервером. Так, він може повернути порожній набір. Чи можна отримати порожню веб-сторінку з 200 результатами як http, так?

Замість цього ви можете повернути 200 HTTP-код і просто JSON з порожнім масивом / об’єктом, або використовувати прапор результату / успіху bool для інформування про стан виконаної операції.

Також деякі інтернет-провайдери можуть перехопити ваші запити та повернути вам 404 http-код. Це не означає, що ваші дані не знайдені, але на транспортному рівні щось не так.

З Вікі :

У липні 2004 року британський провайдер телекомунікаційних послуг BT Group розгорнув систему блокування вмісту Cleanfeed, яка повертає помилку 404 у будь-який запит на вміст, визначений Фондом Інтернет-годин, як потенційно незаконний. Інші провайдери повертають HTTP 403 "заборонену" помилку за тих самих обставин. Практика використання підроблених 404 помилок як засобу для приховування цензури також повідомляється в Таїланді та Тунісі. У Тунісі, де цензура була жорстокою до революції 2011 року, люди усвідомили характер фальшивих помилок 404 і створили уявного персонажа на ім'я "Аммар 404", який представляє "невидимого цензора".

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