Qual è la risposta del codice di stato HTTP appropriata per una richiesta generale non riuscita (non un errore)?


109

Sto creando un'API RESTful che elaborerà una serie di interazioni utente, incluso l'inserimento di ordini utilizzando carte di credito memorizzate.

Nel caso di un ordine andato a buon fine, restituisco un 200 OK e nel caso in cui la richiesta d'ordine non sia valida o non sia valida, restituisco un 400 Bad Request. Ma cosa devo restituire se c'è un problema durante l'effettiva elaborazione dell'ordine?

  1. Il cliente invia l'ordine al server per una risorsa utente. Se l'utente non esiste, viene restituito 404 Not Found.
  2. Il formato e le informazioni dell'ordine vengono convalidati. Se non è valido, viene restituito 400 Bad Request.
  3. L'ordine viene elaborato. Se l'ordine ha esito positivo, viene restituito un 201 Created per l'ordine. Se si verifica un errore imprevisto, viene restituito un errore del server 500.

L'ultimo passaggio è il problema: cosa devo restituire se l'ordine non viene completato per qualsiasi altro motivo? I possibili scenari potrebbero includere:

  • Il prodotto è esaurito
  • Limite massimo di ordini utente raggiunto
  • Errore di transazione con carta di credito (fondi insufficienti, ecc.)

Questo non sembra essere appropriato per un 400 o 500. Semmai potrei vederlo come 400 se non c'è un codice migliore - la richiesta non era valida secondo le regole aziendali. Semplicemente non sembra accurato.

Modifica: ho trovato anche questa discussione esistente sullo stesso argomento. Tutte le risposte sembrano indicare l'utilizzo di codici di stato per questo tipo di violazione, con alcune discussioni sull'uso dell'estensione 400, 409 o 422.


8
Mi piace "422 entità unprocessable" per gli errori di convalida. E lo useresti per gli esempi precedenti, includi un messaggio nella risposta con l'effettivo problema aziendale "Il prodotto è esaurito" ed eventualmente aggiungi i tuoi "codici" se il cliente ha bisogno di prendere decisioni diverse in base alla risposta in modo programmatico
house9

prima di passare alla 422, considera se supporti le funzionalità WebDAV
Mbithy Mbithy

Risposte:


90

Dovresti usare 400 per le regole aziendali. Non restituire 2xx se l'ordine non è stato accettato. HTTP è un protocollo applicativo, non dimenticarlo mai. Se restituisci 2xx, il cliente può presumere che l'ordine sia stato accettato, indipendentemente dalle informazioni inviate nel corpo.


Dal ricettario dei servizi Web RESTful :

Un errore comune commesso da alcuni servizi Web è restituire un codice di stato che rifletta il successo (codici di stato da 200 a 206 e da 300 a 307) ma includere un corpo del messaggio che descrive una condizione di errore. In questo modo si impedisce al software compatibile con HTTP di rilevare gli errori. Ad esempio, una cache la memorizzerà come risposta corretta e la servirà ai client successivi anche quando i client potrebbero essere in grado di effettuare una richiesta riuscita.

Lascio a te decidere tra 4xx e 5xx, ma dovresti usare un codice di stato di errore.


1
Hai esempi o riferimenti per questo approccio rispetto all'altro? Entrambe le risposte tue e di Widor hanno senso, una dal punto di vista di HTTP come protocollo applicativo e l'altra in quanto strettamente ai fini del trasferimento. La specifica lo definisce come un "protocollo a livello di applicazione", il che è un po 'vago. Ho anche visto prospettive ed esempi sul Web durante la ricerca di questo.
Raelshark

questo è così vero.
Young Hyun Yoo

2
Vuoi dire, "Dovresti usare 4xx per le regole aziendali"?
Yawar

28

È necessario utilizzare 4xx per un errore del client se il client può modificare la richiesta per aggirare l'errore. Usa un 5xx per un errore del server che il client non può davvero aggirare.

Il prodotto esaurito sarebbe un errore del server. Il client non può modificare la richiesta in alcun modo per aggirare l'errore. Potresti passare a un altro prodotto ma non sarebbe una nuova richiesta?

Anche il limite massimo di ordini dell'utente raggiunto è un errore del server. Niente che il cliente possa fare per aggirare quell'errore.

Il fallimento della transazione con carta di credito sarebbe un errore del cliente. Il cliente potrebbe inviare nuovamente la richiesta con un metodo di pagamento o un numero di carta di credito diversi per aggirare l'errore.


6
Se viene raggiunto il limite dell'ordine, il cliente non dovrebbe avvisare l'utente di questo e lasciargli modificare la richiesta in modo appropriato? Sembra un errore 4xx. Lo stesso vale per il prodotto esaurito. Gli errori 5xx sono destinati agli errori causati da un guasto del sistema in qualche modo, non per un'azione non consentita da una regola aziendale.
carlin.scott

7
Sono d'accordo con il commento sopra. Gli errori 5xx riguardano quando il server ha problemi. Errori 4xx per le regole aziendali.
Merc

21

Tipo di errore:

4×× Client Error

Codice di errore:

422 Unprocessable Entity

Il server comprende il tipo di contenuto dell'entità richiesta (quindi un codice di stato Tipo di supporto 415 non supportato è inappropriato) e la sintassi dell'entità richiesta è corretta (quindi un codice di stato 400 Bad Request non è appropriato) ma non è stato in grado di elaborare il contenuto Istruzioni.

Ad esempio, questa condizione di errore può verificarsi se il corpo di una richiesta XML contiene istruzioni XML ben formate (cioè sintatticamente corrette), ma semanticamente errate.

https://httpstatuses.com/422


16

So che questa domanda è vecchia, ma oggi mi è venuta in mente la stessa domanda. Se il mio utente esaurisce i crediti, quale codice di stato deve restituire la mia API REST?

Tendo a propendere per 402 Payment Required:

Secondo Wikipedia :

Riservato per uso futuro. L'intenzione originale era che questo codice potesse essere utilizzato come parte di qualche forma di denaro digitale o schema di micropagamento, ma ciò non è accaduto e questo codice di solito non viene utilizzato. L'API di Google Developers utilizza questo stato se un determinato sviluppatore ha superato il limite giornaliero di richieste.

E infatti lo fanno :

PAYMENT_REQUIRED (402)

  • È stato raggiunto un limite di budget giornaliero impostato dallo sviluppatore.
  • L'operazione richiesta richiede più risorse di quelle consentite dalla quota. Il pagamento è richiesto per completare l'operazione.
  • L'operazione richiesta richiede un qualche tipo di pagamento da parte dell'utente autenticato.

Questa è la risposta più pensata e logica.
GTodorov

5

Che ne dici 424 Failed Dependency? La specifica lo descrive come:

Non è stato possibile eseguire il metodo sulla risorsa perché l'azione richiesta dipendeva da un'altra azione e tale azione non è riuscita.

Ma c'è anche questa definizione :

Il codice di stato 424 è definito nello standard WebDAV ed è per un caso in cui il client deve cambiare ciò che sta facendo - il server non sta riscontrando alcun problema qui.

Puoi dire al cliente (o fingere) che hai azioni interne che dovrebbero creare l'ordine e detrarre il saldo, e che una di quelle azioni non è riuscita, anche se per ragioni perfettamente valide, ed è per questo che la richiesta non è riuscita.

Per quanto posso vedere, "azione" è un termine piuttosto ampio e può essere utilizzato in una varietà di situazioni, tra cui scorte insufficienti, credito insufficiente o notte di festa in magazzino.


Un'altra opzione potrebbe essere 422 Unprocessable Entity:

Il server comprende il tipo di contenuto dell'entità richiesta (quindi un codice di stato Tipo di supporto 415 non supportato è inappropriato) e la sintassi dell'entità richiesta è corretta (quindi un codice di stato 400 Bad Request non è appropriato) ma non è stato in grado di elaborare il contenuto Istruzioni.

Ad esempio, questa condizione di errore può verificarsi se il corpo di una richiesta XML contiene istruzioni XML ben formate (cioè sintatticamente corrette), ma semanticamente errate.

Cercare di richiedere un articolo che è esaurito, o quando hai un credito insufficiente, potrebbe essere considerato un errore a livello semantico.

MozDev dice che questo indica un errore dal lato client, in particolare: il client non deve ripetere questa richiesta senza modifiche.

Loopback 4 utilizza 422 quando la convalida dell'input non riesce.


Probabilmente, una scorta insufficiente o una notte di festa in magazzino potrebbero essere considerate stati temporanei, quindi la richiesta potrebbe essere ritentata in seguito. Questa situazione può essere indicata da503 Service Unavailable

Il server non è attualmente in grado di gestire la richiesta a causa di un sovraccarico temporaneo o di una manutenzione programmata, che probabilmente verrà alleviata dopo un certo ritardo.

Il server PU inviare un campo di intestazione Retry-After per suggerire un periodo di tempo appropriato per il client prima di ritentare la richiesta.


Nessuno di questi si riferisce a un pagamento. Vado con 402 dalla risposta precedente!
GTodorov

2

Non credo che 400 possa essere utilizzato per tutti gli scenari aziendali. Può essere utilizzato per la convalida dell'input dei dati di base. Oltre a ciò, potrebbe essere difficile adattare il tempo ad altra logica aziendale in questo codice di errore. Gli errori gestiti da questo sono per lo più errori in fase di progettazione che lo sviluppatore incontrerà probabilmente durante la codifica del client.

Diciamo che tutti i parametri sono corretti e diciamo che stiamo passando il numero dell'account utente nella richiesta.

Quindi la richiesta ora non è più una cattiva richiesta, il server è in grado di accettare la richiesta. Ma ora si rifiuta di soddisfare la richiesta sulla base delle nuove informazioni disponibili, ovvero - il conto non ha un saldo sufficiente.

Suggerirei di utilizzare 403 con un messaggio di errore appropriato in questi scenari.

Un altro possibile codice di errore potrebbe essere un conflitto 409. Ma viene utilizzato negli scenari in cui la risorsa si trova in uno stato coerente.


-1

Vado con 406 Not Acceptable.

Ecco un elenco 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585

8
Sebbene il nome del codice di stato 406 possa sembrare accurato di per sé, è necessario essere consapevoli del fatto che ogni codice di stato ha una descrizione testuale autorevole. La descrizione del codice di stato 406 non è adatta al caso in questione. Vedi httpstatuses.com/406 , per esempio.
Zero3

1
@ Zero3 ha ragione, questo codice significa che il tipo di risposta non è accettabile, poiché c'è una mancata corrispondenza tra le intestazioni di accettazione inviate dal client e i MediaType inviati dall'endpoint, ad esempio application / json vs. text / plain
Gregor
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.