musimy przesłać wszystkie dane artykułów z powrotem do interfejsu API w celu aktualizacji i nie można zaimplementować pracy wielu użytkowników. Na przykład redaktor mógłby wysłać dane o 5 sekund starsze i zastąpić poprawkę, którą jakiś inny dziennikarz właśnie zrobił 2 sekundy temu, i nie ma sposobu, bym mógł to wyjaśnić klientom, ponieważ publikujący artykuł nie jest w żaden sposób związany z aktualizacją treści.
Takie rzeczy są wyzwaniem bez względu na to, co robisz. Jest to bardzo podobny problem do rozproszonej kontroli źródła (mercurial, git itp.), A rozwiązanie, zapisane w HTTP / ReST, wygląda trochę podobnie.
Załóżmy, że masz dwóch użytkowników, Alice i Boba, którzy pracują nad tym /articles/lunch
. (dla jasności odpowiedź jest odważna)
Najpierw Alice tworzy artykuł.
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
Serwer nie utworzył zasobu, ponieważ do żądania nie została dołączona „wersja” (zakładając identyfikator /articles/{id}/{version}
. Aby wykonać tworzenie, Alice została przekierowana na adres URL artykułu / wersji, którą będzie tworzyć. Użytkownik Alice agent ponownie zastosuje żądanie pod nowym adresem.
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
A teraz artykuł został utworzony. następnie Bob patrzy na artykuł:
GET /articles/lunch HTTP/1.1
Host: example.com
Authorization: Basic Ym9iOnBhc3N3b3Jk
301 Moved Permanently
Location: /articles/lunch/1
Bob tam patrzy:
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?
Postanawia dodać własną zmianę.
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
Podobnie jak w przypadku Alicji, Bob zostaje przekierowany do miejsca, w którym będzie tworzył nową wersję.
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
Wreszcie Alice decyduje, że chciałaby dodać do swojego artykułu:
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.
Zamiast zostać przekierowanym jak zwykle, klient otrzymuje inny kod stanu 409
, co informuje Alice, że wersja, z której próbowała się rozgałęzić, została już rozgałęziona. Nowe zasoby i tak zostały utworzone (jak pokazano w Location
nagłówku), a różnice między nimi uwzględniono w treści odpowiedzi. Alice wie teraz, że jej prośba musi zostać w jakiś sposób połączona.
Całe to przekierowanie jest powiązane z semantyką PUT
, która wymaga, aby nowe zasoby były tworzone dokładnie tam, gdzie prosi o to linia żądania. może to również zapisać cykl żądań za pomocą POST
zamiast tego, ale wtedy numer wersji musiałby zostać zakodowany w żądaniu przez inną magię, co wydawało mi się mniej oczywiste dla celów ilustracji, ale prawdopodobnie nadal byłoby preferowane w prawdziwym API aby zminimalizować cykle zapytań / odpowiedzi.
api/article?action=publish
? Parametry zapytania są przeznaczone do takich przypadków, w których stan zasobu zależy od wspomnianego „algorytmu” (lub akcji). Np.api/articles?sort=asc
Jest ważny