нам потрібно повернути всі статті статті назад в API, щоб робота з оновленнями не могла бути реалізована. Наприклад, редактор міг надіслати на 5 секунд старіші дані та переписати виправлення, які робив якийсь інший журналіст 2 секунди тому, і я не можу пояснити це клієнтам, оскільки публікація статті насправді ніяк не пов'язана з оновленням вмісту.
Така річ є проблемою, незалежно від того, що ви робите, це дуже схожа проблема з розподіленим контролем джерел (mercurial, git тощо), і рішення, написане в HTTP / ReST, виглядає дещо схожим.
Припустимо, у вас є два користувачі, Аліса та Боб, які працюють над обома /articles/lunch
. (для наочності відповідь є жирним шрифтом)
По-перше, Аліса створює статтю.
PUT /articles/lunch HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
301 Moved Permanently
Location: /articles/lunch/1
Сервер не створив ресурс, оскільки до запиту не додалася "версія" (припускаючи ідентифікатор /articles/{id}/{version}
. Для здійснення створення Аліса була перенаправлена на URL-адресу статті / версії, яку вона створюватиме. Користувач Аліси Потім агент повторно подасть запит за новою адресою.
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
201 Created
І ось стаття створена. далі, Боб розглядає статтю:
GET /articles/lunch HTTP/1.1
Host: example.com
Authorization: Basic Ym9iOnBhc3N3b3Jk
301 Moved Permanently
Location: /articles/lunch/1
Боб дивиться туди:
GET /articles/lunch/1 HTTP/1.1
Host: example.com
Authorization: Basic Ym9iOnBhc3N3b3Jk
200 Ok
Content-Type: text/plain
Hey Bob, what do you want for lunch today?
Він вирішує додати власну зміну.
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic Ym9iOnBhc3N3b3Jk
Hey Bob, what do you want for lunch today?
Does pizza sound good to you, Alice?
301 Moved Permanently
Location: /articles/lunch/2
Як і у випадку з Алісою, Боб перенаправляють туди, де він буде створювати нову версію.
PUT /articles/lunch/2 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic Ym9iOnBhc3N3b3Jk
Hey Bob, what do you want for lunch today?
Does pizza sound good to you, Alice?
201 Created
Нарешті, Аліса вирішує, що їй хотілося б додати до власної статті:
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
I was thinking about getting Sushi.
409 Conflict
Location: /articles/lunch/3
Content-Type: text/diff
---/articles/lunch/2
+++/articles/lunch/3
@@ 1,2 1,2 @@
Hey Bob, what do you want for lunch today?
-Does pizza sound good to you, Alice?
+I was thinking about getting Sushi.
Замість того, щоб переадресовуватись як звичайне, клієнту повертається інший код статусу 409
, який повідомляє Алісі, що версія, з якої вона намагалася відключитися, вже розгалужена. Нові ресурси були створені в будь-якому випадку (як показано в Location
заголовку), і відмінності між ними були включені в орган відповіді. Аліса тепер знає, що запит, який вона щойно зробила, потрібно якось об'єднати.
Все це перенаправлення пов'язане з семантикою PUT
, яка вимагає створення нових ресурсів саме там, де запитує рядок запиту. це також може зберегти цикл запитів, використовуючи POST
натомість, але тоді номер версії повинен був би бути закодований в запиті якоюсь іншою магією, яка для ілюстрації для мене здавалася менш очевидною, але, ймовірно, все-таки буде віддана перевагу в реальному API щоб мінімізувати цикли запиту / відповіді.
api/article?action=publish
? Параметри запиту призначені для таких випадків, коли стан ресурсу залежить від згаданого вами алгоритму (або дії). Наприкладapi/articles?sort=asc
, діє