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

36

Supponiamo di avere un endpoint REST che accetta un 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 la richiesta di 0 waffle è una perdita di tempo). Quindi voglio rifiutare qualsiasi richiesta che non contenga un numero intero positivo. Voglio anche respingere una richiesta che supera un numero intero massimo (diciamo per ora che è MAX_INTEGER).

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

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Una regola aziendale non rientra in nessuno di questi tre esempi. È sintatticamente corretto, è correttamente incorniciato e non è un instradamento di richieste ingannevole.

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 da restituire?

    
posta Thunderforge 24.08.2016 - 21:45
fonte

5 risposte

24

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

RFC 2616 (giugno 1999)

10.4.1 400 Bad Request

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.

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

RFC 4918 (giugno 2007)

11.2. 422 Unprocessable Entity

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

422 L'entità non elaborabile è stata creata per colmare il vuoto di convalida semantica nelle specifiche originali dei codici di stato 4xx. Tuttavia, nel 2014 è emerso un altro RFC rilevante che ha generalizzato 400 per non essere più specifico della sintassi .

RFC 7231 (giugno 2014, esplicitamente obsoleto RFC 2616)

6.5.1. 400 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Si noti che la descrizione 422 dice che il motivo 400 è inappropriato perché 400 (a partire da RFC 2616) dovrebbe essere restituito solo per la 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 in questione: mentre 422 è tecnicamente più specifico, dato questo contesto, potrei vedere 400 o 422 usati per la validazione semantica dei parametri API. Sono riluttante a usare 422 nelle mie API perché la definizione di 422 è tecnicamente superata a questo punto (anche se non so se è ufficialmente riconosciuta ovunque). L'articolo a cui si fa riferimento nella risposta accettata è stato scritto nel 2012, due anni prima che RFC 7231 chiarisse l'HTTP 400. Assicurati semplicemente di standardizzare l'uno o l'altro.

    
risposta data 24.02.2017 - 15:51
fonte
40

Ho letto la prima risposta e non sono assolutamente d'accordo 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 per la restituzione di 422.

da IETF

422 Entità non elaborabile (WebDAV; RFC 4918) La richiesta era ben formata ma non è stato possibile seguirla a causa di errori semantici

Questa sembra una risposta più appropriata dal momento che la tua richiesta è ben strutturata, ma non passa le tue regole di convalida.

    
risposta data 24.08.2016 - 22:09
fonte
7

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

Le eccezioni a questo sono se la regola aziendale è legata alla sicurezza (allora 401 Unauthorized o 403 Forbidden sarebbe meglio). In alternativa, se l'invio di 400 causerebbe la perdita di informazioni sull'esistenza di qualcosa, e quindi 404 Not Found potrebbe essere più appropriato.

    
risposta data 24.08.2016 - 21:57
fonte
7

No, non dovresti. I codici HTTP sono pensati per il livello HTTP della tua applicazione. Le regole aziendali sono completamente diverse e sono specifiche per le applicazioni, quindi devi trovare il tuo "protocollo".

Immagina che si verifichi un'apocalisse e devi passare dal protocollo HTTP all'utilizzo dei piccioni. I piccioni non hanno alcun codice di ritorno, quindi è necessario cambiare il livello aziendale per adattarsi a questo. Ma la tua azienda non è davvero cambiata in alcun modo, quindi non dovresti aver bisogno di cambiare il livello aziendale. Mostra uno stretto accoppiamento tra questi due strati (trasporti e affari).

Torna alla domanda: ciò che dovresti fare è restituire "200 OK" con un corpo che descrive cosa è successo con la richiesta. La specifica dice chiaramente così:

link .

200 OK

The request has succeeded. The information returned with the response is dependent on the method used in the request, for example

POST an entity describing or containing the result of the action;

La tua richiesta HTTP è riuscita? Sì, il server Web sa cosa fare con quella richiesta (ad esempio, passa alla parte server dell'applicazione). Il server Web passa quindi questa richiesta alla parte server dell'applicazione, che accetta i dati POST, li elabora (li convalida nel tuo caso) e restituisce una risposta normale (nel corpo di una risposta HTTP) alla parte client dell'applicazione . Questa risposta dalla parte server dell'applicazione può essere "Ottima, i dati che mi hai inviato sono validi" o "Mi dispiace, i dati inviati 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 server della tua applicazione non ha nemmeno ricevuto la richiesta. O almeno questo è ciò che intende dire: -)

EDIT : mi sono appena reso conto che stai facendo una 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.

    
risposta data 07.03.2017 - 12:43
fonte
-3

Non siamo sicuri che tutti siano d'accordo, ma stiamo usando 409 - Conflict. Molti affermano che il 409 è più un conflitto con lo stato del sistema, ma accettiamo l'interpretazione che un conflitto di valori di dati al di fuori dell'intervallo accettato è riparabile 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. Tuttavia, se non si desidera implementare una serie di risposte, è sufficiente optare per un valore pari a 400.

    
risposta data 24.08.2016 - 22:47
fonte

Leggi altre domande sui tag