Żądanie 400 BAD oznacza kod błędu HTTP?

346

Mam żądanie JSON, które publikuję na adres URL HTTP.

Czy należy to traktować jako miejsce, w 400którym requestedResourceistnieje pole, ale czy "Roman"jest ono niepoprawną wartością dla tego pola?

[{requestedResource:"Roman"}] 

Powinno to być traktowane jako 400gdzie "blah"pole nie istnieje w ogóle?

[{blah:"Roman"}]
Feniks
źródło
34
Może 402 , jeśli naprawdę chcą móc wysłać wartość Roman, muszą po prostu zapłacić więcej :)
Jason Sperske
Prawdziwy scenariusz, w którym to widziałem - wykonałem wywołanie PUT, aby dodać trochę danych. Ponownie wykonałem wywołanie put, używając tego samego ciała żądania i otrzymałem 400, która powiedziała mi, że poprzednie żądanie jest już przetwarzane. Dodanie tych danych przez nasz system zajmuje trochę czasu.
MasterJoe2

Odpowiedzi:

361

400 oznacza, że ​​żądanie było źle sformułowane. Innymi słowy, strumień danych wysyłany przez klienta na serwer nie był zgodny z regułami.

W przypadku interfejsu API REST z ładunkiem JSON, 400 jest zwykle i właściwie powiedziałbym, że wskazuje, że JSON jest w jakiś sposób nieprawidłowy zgodnie ze specyfikacją API dla usługi.

Zgodnie z tą logiką oba podane scenariusze powinny mieć 400.

Wyobraź sobie, że zamiast tego były to XML, a nie JSON. W obu przypadkach kod XML nigdy nie przejdzie sprawdzania poprawności schematu - z powodu niezdefiniowanego elementu lub niewłaściwej wartości elementu. To byłaby zła prośba. Ta sama oferta tutaj.

Widja
źródło
3
Zgadzam się z tobą do „Zgodnie z tą logiką oba podane scenariusze powinny być 400”. Nie sądzę, żeby treść JSON miała tutaj znaczenie. Kiedy mówisz, że jest źle sformułowany, chciałbym wierzyć, że rozwiązuje to problemy w formacie przesyłanych danych, na przykład jeśli pominiesz pole w JSON, powinieneś dostać 400.
Geethanga
2
Przyzwoity zestaw kodów odpowiedzi REST znajduje się na restapitutorial.com/httpstatuscodes.html . Może to również zależeć od tego, jak chcesz obsłużyć prawidłowe żądanie, takie jak niedozwolona metoda 406 (niedopuszczalna) lub 405. Jednak wartość 400 jest odpowiednia, ponieważ „Żądanie nie mogło być zrozumiane przez serwer z powodu nieprawidłowej składni. Klient NIE POWINIEN powtarzać żądania bez modyfikacji.”
Andrew Scott Evans,
3
Tak więc „Żądanie nie może być zrozumiane przez serwer z powodu źle sformułowanej składni” może być albo żądaniem (na przykład jeden z nagłówków HTTP jest źle sformułowany) lub danymi przenoszonymi przez żądanie (na przykład brak wartości JSON) ?
MC Cesarz
2
Vidya mówi: „XML nigdy nie przejdzie sprawdzania poprawności schematu”. Chodzi o to, że parsery XML rozróżniają między dokumentem, który jest dobrze sformułowany (tj. Poprawny składniowo) i poprawny (tj. Poprawny semantycznie, np. Zgodnie ze schematem). Opis kodu 400 brzmi: „żądanie nie mogło zostać zrozumiane przez serwer z powodu źle sformułowanej składni ” - dlatego nie powinno się go używać do błędów sprawdzania poprawności, imho.
Martin Lie
@Vidya stackoverflow.com/questions/42851301/ ... spójrz na ten błąd Mam również do czynienia z tym samym problemem podobnym do tego błędu, jeśli wiesz, proszę o pomoc
Mohan Gopi
74

Od w3.org

10.4.1 400 Zła prośba

Serwer nie mógł zrozumieć żądania z powodu nieprawidłowej składni. Klient NIE POWINIEN powtarzać żądania bez modyfikacji.

Jason Sperske
źródło
10
Poprawność zwracania błędu 400 nie jest oparta na polu względem wartości, ale na żądaniu jako całości. Myślę, że HTTP 400 jest dobrym rozwiązaniem
Jason Sperske
Czy masz na myśli, że 400 odpowiedzi należy użyć, aby powiedzieć klientom, że cokolwiek, np. Adres URL, nagłówki, treść itp., W żądaniu może być niepoprawne, a nie tylko treść?
MasterJoe2,
3
dobrze dla adresu URL poprawnym kodem jest 404, w przypadku nagłówków, myślę, że to rzut w górę, 403 (zabronione) wydaje się właściwą drogą, jeśli nagłówki odrzucają tożsamość, ale co, jeśli nagłówki określają format wyjściowy? jedyną drogą, która moim zdaniem wydaje się słuszna dla 400, jest sytuacja, w której żądane jest działanie, które nie ma sensu i nie powinno być powtarzane. Napisałem tę odpowiedź 4 lata temu, obecnie czuję, że nawet błędy powinny zwrócić 200, i że błędy powinny dotyczyć tylko transmisji HTTP, a nie ładunku.
Jason Sperske
1
Ta odpowiedź obejmuje wiele z tego, choć nie przeczytałem jeszcze wszystkich wykresów stackoverflow.com/a/34324179/16959
Jason Sperske
Usługi równoważenia obciążenia, serwery proxy i inne oprogramowanie pośredniczące @JasonSperske często używają kodów stanu, aby pomóc w trasowaniu, zgłaszaniu i naprawie. na szczęście kody, takie jak „422”, odnoszą się wyraźnie do ładunku, więc w specyfikacji jest trochę miejsca na kody stanu ładunku.
Erik Aronesty
53

Wybór kodu odpowiedzi HTTP jest dość łatwym zadaniem i można go opisać za pomocą prostych reguł. Jedyną trudną częścią, o której często się zapomina, jest paragraf 6.5 z RFC 7231:

Z wyjątkiem odpowiedzi na żądanie HEAD, serwer POWINIEN przesłać reprezentację zawierającą wyjaśnienie sytuacji błędu oraz informację, czy jest to stan tymczasowy czy trwały.

Reguły są następujące:

  1. Jeśli żądanie się powiodło, zwróć kod 2xx (3xx dla przekierowania). Jeśli na serwerze wystąpił wewnętrzny błąd logiczny, zwróć 5xx. Jeśli w żądaniu klienta jest coś nie tak, zwróć kod 4xx.
  2. Przejrzyj dostępny kod odpowiedzi z wybranej kategorii. Jeśli jedno z nich ma nazwę, która dobrze pasuje do Twojej sytuacji, możesz go użyć. W przeciwnym razie wystarczy wrócić do kodu x00 (200, 400, 500). W razie wątpliwości przejdź do kodu x00.
  3. Zwróć opis błędu w treści odpowiedzi. W przypadku kodów 4xx musi zawierać wystarczającą ilość informacji, aby programista klienta mógł zrozumieć przyczynę i naprawić klienta. W przypadku 5xx ze względów bezpieczeństwa nie wolno ujawniać żadnych szczegółów.
  4. Jeśli klient musi rozróżniać różne błędy i reagować w zależności od nich, zdefiniuj format błędów możliwy do odczytu maszynowego i rozszerzalny i używaj go wszędzie w interfejsie API. Dobrą praktyką jest robić to od samego początku.
  5. Pamiętaj, że programista klienta może robić dziwne rzeczy i próbować analizować ciągi zwracane jako opis czytelny dla człowieka. A zmieniając ciągi, złamiesz tak źle napisanych klientów. Dlatego zawsze dostarczaj opis do odczytu maszynowego i staraj się unikać zgłaszania dodatkowych informacji w tekście.

Więc w twoim przypadku zwróciłem błąd 400 i coś takiego, jeśli „Roman” jest uzyskiwany z danych wejściowych użytkownika, a klient musi mieć określoną reakcję:

{
    "error_type" : "unsupported_resource",
    "error_description" : "\"Roman\" is not supported"
}

lub bardziej ogólny błąd, jeśli taka sytuacja jest złym błędem logicznym u klienta i nie jest oczekiwana, chyba że programista popełnił błąd:

{
    "error_type" : "malformed_json",
    "error_description" : "\"Roman\" is not supported for \"requestedResource\" field"
}
Aleksiej Guseynow
źródło
21

W żadnym przypadku „składnia jest zniekształcona”. Błędna jest semantyka. Dlatego IMHO 400 nie jest odpowiedni. Zamiast tego należałoby zwrócić wartość 200 wraz z obiektem błędu, takim jak { "error": { "message": "Unknown request keyword" } }cokolwiek innego.

Rozważ ścieżki przetwarzania klienta. Błąd w składni (np. Niepoprawny JSON) jest błędem w logice programu, innymi słowy, rodzajem błędu i powinien być odpowiednio traktowany, w sposób podobny do powiedzmy 403; innymi słowy, coś złego poszło nie tak.

Z drugiej strony, błąd w wartości parametru jest błędem semantyki, być może z powodu, na przykład, źle zweryfikowanego wprowadzania danych przez użytkownika. To nie jest błąd HTTP (choć przypuszczam, że może to być 422). Ścieżka przetwarzania byłaby inna.

Na przykład w jQuery wolałbym nie pisać pojedynczej procedury obsługi błędów, która dotyczy zarówno rzeczy takich jak 500, jak i niektórych błędów semantycznych specyficznych dla aplikacji. Inne frameworki, w tym Ember, również traktują błędy HTTP, takie jak 400 i 500, identycznie jak duże awarie tłuszczu, wymagające od programisty wykrycia tego, co się dzieje i rozgałęzienia w zależności od tego, czy jest to „prawdziwy” błąd, czy nie.


źródło
4
+1, P w HTTP oznacza Protokół, a jeśli odpowiedzią jest błąd HTTP, powinien to być problem niskiego poziomu. Przez lata unikałem dużej złożoności kodu, stosując podejście opisane przez torazaburo. Byłoby mniej bólu w ziemi REST, gdybyśmy wszyscy napisali odporny kod zamiast tak często wysadzać w błąd błędy HTTP.
Dem Pilafian
25
200 oznacza, że ​​żądanie zostało przetworzone, więc normalna logika sukcesu powinna zostać wykonana na kliencie. Tutaj na pewno mamy błąd, więc odpowiedź nie może mieć kodu 2xx ani 3xx. Nie może to być również 5xx, ponieważ jest to błąd po stronie serwera i mamy błąd po stronie klienta. To musi być błąd 4xx. Ale opis błędu w treści odpowiedzi jest słuszny i jest w rzeczywistości sposobem zalecanym przez specyfikację HTTP.
Alexey Guseynov
422 jest lepszy dla rejestratorów, serwerów proxy i innych narzędzi
Erik Aronesty
16

Używanie 400kodów statusu do jakichkolwiek innych celów niż wskazywanie, że żądanie jest źle sformułowane, jest po prostu błędne.

Jeśli ładunek żądania zawiera sekwencję bajtów, której nie można było przeanalizować jako application/json(jeśli serwer oczekuje, że format danych), odpowiedni kod stanu to 415:

Serwer odmawia obsługi żądania, ponieważ jednostka żądania ma format nieobsługiwany przez żądany zasób dla żądanej metody.

Jeśli ładunek żądania jest poprawny pod względem składniowym, ale semantycznie niepoprawny, 422można użyć niestandardowego kodu odpowiedzi lub standardowego 403kodu stanu:

Serwer zrozumiał żądanie, ale odmawia jego spełnienia. Autoryzacja nie pomoże, a prośba NIE POWINNA zostać powtórzona.

Cochise Ruhulessin
źródło
3
nie, 415 dotyczy sytuacji, gdy jednostka ma być niewłaściwego typu, np. image/gifzamiast text/json w Content-Type:nagłówku. - przypuszczalnie ma to również zastosowanie, jeśli element wieloczęściowy ma określony niewłaściwy typ, patrz tools.ietf.org/html/rfc4918, gdzie omawia 422, aby uzyskać więcej dyskusji,
Jasen
8

Pomyśl o oczekiwaniach.

Jako aplikacja kliencka spodziewasz się wiedzieć, czy coś pójdzie nie tak po stronie serwera. Jeśli serwer musi zgłosić błąd, gdy go blahbrakuje lub requestedResourcewartość jest niepoprawna, odpowiedni byłby błąd 400.

film42
źródło
5

Jako uzupełnienie, dla tych, którzy mogą napotkać ten sam problem, co mój, używam $.ajaxdo wysyłania danych formularza na serwer, a także na początku dostałem 400błąd.

Załóżmy, że mam zmienną javascript,

var formData = {
    "name":"Gearon",
    "hobby":"Be different"
    }; 

Nie używaj zmiennej formDatabezpośrednio jako wartości klucza, datajak poniżej:

$.ajax({
    type: "post",
    dataType: "json",
    url: "http://localhost/user/add",
    contentType: "application/json",
    data: formData,
    success: function(data, textStatus){
        alert("Data: " + data + "\nStatus: " + status); 
    }
});

Zamiast tego użyj JSON.stringify do enkapsulacji formDatajak poniżej:

$.ajax({
    type: "post",
    dataType: "json",
    url: "http://localhost/user/add",
    contentType: "application/json",
    data: JSON.stringify(formData),
    success: function(data, textStatus){
        alert("Data: " + data + "\nStatus: " + status); 
    }
});

W każdym razie, jak pokazali inni, błąd polega na tym, że serwer nie mógł rozpoznać żądania powodującego zniekształconą składnię, po prostu zgłaszam wystąpienie w praktyce. Mam nadzieję, że komuś się przyda.

Eugene
źródło
4

Najpierw sprawdź, czy adres URL może być niepoprawny, jeśli jest poprawny, a następnie sprawdź wysyłane treści żądania, możliwą przyczyną jest brak właściwej składni żądania.

Aby rozwinąć, sprawdź znaki specjalne w ciągu żądania. Jeśli jest używany (znak specjalny), jest to główna przyczyna tego błędu.

spróbuj skopiować żądanie i przeanalizuj dane każdego tagu.

Ankur Bhutani
źródło
Otrzymywałem błąd HTTP 400, sprawdziłem, czy moja prośba ma jakieś znaki specjalne. Aby to naprawić, podałem charset = UTF-8 w typie zawartości.
Kislay Kishore,