Nie można modyfikować ich przez klienta, więc usunęłbym je z reprezentacji zasobów w ogóle. Pozwól mi wyjaśnić moje rozumowanie na przykładzie.
Powiedzmy, że nasz typowy przykład API zwróci następującą reprezentację do klienta, gdy poproszony o podanie jednego zasobu:
GET /example/123
<?xml version="1.0" encoding="UTF-8" ?>
<example>
<id>123</id>
<lorem>ipsum</lorem>
<dolor>sit amet</dolor>
<lastUser uri="/user/321">321</lastUser>
<lastUpdate>2011-04-16 20:00:00 GMT</lastUpdate>
</example>
Jeśli klient chce zmodyfikować zasób, że będzie przypuszczalnie podjąć całą reprezentację i odeślij ją do interfejsu API.
PUT /example/123
<?xml version="1.0" encoding="UTF-8" ?>
<example>
<id>123</id>
<lorem>foobar</lorem>
<dolor>foobaz</dolor>
<lastUser>322</lastUser>
<lastUpdate>2011-04-16 20:46:15 GMT+2</lastUpdate>
</example>
Ponieważ API generuje wartości lastUser
i lastUpdate
automatycznie i nie może zaakceptować danych dostarczonych przez klienta, najwłaściwszą odpowiedzią byłoby 400 Bad Request
lub 403 Forbidden
(ponieważ klient nie może modyfikować te wartości).
Jeśli chcemy zachować zgodność z usługą REST i wysłać pełną reprezentację zasobu podczas wykonywania żądania PUT, musimy usunąć lastUser
i z reprezentacji zasobu. Pozwoli to klientom na wysyłanie pełną jednostkę poprzez PUT:
PUT /example/123
<?xml version="1.0" encoding="UTF-8" ?>
<example>
<id>123</id>
<lorem>foobar</lorem>
<dolor>foobaz</dolor>
</example>
Serwer zaakceptuje pełną reprezentację teraz, że nie zawierają lastUpdate
i lastUser
.
Pozostaje pytanie, w jaki sposób zapewnić klientom dostęp do lastUpdate
i lastUser
. Jeśli go nie potrzebują (i te pola są wymagane tylko wewnętrznie przez API), wszystko jest w porządku, a nasze rozwiązanie jest doskonale URUCHOMIONE.Jeśli jednak klienci potrzebują dostępu do tych danych, najczystsze podejście byłoby użyć nagłówków HTTP:
GET /example/123
...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
X-Last-User: /user/322
...
<?xml version="1.0" encoding="UTF-8" ?>
<example>
<id>123</id>
<lorem>foobar</lorem>
<dolor>foobaz</dolor>
</example>
Korzystanie z niestandardowy nagłówek HTTP nie jest idealny, ponieważ aplikacje klienckie muszą się nauczyć, w jaki sposób ją przeczytać. Jeśli chcemy zapewnić klientom łatwiejszy dostęp do tych samych danych, jedyne, co możemy zrobić, to umieścić dane w reprezentacji i mamy taki sam problem, jak w pierwotnym pytaniu. Przynajmniej spróbuję jakoś go złagodzić. Jeżeli typ zawartości używane przez API XML, możemy umieścić dane do węzła atrybutów zamiast wystawiając je bezpośrednio jako wartości węzłów, tj:
GET /example/123
...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
...
<?xml version="1.0" encoding="UTF-8" ?>
<example last-update="2011-04-16 18:46:15 GMT" last-user="/user/322">
<id>123</id>
<lorem>foobar</lorem>
<dolor>foobaz</dolor>
</example>
ten sposób będziemy przynajmniej uniknąć problemu Jeżeli klient spróbuje przesłać wszystkie węzły XML w kolejnym zapytaniu PUT. To nie zadziała z JSON-em, a rozwiązanie wciąż jest na granicy idempotencji (ponieważ API musiałoby zignorować atrybuty XML podczas przetwarzania żądania).
Jeszcze lepiej, jak Jonah zauważył w komentarzach, jeśli klienci potrzebują dostępu do lastUser
i lastUpdate
, mogą być narażeni jako nowy zasób powiązany z oryginału jeden przykład w następujący sposób:
GET /example/123
<?xml version="1.0" encoding="UTF-8" ?>
<example>
<id>123</id>
<lorem>foobar</lorem>
<dolor>foobaz</dolor>
<lastUpdateUri>/example/123/last-update</lastUpdateUri>
</example>
... a potem:
GET /example/123/last-update
<?xml version="1.0" encoding="UTF-8" ?>
<lastUpdate>
<resourceUri>/example/123</resourceUri>
<updatedBy uri="/user/321">321</updatedBy>
<updatedAt>2011-04-16 20:00:00 GMT</updatedAt>
</lastUpdate>
(. Powyższe można również ładnie rozbudowany, aby zapewnić pełną dziennika kontroli z poszczególnych zmian, zapewniając changelog zasób jest dostępny)
Uwaga:
zgadzam się z Darrel Miller „s take on the question, ale chciałem pro zobaczyć na nim inne podejście. Zauważ, że takie podejście nie jest wspierane przez żadne standardy/RFC/etc, to tylko inne podejście do problemu.
W jaki sposób reprezentujesz 'LastUser' i' LastUpdate' - czy są one częścią reprezentacji zasobów (np. Węzły w XML)? – MicE
Nie, one nawet nie istnieją, gdy issiung aktualizacji, ale zwracam je, gdy kwerendy z get .... tak zrobię PUT, a następnie GET, i otrzymuję czas ostatniej aktualizacji, wydaje ponownie to samo PUT, i inny GET daje inny lastUpdate ... – opensas
OK, dziękuję za potwierdzenie - zobacz moją odpowiedź poniżej dla alternatywnego podejścia do problemu. – MicE