Czy należy stosować kody stanu HTTP do reprezentowania błędów logiki biznesowej na serwerze?

20

Jestem na rozdrożu z pewnym projektem interfejsu API dla klienta (JS w przeglądarce) do rozmowy z serwerem. Używamy konfliktu HTTP 409 do przedstawienia niepowodzenia działania z powodu blokady bezpieczeństwa. Blokada satefy zapobiega tworzeniu przypadkowych zmian w systemach produkcyjnych naszych klientów. Zadanie polegało na tym, aby obsługiwać 409 nieco bardziej wdzięcznie na kliencie, aby wskazać, dlaczego określone wywołanie interfejsu API nie powiodło się.

Moim rozwiązaniem było zawinięcie modułów obsługi błędów wszystkich naszych wywołań AJAX, które wyświetlą powiadomienie klientowi, gdy coś zawiedzie z powodu 409 - wszystko jest w porządku i działa dobrze z innymi błędami 4XX i 5XX, które używają tego samego mechanizmu.

Pojawił się problem, gdy jeden z naszych operatorów obsługi tras odpowiada 409s na wystąpienie błędu logiki biznesowej - moje opakowanie AJAX zgłasza, że ​​blokada bezpieczeństwa jest włączona, podczas gdy istniejąca obsługa błędów klienta zgłasza, co (uważa), że problem jest związany z ciałem odpowiedzi. Prostym rozwiązaniem byłaby zmiana odpowiedzi osoby obsługującej lub kodu statusu, którego używamy do przedstawienia blokady bezpieczeństwa.

Co prowadzi mnie do mojego skrzyżowania: czy kody stanu HTTP powinny być nawet używane do reprezentowania błędów logiki biznesowej? To pytanie dotyczy tego samego problemu, z którym mam do czynienia, ale nie zyskało dużej przyczepności. Jak zasugerowano w odpowiedzi na link, skłaniam się ku użyciu HTTP 200 OK z odpowiednią treścią do reprezentowania błędów w logice biznesowej.

Czy ktoś ma tu jakieś mocne opinie? Czy ktoś jest w stanie przekonać mnie, że to niewłaściwy sposób reprezentowania porażki?

Joe Shanahan
źródło
3
Waham się, aby opublikować moją prostą opinię jako odpowiedź. W skrócie: generalnie unikam używania kodów stanu HTTP do reprezentowania błędów biznesowych. Powinny one dotyczyć wyłącznie statusu komunikacji między klientem a serwerem. Odpowiednim kodem stanu dla zwracania sprawdzania poprawności lub błędów logiki biznesowej będzie 400 Bad Request. Powodem tego rozdzielenia jest to, że przyszłe systemy, twórcy lub czytelnicy dokumentów mogą być zdezorientowani przez twoje odchylenie od światowego standardu.
Ivo Coumans
@IvoCoumans: zrób z tego ^ odpowiedź, abym mógł ją głosować. 400 Bad Requestponieważ ogólny kod HTTP wydaje się najlepiej obejmować błędy logiki biznesowej jako klasę.
9000
Preferencje osobiste, ale zwykle używam, 400 Bad Requestgdy brakuje danych lub nie można ich odczytać / przeanalizować. To znaczy, że same dane żądania są w jakiś sposób złe.
Kasey Speakman,
Proszę rozwinąć pojęcie „błąd logiki biznesowej”. To bardzo niejasne. Czy masz na myśli dane wejściowe, które są niepoprawne zgodnie z (poprawnymi) sprawdzeniami sprawdzania poprawności danych, dane wejściowe, które mogą być ważne w innym momencie, ale które są nieprawidłowe w obecnym stanie, lub błąd w logice biznesowej, gdy odrzuca prawidłowe dane wejściowe?
jpmc26,
@ jpmc26 Byłem celowo niejasny, ponieważ było to ogólne pytanie. Serwery dobrze poradziły sobie z żądaniem, ale zdecydowały, że zapytanie / asercja nie ma sensu.
Joe Shanahan,

Odpowiedzi:

19

Kasey obejmuje główny punkt.

Kluczowy pomysł w dowolnym interfejsie internetowym: dostosowujesz domenę, aby wyglądała jak magazyn dokumentów. GET / PUT / POST / DELETE i tak dalej to wszystkie sposoby interakcji z magazynem dokumentów.

Więc na sposób myślenia o tym, co kody do użycia, jest, aby zrozumieć, co analogiczna operacja jest w sklepie dokumentu, a co to porażka będzie wyglądać w tym analogowych.

2xx jest całkowicie nieodpowiedni

Klasa 2xx (Pomyślna) kodu statusu wskazuje, że żądanie klienta zostało pomyślnie odebrane, zrozumiane i zaakceptowane.

5xx jest również nieodpowiedni

Klasa 5xx (Błąd serwera) kodu statusu wskazuje, że serwer wie, że popełnił błąd

W tym przypadku serwer nie popełnił błędu; zdaje sobie sprawę, że w tej chwili nie należy modyfikować tego zasobu w ten sposób.

Błędy logiki biznesowej (co oznacza, że ​​niezmiennik biznesowy nie pozwala obecnie na proponowaną edycję) to prawdopodobnie 409

Kod stanu 409 (konflikt) wskazuje, że żądanie nie mogło zostać zakończone z powodu konfliktu z bieżącym stanem zasobu docelowego. Ten kod jest używany w sytuacjach, w których użytkownik może rozwiązać konflikt i ponownie przesłać żądanie. Serwer POWINIEN wygenerować ładunek zawierający wystarczającą ilość informacji, aby użytkownik mógł rozpoznać źródło konfliktu.

Zwróć uwagę na ten ostatni bit - ładunek odpowiedzi 409 powinien przekazywać konsumentowi informacje o tym, co poszło nie tak, i idealnie obejmuje kontrole hipermedialne, które prowadzą konsumenta do zasobów, które mogą pomóc w rozwiązaniu konfliktu.

Moim rozwiązaniem było zawinięcie modułów obsługi błędów wszystkich naszych wywołań AJAX, które wyświetlą powiadomienie klientowi, gdy coś zawiedzie z powodu 409 - wszystko jest w porządku i działa dobrze z innymi błędami 4XX i 5XX, które używają tego samego mechanizmu.

I wskazałbym na to jako na problem; Twoja implementacja u klienta zakładała, że ​​kod stanu był wystarczający do zdefiniowania problemu. Zamiast tego kod klienta powinien sprawdzać ładunek i działać na podstawie dostępnych tam informacji.

Tak właśnie zrobiłby to magazyn dokumentów

409  Conflict

your proposed change has been declined because ${REASON}.  
The following resolution protocols are available: ${LINKS[@]})

Dopuszczalne 400 Bad Requestbyłoby również takie samo podejście z co z grubsza „przekłada się na” Wystąpił problem z Twoją prośbą. Nie możemy zadać sobie trudu, aby dowiedzieć się, który kod stanu najlepiej pasuje, więc proszę bardzo. Szczegółowe informacje można znaleźć w ładunku ”.

Użyłbym 422. Dane wejściowe są prawidłowe, więc 400 nie jest odpowiednim kodem błędu do użycia

Specyfikacja WebDAV zawiera to zalecenie

Kod statusu 422 (Unprocessable Entity) oznacza, że ​​serwer rozumie typ treści encji żądania (stąd kod statusu 415 (Unsupported Media Type) jest nieodpowiedni), a składnia encji żądania jest poprawna (a więc 400 (Bad Request ) kod stanu jest nieodpowiedni), ale nie mógł przetworzyć zawartych instrukcji. Na przykład ten warunek błędu może wystąpić, jeśli treść żądania XML zawiera dobrze sformułowane (tj. Poprawne składniowo), ale semantycznie błędne instrukcje XML.

Nie sądzę, żeby to pasowało (choć zgadzam się, że budzi to wątpliwości 400jako alternatywa). Moja interpretacja oznacza, że 422„wysłałeś niewłaściwy byt”, gdzie 409jest „wysłałeś byt w niewłaściwym czasie”.

Innymi słowy, 422wskazuje problem z komunikatem żądania rozpatrywanym osobno, gdzie 409wskazuje, że komunikat żądania jest w konflikcie z bieżącym stanem zasobu.

Warto rozważyć dyskusję Bena Nadala na temat 422 .

VoiceOfUnreason
źródło
5
dostosowujesz swoją domenę, aby wyglądała jak magazyn dokumentów ” - chciałbym, aby ludzie to czytali i w pełni rozumieli wszystkie konsekwencje i implikacje, zanim zdecydują się na (lub przeciw) REST. Naprawdę.
JensG
„Błędy logiki biznesowej” brzmią dla mnie jak „nieprawidłowe dane wejściowe”, co zwykle jest zwykłym 400, ponieważ nie ma bardziej szczegółowego kodu błędu. Jeśli to nie dane wejściowe są niepoprawne, oznacza to, że serwer ma błąd, a 500 jest odpowiednie. Twoja odpowiedź wydaje się przesadnie zakładać naturę „błędu logiki biznesowej”.
jpmc26,
Użyłbym 422. Dane wejściowe są prawidłowe, więc 400 nie jest odpowiednim kodem błędu do użycia
Konrad
19

Z mojego doświadczenia wynika, że ​​kody błędów HTTP nie są wystarczające do przedstawienia błędów biznesowych. Są one jednak przydatne do reprezentowania klas błędów.

Tak więc, moim zaleceniem byłoby użycie kodów błędów HTTP dla kategorii błędów, ale wybranie konkretnego błędu w przypadku awarii logiki biznesowej (np. 409 Konflikt ... 200 OK wprowadziłoby w błąd tutaj) i włączenie danych w odpowiedzi wskazującej konkretny błąd biznesowy . Upewnij się, że jest to część treści odpowiedzi, a nie tekst statusu, ponieważ niektóre przeglądarki ignorują niestandardowy tekst statusu. Język, którego lubię używać, ma typy Unii, które są wygodne do reprezentowania wiadomości. Ale można również zdefiniować stałe ciągów dla przypadków błędów.

Przykłady

// error with text response
409 Conflict "safety_lock_engaged"
409 Conflict "customer_not_eligible_for_selected_discount"
// warning with JSON response
202 Accepted { "backorderedProductIds": [ 37, 476 ] }
Kasey Speakman
źródło
Kody statusu 4xx powyżej 400 mają bardzo konkretne znaczenie. Wybierz 400, jeśli twoja sprawa nie jest specjalnie objęta innymi.
jpmc26,
@ jpmc26 Jeśli nie używam kodów stanu w ten sposób, to nigdy nie są one używane. Ale skorzystaj z nich we właściwy i prawidłowy sposób w swoich odpowiedziach.
Kasey Speakman
W pewnym sensie masz rację. Nigdy nie są używane. Znaczenie wybrane dla konkretnych kodów nie wydaje się być bardzo częstym przypadkiem użycia w większości aplikacji. W porządku Jest też wiele wyjątków, których nigdy nie piszemy, aby złapać kod.
jpmc26,
@ jpmc26 Cóż, wyjątki nienajlepszym modelem do naśladowania . Ale jasne, śmiało.
Kasey Speakman
Brak rzucania lub wyłapywania określonych typów wyjątków jest analogiczny do tego, że nigdy nie używa się określonych kodów HTTP ani żadnych innych kodów błędów. Zakładałem, że to będzie oczywiste. To, czy model wyjątku jest „najlepszy”, jest całkowicie nieistotne.
jpmc26
5

Ogólnie rzecz biorąc, unikałbym używania kodów stanu HTTP do reprezentowania określonych błędów logiki biznesowej. Wynika to z tego, że mają one już znaczenie semantyczne zdefiniowane przez światowy standard. Inne systemy, nowi twórcy i tak dalej będą zdezorientowane odchyleniem standardu.

To, co znalazłem w ostatnich, podobnych badaniach, polegało na tym, że jest ogólnie przyjęte 400 Bad Requestw przypadku błędów walidacyjnych i tym podobnych. W ten sposób używasz jednego kodu stanu dla wszystkich błędów logiki biznesowej.

Nawiasem mówiąc, 409należy go użyć, gdy zasób zmienił się podczas edycji i próbowałeś go ponownie zapisać.

Ivo Coumans
źródło
4

Możesz użyć „Błędnego żądania” i dołączyć identyfikator naruszonej reguły biznesowej oraz dodatkowe szczegóły w treści odpowiedzi.

noneconnex
źródło
Nie wiem, czy serwatka została odrzucona. W ten sposób firmy mogą zwracać wyjątki biznesowe.
Skadoosh,