Buduję serwer, który pozwala klientom przechowywać obiekty. Obiekty te są w pełni zbudowane po stronie klienta, wraz z identyfikatorami obiektów, które są stałe przez cały okres życia obiektu.
Zdefiniowałem interfejs API, aby klienci mogli tworzyć lub modyfikować obiekty za pomocą PUT:
PUT /objects/{id} HTTP/1.1
...
{json representation of the object}
{Id} jest identyfikatorem obiektu, więc jest częścią identyfikatora URI żądania.
Teraz rozważam również zezwolenie klientom na tworzenie obiektu za pomocą POST:
POST /objects/ HTTP/1.1
...
{json representation of the object, including ID}
Ponieważ POST ma oznaczać operację „dołącz”, nie jestem pewien, co zrobić, jeśli obiekt już tam jest. Czy powinienem traktować to żądanie modyfikacji, czy powinienem zwrócić kod błędu (który)?
Odpowiedzi:
Moje odczucie jest
409 Conflict
najbardziej odpowiednie, jednak rzadko spotykane na wolności:źródło
HTTP 409
zLocation
nagłówkiem wskazującym na istniejący / sprzeczny zasób.Zgodnie z RFC 7231 , o 303 Zobacz inne MOGĄ być wykorzystywane Jeśli wynik przetwarzania stanowiska byłoby równoznaczne z reprezentacji istniejącego zasobu .
źródło
Osobiście korzystam z rozszerzenia WebDAV
422 Unprocessable Entity
.Zgodnie z RFC 4918
źródło
422
Chodzi o kontekst , a także o to, kto jest odpowiedzialny za obsługę duplikatów w żądaniach (serwer, klient lub oba)
Jeśli serwer po prostu wskazuje duplikat , spójrz na 4xx:
Aby zobaczyć niejawną obsługę duplikatów, spójrz na 2XX:
jeśli oczekuje się, że serwer coś zwróci , spójrz na 3XX:
gdy serwer jest w stanie wskazać istniejący zasób, oznacza to przekierowanie.
Jeśli powyższe nie wystarczy, zawsze dobrą praktyką jest przygotowanie komunikatu o błędzie w treści odpowiedzi.
źródło
Może późno do gry, ale natknąłem się na ten problem semantyki, próbując stworzyć interfejs API REST.
Aby nieco rozwinąć odpowiedź Wrikkena, myślę, że możesz użyć jednego
409 Conflict
lub403 Forbidden
zależnie od sytuacji - w skrócie, użyj błędu 403, gdy użytkownik nie może zrobić absolutnie nic, aby rozwiązać konflikt i zrealizować żądanie (np. Nie może wysłaćDELETE
żądanie jawnego usunięcia zasobu) lub użyj 409, jeśli można coś zrobić.W dzisiejszych czasach ktoś mówi „403” i przychodzi na myśl problem z uprawnieniami lub uwierzytelnianiem, ale specyfikacja mówi, że to w zasadzie serwer mówi klientowi, że nie zamierza tego zrobić, nie pytaj go ponownie, a oto dlaczego klient nie powinien „t.
Jeśli chodzi o
PUT
vs.POST
...POST
należy użyć do utworzenia nowej instancji zasobu, gdy użytkownik nie ma środków lub nie powinien utworzyć identyfikatora zasobu.PUT
jest używany, gdy znana jest tożsamość zasobu.źródło
POST
żądanie (przy prawidłowym użyciu), ponieważ stwierdza, że powinien zostać zwrócony, gdy wystąpi konflikt z zasobem docelowym . Ponieważ zasób docelowy nie został jeszcze zaksięgowany, nie może być w konflikcie, a zatem odpowiedź za pomocą409 Conflict
nie ma żadnego sensu.POST
, w rzeczywistości wywnioskowałbym coś przeciwnego, ponieważ „Konflikty najprawdopodobniej wystąpią w odpowiedzi na żądanie PUT”. wydaje się wskazywać, że inne metody żądania mogą również korzystać z tego kodu. Dodatkowo: „Treść odpowiedzi powinna zawierać wystarczającą ilość informacji, aby użytkownik mógł rozpoznać źródło konfliktu. Idealnie, by jednostka odpowiedzi zawierała wystarczającą ilość informacji dla użytkownika lub agenta użytkownika, aby rozwiązać problem; może to jednak nie być możliwe i jest nie wymagane ”. ( webdav.org/specs/rfc2616.html#status.409 )„302 Znaleziono” brzmi dla mnie logicznie. A RFC 2616 mówi, że można odpowiedzieć na inne żądania niż GET i HEAD (i to z pewnością obejmuje POST)
Ale nadal utrzymuje odwiedzającego pod tym adresem URL, aby uzyskać ten „znaleziony” zasób przez RFC. Aby przejść bezpośrednio do rzeczywistego adresu URL „Znaleziony”, należy użyć „303 Zobacz inne”, co ma sens, ale wymusza kolejne wywołanie, aby uzyskać następujący adres URL. Z drugiej strony, ten GET można buforować.
Myślę, że użyłbym „303 See Other” . Nie wiem, czy mogę odpowiedzieć „rzeczą” znalezioną w ciele, ale chciałbym to zrobić, aby zapisać jedną podróż do serwera.
AKTUALIZACJA: Po ponownym odczytaniu RFC nadal uważam, że nieistniejący kod „Znaleziono 4XX + 303” powinien być poprawny. Jednak „konflikt 409” jest najlepszym istniejącym kodem odpowiedzi (jak wskazał @Wrikken), może zawierać nagłówek lokalizacji wskazujący na istniejący zasób.
źródło
Nie sądzę, że powinieneś to zrobić.
POST służy, jak wiadomo, do modyfikacji kolekcji i służy do TWORZENIA nowego elementu. Jeśli więc wyślesz identyfikator (myślę, że to nie jest dobry pomysł), powinieneś zmodyfikować kolekcję, tj. Zmodyfikować element, ale jest to mylące.
Użyj go, aby dodać element bez identyfikatora. To najlepsza praktyka.
Jeśli chcesz przechwycić ograniczenie UNIQUE (nie identyfikator), możesz odpowiedzieć 409, tak jak w żądaniach PUT. Ale nie identyfikator.
źródło
Idę z
422 Unprocessable Entity
, który jest używany, gdy żądanie jest nieprawidłowe, ale problem nie dotyczy składni lub uwierzytelnienia.Jako argument przeciwko innym odpowiedziom użycie dowolnego
4xx
kodu innego niż kod błędu oznaczałoby, że nie jest to błąd klienta i oczywiście tak jest. Używanie4xx
kodu innego niż błąd do reprezentowania błędu klienta nie ma żadnego sensu.Wygląda na to że
409 Conflict
jest to najczęstsza odpowiedź tutaj, ale zgodnie ze specyfikacją oznacza to, że zasób już istnieje, a nowe dane, które do niego aplikujesz, są niezgodne z jego bieżącym stanem. Jeśli wysyłaszPOST
żądanie, na przykład z nazwą użytkownika, która jest już zajęta, tak naprawdę nie powoduje konfliktu z zasobem docelowym, ponieważ zasób docelowy (zasób, który próbujesz utworzyć) nie został jeszcze opublikowany. Jest to błąd specyficzny dla kontroli wersji, gdy występuje konflikt między wersją przechowywanego zasobu a wersją żądanego zasobu. Jest to bardzo przydatne w tym celu, na przykład gdy klient zbuforował starą wersję zasobu i wysyła żądanie oparte na tej niepoprawnej wersji, która nie byłaby warunkowo ważna. „W takim przypadku reprezentacja odpowiedzi prawdopodobnie zawierałaby informacje przydatne do scalenia różnic w oparciu o historię zmian.” Prośba o utworzenie innego użytkownika o tej nazwie jest po prostu nieprzetworzona i nie ma nic wspólnego z kontrolą wersji.Dla przypomnienia, 422 jest także kodem statusu, którego używa GitHub, gdy próbujesz utworzyć repozytorium o nazwie już używanej.
źródło
Myślę, że w przypadku REST musisz podjąć decyzję dotyczącą zachowania tego konkretnego systemu, w takim przypadku myślę, że „właściwa” odpowiedź byłaby jedną z kilku podanych tutaj odpowiedzi. Jeśli chcesz zatrzymać żądanie i zachowywać się tak, jakby klient popełnił błąd, który należy naprawić przed kontynuowaniem, użyj 409. Jeśli konflikt naprawdę nie jest tak ważny i chcesz kontynuować żądanie, odpowiedz poprzez przekierowanie klient znalezionej jednostki. Myślę, że odpowiednie interfejsy API REST powinny przekierowywać (lub przynajmniej dostarczać nagłówek lokalizacji) do punktu końcowego GET dla tego zasobu po zakończeniu testu POST, więc zachowanie to zapewni spójne działanie.
EDYCJA: Warto również zauważyć, że powinieneś rozważyć PUT, ponieważ podajesz identyfikator. Zatem zachowanie jest proste: „Nie dbam o to, co jest teraz, umieść to tutaj”. Oznacza to, że jeśli nic tam nie będzie, zostanie utworzone; jeśli coś tam jest, zostanie zastąpione. Myślę, że test POST jest bardziej odpowiedni, gdy serwer zarządza tym identyfikatorem. Oddzielenie dwóch pojęć w zasadzie mówi ci, jak sobie z tym poradzić (tj. PUT jest idempotentny, więc zawsze powinien działać tak długo, jak długo ładunek się sprawdza, POST zawsze tworzy, więc jeśli występuje kolizja identyfikatorów, 409 opisałby ten konflikt) .
źródło
POST
żądanie (przy prawidłowym użyciu), ponieważ stwierdza, że powinien zostać zwrócony, gdy wystąpi konflikt z zasobem docelowym . Ponieważ zasób docelowy nie został jeszcze zaksięgowany, nie może być w konflikcie, a zatem odpowiedź za pomocą409 Conflict
nie ma żadnego sensu.PUT
.W końcu innym potencjalnym sposobem leczenia jest stosowanie PATCH. PATCH definiuje się jako coś, co zmienia stan wewnętrzny i nie ogranicza się do dołączania.
PATCH rozwiązałby problem, umożliwiając aktualizację już istniejących elementów. Zobacz: RFC 5789: PATCH
źródło
Dlaczego nie zaakceptowano 202 ? Jest to żądanie OK (200s), per se nie wystąpiły błędy klienta (400s).
Z 10 definicji kodów stanu :
... ponieważ nie trzeba było go wypełniać, ponieważ już istniał. Klient nie wie, że już istniał, nie zrobił nic złego.
Opieram się na rzucaniu 202 i zwracaniu podobnych treści do tego, co
/{resource}/{id}
zwróciłby GET .źródło
Natknąłem się na to pytanie, sprawdzając poprawność kodu dla duplikatu rekordu.
Przepraszam za moją ignorancję, ale nie rozumiem, dlaczego wszyscy ignorują kod „300”, który wyraźnie mówi „wielokrotny wybór” lub „dwuznaczny”
Moim zdaniem byłby to idealny kod do budowy niestandardowego lub konkretnego systemu na własny użytek. Mogę się również mylić!
https://tools.ietf.org/html/rfc7231#section-6.4.1
źródło
Bardziej prawdopodobne jest
400 Bad Request
Ponieważ żądanie zawiera zduplikowaną wartość (wartość, która już istnieje), może być postrzegane jako błąd klienta. Musisz zmienić żądanie przed następną próbą.
Uwzględniając te fakty, możemy stwierdzić, że błędny wniosek HTTP STATUS 400.
źródło
Co z 208 - http://httpstatusdogs.com/208-already-reported ? Czy to jest opcja?
Moim zdaniem, jeśli jedyną rzeczą jest powtarzanie zasobów, nie należy zgłaszać błędów. W końcu nie ma błędu ani po stronie klienta, ani serwera.
źródło