Щоб включити ідентифікатор ресурсу в корисний вантаж або отримати з URI


13

Розробляючи API, ми зіткнулися з питанням, чи повинен PUT корисний набір містити ідентифікатор оновленого ресурсу.

Ось що ми маємо:

PUT /users/123 Payload: {name: "Adrian"}

Наш код маршруту дістає ідентифікатор з URI і продовжує оновлення.

Перші користувачі нашого API запитують, чому ми не допускаємо ідентифікатор у корисному навантаженні:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

Причина, яку ми цього не допустили, полягає в тому, що ідентифікатор копіюється у корисному навантаженні та URI.

Думаючи про це ще трохи, ми підключаємо ресурс до URI.

Якщо URI не має ідентифікатора, корисне навантаження потрібно змінити:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Чи є причини, щоб цього не зробити?

Відповіді:


14

Ви повинні з'єднати Уніфікований ідентифікатор ресурсу до ресурсу .

Коли REST реалізований за допомогою HTTP, ви використовуєте GET для отримання поточного значення ресурсу, а PUT для встановлення нового значення. GET не має корисного навантаження, тому ресурс повинен бути ідентифікований URI. І PUT логічно робиться для того ж URI, і корисне навантаження має виглядати саме так, як ви хочете, щоб наступний GET повернувся.

Ви можете використовувати POST для різних URI, але це матиме лише менший сенс, оскільки це буде непотрібно асиметричним для GET. POST для загального URI може мати сенс лише для створення нових ресурсів ( POST /users/new, payload:, {name: "Adrian"}response {id: 345, name: "Adrian"}), але це не є безсильним, і тому його слід уникати якщо ви прагнете ВІДБУТИ¹. Натомість слід резервувати ідентифікатор одним викликом, а потім використати PUT для встановлення нового ідентифікатора; це стійко до відмов, оскільки якщо перший запит не вдасться, резервування ідентифікатора може в кінцевому підсумку вичерпатись, і значення PUTбуде ідентично. Або використовувати створений клієнтом UUID.


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


3
Наскільки мені відомо, запит POST не повинен бути ідентичним. Тому я не бачу жодних проблем із публікацією повідомлення /users(немає необхідності додавати "нове").
lex82

Спасибі за Вашу відповідь. Я бачу, що це приємна особливість мати idempotency для всіх запитів, але хто каже, що це потрібно для API REST? Звичайно, багато API, які називають себе RESTful, дозволяють неідентифікувати запити POST (особливо коли сервер генерує ідентифікатори для нових ресурсів). Але навіть якщо ви застосовуєте дуже суворе визначення REST, я не бачу, яке архітектурне обмеження порушується з неімпотентними POST, як на прикладі вище.
lex82

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


3
Вся ідея POST - це не бути
безсильним

2

Думаючи про це ще трохи, ми підключаємо ресурс до URI.

Якщо URI не має ідентифікатора, корисне навантаження потрібно змінити:

PUT / ні / id / тут Корисне навантаження: {ім'я: "Adrian"} <Який користувач ???

Чи є причини, щоб цього не зробити?

Відповідь на це питання залежить від того, чи хочете ви дозволити клієнту змінити ідентифікатор?

Якщо клієнт може змінити ідентифікатор через PUT, то URI ресурсу зміниться, і ви повинні надати 301 переміщений постійно будь-який час, коли ресурс отримує доступ до старого URI.

Так, наприклад, ви починаєте з ресурсу в

/users/123

а клієнт виводить на ресурс наступне

{id: 222, name: "Adrian"}

ресурс було оновлено, і його URI зараз

/users/222

LocationПоле у відповідь PUT повинен містити новий URI, і якщо ви йдете /users/123ви повинні отримати 301відповідь з полем Розташування вказує на новий /users/222ресурс.

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

Якщо ви PUT вимагаєте до іншого URI на одному ресурсі, скажіть

/users/adian_lync

тоді, якщо цього ресурсу не існує, сервер повинен створити його та створити та ідентифікувати, коли він це робить


1
Причиною, що ми ставили під сумнів розміщення ідентифікатора у корисному навантаженні, було тому, що Backbone.js передав ідентифікатор у запиті PUT за замовчуванням. Ми можемо не допустити цього, але зараз я хочу знати, чому це поведінка за замовчуванням.
Адріан Лінч

1
Боюсь, я не знайомий з Backbone.js. Вам здається непотрібним, якщо ідентифікатор включений у URL-адресу. Можливо, нагляд з боку бісів
Кормак Малхолл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.