Chociaż specyfikacja HTTP 1.1 wydaje się zezwalać na treści wiadomości w żądaniach DELETE , wydaje się wskazywać, że serwery powinny ją ignorować, ponieważ nie ma dla niej zdefiniowanej semantyki.
4.3 Treść wiadomości
Serwer POWINIEN odczytać i przesłać dalej treść wiadomości na każde żądanie; jeśli metoda żądania nie obejmuje zdefiniowanej semantyki dla treści jednostki, wówczas treść wiadomości POWINNA zostać zignorowana podczas obsługi żądania.
Przejrzałem już kilka powiązanych dyskusji na ten temat w SO i nie tylko, takich jak:
- Czy treść jednostki jest dozwolona dla żądania HTTP DELETE?
- Ładunki metod żądań HTTP
- HTTP GET z treścią żądania
Większość dyskusji wydaje się zgadzać, że dostarczanie treści wiadomości w DELETE może być dozwolone , ale generalnie nie jest zalecane.
Co więcej, zauważyłem trend w różnych bibliotekach klienta HTTP, w którym wydaje się, że coraz więcej ulepszeń jest rejestrowanych dla tych bibliotek w celu obsługi treści żądań w DELETE. Większość bibliotek wydaje się być do tego zobowiązana, choć czasami z niewielkim początkowym oporem.
Mój przypadek użycia wymaga dodania niektórych wymaganych metadanych do DELETE (np. „Powód” usunięcia, wraz z innymi metadanymi wymaganymi do usunięcia). Rozważyłem następujące opcje, z których żadna nie wydaje się całkowicie odpowiednia i zgodna ze specyfikacjami HTTP i / lub najlepszymi praktykami REST:
- Treść wiadomości - specyfikacja wskazuje, że treści wiadomości w DELETE nie mają wartości semantycznej; nie w pełni obsługiwane przez klientów HTTP; nie jest to standardowa praktyka
- Niestandardowe nagłówki HTTP - wymaganie niestandardowych nagłówków jest generalnie sprzeczne ze standardowymi praktykami ; używanie ich jest niezgodne z resztą mojego API, z których żadne nie wymaga niestandardowych nagłówków; ponadto brak jest dobrej odpowiedzi HTTP wskazującej złe wartości nagłówka niestandardowego (prawdopodobnie jest to zupełnie oddzielne pytanie)
- Standardowe nagłówki HTTP - żadne standardowe nagłówki nie są odpowiednie
- Parametry zapytania - dodanie parametrów zapytania w rzeczywistości zmienia usuwany identyfikator URI żądania; przeciwko standardowym praktykom
- Metoda POST - (np.
POST /resourceToDelete { deletemetadata }
) POST nie jest semantyczną opcją usuwania; POST w rzeczywistości reprezentuje odwrotną pożądaną akcję (tj. POST tworzy podrzędne zasoby; ale muszę usunąć zasób) - Wiele metod - Dzielenie żądania DELETE na dwie operacje (np. PUT delete metadata, a następnie DELETE) dzieli niepodzielną operację na dwie, potencjalnie pozostawiając niespójny stan. Przyczyna usunięcia (i inne powiązane metadane) nie są częścią samej reprezentacji zasobów.
Moją pierwszą preferencją byłoby prawdopodobnie użycie treści wiadomości, a następnie niestandardowych nagłówków HTTP; jednak, jak wskazano, podejście to ma pewne wady.
Czy istnieją jakieś zalecenia lub najlepsze praktyki zgodne ze standardami REST / HTTP dotyczące umieszczania takich wymaganych metadanych w żądaniach DELETE? Czy są jakieś inne alternatywy, których nie rozważałem?
źródło
Jersey
nie zezwalają nadelete
treść żądań.Odpowiedzi:
Pomimo pewnych zaleceń, aby nie używać treści wiadomości dla żądań DELETE, to podejście może być odpowiednie w niektórych przypadkach użycia. To podejście, które ostatecznie zastosowaliśmy po ocenie innych opcji wymienionych w pytaniu / odpowiedziach i po współpracy z konsumentami usługi.
Chociaż użycie treści wiadomości nie jest idealne, żadna z pozostałych opcji również nie była idealnie dopasowana. Treść żądania DELETE pozwoliła nam łatwo i wyraźnie dodać semantykę wokół dodatkowych danych / metadanych, które były potrzebne do towarzyszenia operacji DELETE.
Nadal byłbym otwarty na inne przemyślenia i dyskusje, ale chciałem zamknąć pętlę w tej kwestii. Doceniam wszystkie przemyślenia i dyskusje na ten temat!
źródło
Wydaje się, że pragniesz jednej z dwóch rzeczy, z których żadna nie jest czysta
DELETE
:PUT
o powód usunięcia następnie przezDELETE
zasobu. Po usunięciu zawartość zasobu nie jest już dostępna dla nikogo. „Powód” nie może zawierać hiperłącza do usuniętego zasobu. Lub,state=active
dostate=deleted
przy użyciuDELETE
metody. Zasoby ze stanem = usunięte są ignorowane przez główny interfejs API, ale nadal mogą być czytelne dla administratora lub osoby z dostępem do bazy danych. Jest to dozwolone -DELETE
nie trzeba usuwać danych kopii zapasowej zasobu, a jedynie usunąć zasób uwidoczniony pod tym identyfikatorem URI.Dowolną operację, która wymaga treści wiadomości w
DELETE
żądaniu, można podzielić na najogólniej: a,POST
aby wykonać wszystkie niezbędne zadania z treścią wiadomości, iDELETE
. Nie widzę powodu, aby łamać semantykę protokołu HTTP.źródło
PUT
powód się powiedzie, aDELETE
zasoby zawiodą? Jak można zapobiegać stanom niekonsekwentnym?Biorąc pod uwagę sytuację, którą masz, podjąłbym jedno z następujących podejść:
resource/:id
. Możesz uczynić go wykrywalnym za pomocą nagłówków Link w zasobie z każdego powodu (zrel
tagiem na każdym z nich, aby zidentyfikować przyczynę).resource/:id/canceled
. To faktycznie zmienia identyfikator URI żądania i zdecydowanie nie jest zgodny z REST. Ponownie, nagłówki linków mogą sprawić, że będzie to wykrywalne.Pamiętaj, że REST to nie prawo ani dogmat. Potraktuj to bardziej jako wskazówkę. Tak więc, jeśli ma sens nie stosować się do wskazówek dotyczących domeny, w której występuje problem, nie rób tego. Po prostu upewnij się, że konsumenci API są poinformowani o rozbieżności.
źródło
/orders/:id
to zwróci ten sam zasób co/orders/:id?exclude=orderdetails
. Ciąg zapytania jest tylko wskazówką dla serwera - w tym przypadku w celu wykluczenia szczegółów zamówienia z odpowiedzi (jeśli jest obsługiwana). Podobnie, jeśli wysyłasz DELETE do/orders/:id
lub/orders/:id?reason=canceled
lub/orders/:id?reason=bad_credit
, nadal działasz na tym samym zasobie bazowym. Aby zachować „jednolity interfejs”, miałbym domyślny powód, aby wysyłanie parametru zapytania nie było wymagane./foo?123
oznacza, że usuwasz inny zasób, niż gdybyś miał wysłać DELETE do/foo?456
.Proponuję dołączyć wymagane metadane jako część samej hierarchii URI. Przykład (naiwny):
Jeśli chcesz usunąć wpisy na podstawie zakresu dat, zamiast przekazywać datę początkową i końcową w treści lub jako parametry zapytania, skonstruuj identyfikator URI w taki sposób, aby przekazać wymagane informacje jako część identyfikatora URI.
na przykład
DELETE /entries/range/01012012/31122012
- Usuń wszystkie wpisy między 1 stycznia 2012 a 31 grudnia 2012Mam nadzieję że to pomoże.
źródło
range
określone w zapytaniu parametry lub ładunek, który jest podstawą tego pytania: aby zrozumieć podejście najlepszych praktyk do problemu, które powiedziałbym, że nie jest to.