Devo restituire uno stato HTTP 400 (richiesta non valida) se un parametro è sintatticamente corretto, ma viola una regola aziendale?


56

Dì che ho un endpoint REST che accetta un numero intero come parametro:

/makeWaffles?numberOfWaffles=3

In questo caso, voglio che il numero sia positivo perché non riesco a creare un numero negativo di waffle (e richiedere 0 waffle è una perdita di tempo). Quindi voglio rifiutare qualsiasi richiesta che non contenga un numero intero positivo. Voglio anche rifiutare una richiesta che superi un numero intero massimo (diciamo per ora che è MAX_INTEGER).

Nel caso in cui qualcuno richieda un numero non positivo di waffle, devo restituire uno stato HTTP 400 (Bad Request)? Il mio pensiero iniziale è sì: non è un numero valido per me completare la richiesta. Tuttavia, la RFC non menziona le regole aziendali come motivo per lanciarle:

Il codice di stato 400 (Richiesta non valida) indica che il server non può o non elabora la richiesta a causa di qualcosa che viene percepito come un errore client (ad es. Sintassi della richiesta non valida, framing del messaggio di richiesta non valido o instradamento della richiesta ingannevole).

Una regola aziendale non rientra in nessuno di questi tre esempi. È sintatticamente corretto, è correttamente inquadrato e non è un routing di richieste ingannevoli.

Quindi, dovrei restituire uno stato HTTP 400 (richiesta non valida) se un parametro è sintatticamente corretto, ma viola una regola aziendale? O c'è uno stato più appropriato per tornare?



Risposte:


38

Questa è una grande domanda, e ancora molto rilevante dato il contesto storico (e definizioni apparentemente contraddittorie) dei codici di ritorno HTTP. Anche tra le risposte a questa domanda ci sono definizioni contrastanti. Ciò può essere chiarito spostandosi cronologicamente.

RFC 2616 (giugno 1999)

10.4.1 400 Richiesta non valida

La richiesta non è stata compresa dal server a causa di una sintassi non corretta. Il client NON DOVREBBE ripetere la richiesta senza modifiche.

A partire da questo RFC, questo codice di stato si applicava specificamente solo alle richieste sintatticamente non valide. C'era una lacuna nei codici di stato per la convalida semantica. Pertanto, quando è arrivato RFC 4918, è nato un nuovo codice.

RFC 4918 (giugno 2007)

11.2. 422 Entità non elaborabile

Il codice di stato 422 (entità non elaborabile) indica che il server comprende il tipo di contenuto dell'entità richiesta (quindi un codice di stato 415 (tipo di supporto non supportato) è inappropriato) e la sintassi dell'entità richiesta è corretta (quindi un 400 (richiesta non valida) ) il codice di stato non è appropriato) ma non è stato in grado di elaborare le istruzioni contenute. Ad esempio, questa condizione di errore può verificarsi se un corpo di richiesta XML contiene istruzioni XML ben formate (cioè sintatticamente corrette), ma semanticamente errate.

422 Entità non elaborata è stata creata per colmare il divario della convalida semantica nella specifica originale dei codici di stato 4xx. Tuttavia, nel 2014 si è verificato un altro RFC rilevante che ha generalizzato 400 per non essere più specifico della sintassi .

RFC 7231 (giugno 2014, viola esplicitamente RFC 2616)

6.5.1. 400 Richiesta non valida

Il codice di stato 400 (Richiesta non valida) indica che il server non può o non elabora la richiesta a causa di qualcosa che viene percepito come un errore client (ad es. Sintassi della richiesta non valida, framing del messaggio di richiesta non valido o instradamento della richiesta ingannevole).

Si noti che la descrizione 422 indica che il motivo 400 è inappropriato perché 400 (a partire da 2616 RFC) deve essere restituito solo per una sintassi di richiesta errata. Tuttavia, a partire da RFC 7231, la definizione rigorosa di errore di sintassi non si applica più a 400 .

Torniamo alla domanda: mentre 422 è tecnicamente più specifico, dato questo contesto, ho potuto vedere 400 o 422 utilizzati per la convalida semantica dei parametri API. Sono titubante nell'usare 422 nelle mie stesse API perché la definizione di 422 è tecnicamente superata a questo punto (anche se non so se sia ufficialmente riconosciuto da nessuna parte). L'articolo a cui fa riferimento la risposta di Fran che incoraggia l'uso di 422 è stato scritto nel 2012, due anni prima che RFC 7231 chiarisse HTTP 400. Assicurati solo di standardizzare l'uno o l'altro.


42

Ho letto la prima risposta e non l'ho davvero concordato perché, almeno nella mia lettura, una cattiva richiesta (400) significa "Non riesco nemmeno a gestire la tua richiesta perché qualcosa è fondamentalmente sbagliato". E ho trovato questo post che rende il caso di restituire un 422.

da IETF

422 entità non elaborabile (WebDAV; RFC 4918) La richiesta era ben formata ma non poteva essere seguita a causa di errori semantici

Questa sembra una risposta più appropriata poiché la tua richiesta è ben formata, ma non supera le tue regole di validazione.


5
L'ho sentito descritto come "400 significa cattiva sintassi, 422 significa cattiva semantica".
cbojar,

33
Tutti i codici x00 sono codici generici "catch all". Un 400 non è inappropriato , solo meno specifico .
Jack,

1
Buona risposta, ma l'ansewer data dal @GoFree ha più senso per me.
Ewerton,

2
C'è un caso davvero valido per la restituzione di codici che tutti conoscono. Assolutamente tutti dovranno cercare 422, e scommetto che molti non sapranno ancora cosa farne.
sylvanaar,

9

No non dovresti. I codici HTTP sono pensati per il livello HTTP dell'applicazione. Le regole aziendali sono completamente diverse e sono specifiche dell'applicazione, quindi è necessario elaborare il proprio "protocollo".

Immagina che accada un'apocalisse e devi passare dal protocollo HTTP all'utilizzo di Pigeons. I piccioni non hanno alcun codice di ritorno, quindi dovresti cambiare il tuo livello aziendale per adattarlo. Ma la tua attività non è cambiata in alcun modo, quindi non dovresti cambiare livello aziendale. Mostra un accoppiamento stretto tra quei due strati (trasporto e affari).

Torna alla domanda: quello che dovresti fare è restituire "200 OK" con un corpo che descrive cosa è successo con la richiesta. Le specifiche lo dicono chiaramente:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1 .

200 OK

La richiesta è riuscita. Le informazioni restituite con la risposta dipendono , ad esempio, dal metodo utilizzato nella richiesta

POST un'entità che descrive o contiene il risultato dell'azione;

La tua richiesta HTTP è riuscita? Sì, il web server sa cosa fare con quella richiesta (es. Passalo alla parte server della tua applicazione). Il server Web quindi passa questa richiesta alla parte server della tua applicazione, che prende i dati POST, li elabora (li convalida nel tuo caso) e restituisce una risposta normale (nel corpo di una risposta HTTP) alla parte client della tua applicazione . Questa risposta dalla parte del server dell'applicazione può essere "Ottima, i dati che mi hai inviato sono validi" o "Mi dispiace, i dati che hai inviato non sono validi". E spetta al tuo cliente parte dell'applicazione capire cosa significa la risposta.

PS: "400 Bad Request" significa che il server web non ha capito cosa vuoi da esso. Significa che la parte del server dell'applicazione non ha nemmeno ricevuto la richiesta. O almeno è quello che significa :-)

EDIT : Ho appena realizzato, che stai facendo richiesta GET, non POST. Questa è una cattiva idea perché GET non dovrebbe cambiare lo stato dell'applicazione. GET dovrebbe semplicemente recuperare i dati dal server. Ma nella tua richiesta stai effettivamente cambiando lo stato dell'applicazione, quindi dovresti davvero usare POST.


1
Sì, restituire 404 in quel caso va bene. Non sto dicendo che il server dovrebbe sempre inviare 200 OK con una spiegazione nel corpo.
GoFree

Una spiegazione migliore che ho visto finora. Ho questa stessa domanda e sembra che tutta la parola sia diversa da me e da te @ Go Free
Ewerton

@GoFree Questa è davvero una buona risposta per ripensare API Design. Ma non è il caso che utilizziamo HTTP e il suo codice di risposta come parte eminente del livello delle regole aziendali quando utilizziamo un'API REST?
Thomas Lauria,

1
@Thomas Lauria Non ho ancora visto una corretta implementazione dell'API RESTFUL. Tuttavia, l'API REST è una parola d'ordine oggi, quindi ogni azienda deve usarla (la parola, non la tecnologia) senza realmente comprendere il concetto alla base. Quindi sì, viene usato in modo sbagliato ovunque. Ciò che i programmatori di solito creano non è un'API REST, ma un'API HTTP o API OVER HTTP. In realtà una delle poche buone implementazioni RESTFUL è lo stesso HTTP :)
GoFree

1
L'uso di 200-OK è particolarmente logico se l'applicazione include un campo "errore" nel corpo della risposta per descrivere eventuali errori di livello aziendale come valore di input troppo alto o troppo basso o mancante, prodotto esaurito, ecc.
Roland

8

Sì, l'input che non segue il contratto implicito dell'endpoint è "qualcosa percepito come un errore client" e dovrebbe restituire 400.

L'eccezione a ciò è se la regola aziendale è legata alla sicurezza (quindi 401 Unauthorizedo 403 Forbiddensarebbe meglio). In alternativa, se l'invio di un 400 perderebbe informazioni sull'esistenza di qualcosa, e quindi un 404 Not Foundpotrebbe essere più appropriato.


-3

Non sono sicuro che tutti sarebbero d'accordo, ma stiamo usando 409 - Conflict. Molti affermano che il 409 è più un conflitto con lo stato del sistema, ma abbiamo accettato l'interpretazione che un conflitto di valori di dati al di fuori dell'intervallo accettato è risolvibile dal richiedente e un uso accettabile di 409. 422 Penso che sarebbe ragionevole come la richiesta è formato correttamente ma non può essere elaborato come richiesto. Mi oppongo, tuttavia, se non si desidera implementare una serie di risposte, solo dare un 400 è ancora accettabile.


5
409 significa "lo stato in cui stai cercando di inserirlo è in conflitto con lo stato in cui un altro client sta cercando di inserirlo", serve per bloccare le scritture simultanee (usando ETags, per esempio)
Jack
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.