400 vs 422 risposta al POST di dati


356

Sto cercando di capire quale sia il codice di stato corretto da restituire in diversi scenari con un'API "simile a REST" su cui sto lavorando. Diciamo che ho un punto finale che consente gli acquisti POST in formato JSON. Sembra così:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

Cosa devo restituire se il client mi invia "sales_tax" (anziché la "tassa" prevista). Attualmente, sto tornando un 400. Ma, ho iniziato a interrogarmi su questo. Dovrei davvero restituire un 422? Voglio dire, è JSON (che è supportato) ed è JSON valido, semplicemente non contiene tutti i campi richiesti.


Risposte:


419

400 Richiesta non valida ora sembra essere il miglior codice di stato HTTP / 1.1 per il tuo caso d'uso.

Al momento della tua domanda (e della mia risposta originale), RFC 7231 non era una cosa; a quel punto mi sono opposto 400 Bad Requestperché RFC 2616 diceva (con enfasi la mia):

La richiesta non è stata compresa dal server a causa di una sintassi non corretta .

e la richiesta che descrivi è JSON sintatticamente valida racchiusa in HTTP sintatticamente valido, e quindi il server non ha problemi con la sintassi della richiesta.

Tuttavia, come sottolineato da Lee Saferite nei commenti , RFC 7231, che viola RFC 2616, non include tale restrizione :

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).


Tuttavia, prima di quella riformulazione (o se si desidera cavillare sul fatto che RFC 7231 sia solo uno standard proposto in questo momento), 422 Unprocessable Entitynon sembra un codice di stato HTTP errato per il proprio caso d'uso, perché come dice l'introduzione a RFC 4918:

Mentre i codici di stato forniti da HTTP / 1.1 sono sufficienti per descrivere la maggior parte delle condizioni di errore riscontrate dai metodi WebDAV, ci sono alcuni errori che non rientrano perfettamente nelle categorie esistenti. Questa specifica definisce codici di stato extra sviluppati per i metodi WebDAV (Sezione 11)

E la descrizione di422 dice:

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.

(Nota il riferimento alla sintassi; sospetto che 7231 in parte oscilli anche 4918)

Questo suona esattamente come la tua situazione, ma nel caso in cui ci fossero dei dubbi, continua dicendo:

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.

(Sostituisci "XML" con "JSON" e penso che possiamo essere d'accordo sulla tua situazione)

Ora, alcuni obietteranno che RFC 4918 riguarda "Estensioni HTTP per Web Distributed Authoring and Versioning (WebDAV)" e che tu (presumibilmente) non stai facendo nulla che coinvolga WebDAV, quindi non dovresti usare cose da esso.

Data la scelta tra l'utilizzo di un codice di errore nello standard originale che non copre esplicitamente la situazione e uno di un'estensione che descriva esattamente la situazione, sceglierei quest'ultimo.

Inoltre, la Sezione 21.4 di RFC 4918 fa riferimento al registro dei codici di stato HTTP (Hypertext Transfer Protocol) IANA , dove è possibile trovare 422.

Propongo che sia assolutamente ragionevole per un client o un server HTTP utilizzare qualsiasi codice di stato da quel registro, purché lo faccia correttamente.


Ma a partire da HTTP / 1.1, RFC 7231 ha trazione, quindi basta usare 400 Bad Request!


5
La tua risposta (422) ha senso per me. Questo è anche ciò che Rails ( respond_with ) utilizza quando una risorsa non può essere elaborata a causa di errori di convalida.
Tyler Rick,

11
Nota l'uso di 422 in specifiche non WebDAV qui: tools.ietf.org/html/rfc5789#section-2.2
Andrey Shchekin

4
Proprio come un aggiornamento, RFC 7231 ha una descrizione diversa per il codice di risposta 400 che cambia la semantica.
Lee Saferite,

5
Mi scuso: ho aggiornato questa risposta per riflettere il cambiamento nelle RFC e ho perso un po 'di chiarezza; Proverò a refactoring. È quasi certamente sicuro usare 422, ma al giorno d'oggi dovresti usarne 400.
Kristian Glass

2
Penso ancora che le specifiche potrebbero essere molto più chiare. Gli esempi forniti sono chiari casi in cui il cliente fa qualcosa di sbagliato. Anche la situazione del PO rientra in quella categoria. Tuttavia, ci sono casi come "Capisco quello che stai chiedendo, ma mi rifiuto di farlo perché c'è qualche regola commerciale contro di esso" non è così chiara. Non è esattamente colpa del cliente, quindi un 403 potrebbe effettivamente essere applicato, per la stessa specifica: "Tuttavia, una richiesta potrebbe essere vietata per motivi non correlati alle credenziali". Preferirei avere codici separati per le cose relative alle autorizzazioni vs "non si può fare" però.
Thorarin,

38

400 Bad Request è il codice di stato HTTP corretto per il tuo caso d'uso. Il codice è definito da HTTP / 0.9-1.1 RFC.

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

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 L'entità non elaborabile è definita da RFC 4918 - WebDav. Si noti che c'è una leggera differenza rispetto a 400, vedere il testo citato di seguito.

Questa condizione di errore può verificarsi se un corpo di richiesta XML contiene istruzioni XML ben formate (cioè sintatticamente corrette), ma semanticamente errate.

Per mantenere un'interfaccia uniforme, utilizzare 422 solo in caso di risposte XML e supportare anche tutti i codici di stato definiti dall'estensione Webdav, non solo 422.

http://tools.ietf.org/html/rfc4918#page-78

Vedi anche il post di Mark Nottingham sui codici di stato:

è un errore tentare di mappare "profondamente" ogni parte dell'applicazione in codici di stato HTTP; nella maggior parte dei casi il livello di granularità che si desidera puntare è molto più grossolano. In caso di dubbio, è OK utilizzare i codici di stato generico 200 OK, 400 Richiesta errata e 500 Errore di servizio interno quando non si adatta meglio .

Come pensare ai codici di stato HTTP


4
Il codice 422 fa parte del registro IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml quindi qualsiasi IMHO non ha senso. In ogni caso, l'API REST di Facebook e Twitter reinventa i propri codici e non utilizza gli standard RFC / IANA. Quindi puoi farlo.
gavenkoa,

15
La Sezione 11 specifica che vengono aggiunti all'intera specifica e non solo all'interno della specifica WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Steve Tauber,

8
Solo perché il codice è descritto come parte delle specifiche WebDAV non significa che sia specifico per WebDAV! I codici di stato dovrebbero essere generici.
Tratta bene le tue mod il

33

Per riflettere lo stato dal 2015:

A livello comportamentale, entrambi i codici di risposta 400 e 422 saranno trattati allo stesso modo da clienti e intermediari, quindi in realtà non fa alcuna differenza concreta .

Tuttavia mi aspetto di vedere 400 attualmente utilizzati più ampiamente, e inoltre i chiarimenti forniti dalle specifiche HTTPbis lo rendono il più appropriato dei due codici di stato:

  • La specifica HTTPbis chiarisce l'intento di 400 di non essere esclusivamente per errori di sintassi. La frase più ampia "indica che il server non può o non elaborerà la richiesta a causa di qualcosa che viene percepito come un errore del client" viene ora utilizzata.
  • 422 È specificamente un'estensione WebDAV e non è referenziata in RFC 2616 o nella nuova specifica HTTPbis .

Per il contesto, HTTPbis è una revisione delle specifiche HTTP / 1.1 che tenta di chiarire le aree in cui erano poco chiare o incoerenti. Una volta raggiunto lo stato approvato, sostituirà RFC2616.


4
Allora il 403 Proibito potrebbe anche essere usato per questo contesto? Citazione: il codice di stato 403 (proibito) indica che il server ha compreso la richiesta ma si rifiuta di autorizzarla ... Se nella richiesta sono state fornite credenziali di autenticazione, il server le considera insufficienti per concedere l'accesso .... Tuttavia, una richiesta potrebbe essere vietato per motivi estranei alle credenziali. Quindi sembra che 403 possa essere utilizzato per rifiutare le richieste al di fuori dell'autenticazione.
garbagecollector,

1
@garbagecollector nota che "rifiutato per motivi al di fuori delle credenziali "! = "rifiutato per motivi al di fuori dell'autenticazione ". Esistono molti modi per autenticare qualcuno senza utilizzare le credenziali, in particolare.
Knetic,

@garbagecollector no, credenziali significa autenticazione ("chi sei"), che sarebbe 401 in caso di fallimento. L'autorizzazione ("cosa puoi fare") sarebbe 403 in caso di fallimento. Spiegazione completa qui: stackoverflow.com/a/6937030/137948 Né si applica alla situazione "campi mancanti" dell'OP perché l'errore sarebbe lo stesso indipendentemente dall'utente che l'ha tentato. Sono d'accordo 400 è la risposta giusta.
Will Sheppard,

27

Caso di studio: API GitHub

https://developer.github.com/v3/#client-errors

Forse copiare da API ben note è un'idea saggia:

Esistono tre possibili tipi di errori client nelle chiamate API che ricevono i corpi di richiesta:

L'invio di JSON non validi comporterà una risposta di 400 richieste errate.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

L'invio di un tipo errato di valori JSON comporterà una risposta di 400 richieste errate.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

L'invio di campi non validi comporterà una risposta di entità non elaborabile 422.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}

Penso che questa sia la risposta corretta e comprensibile.
LEMUEL ADANE,

1
Non posso votarlo di più. Vorrei che risposte più votate si riferissero a questo. Le specifiche (RFC, IANA) non sono riuscite a fornire chiare definizioni e distinzioni tra i due. Quindi la risposta si riduce alle migliori pratiche e GitHub ce ne dà una.
Alex Klaus,

15

Non esiste una risposta corretta, poiché dipende dalla definizione di "sintassi" per la tua richiesta. La cosa più importante è che tu:

  1. Utilizzare i codici di risposta in modo coerente
  2. Includi quante più informazioni aggiuntive nel corpo della risposta che puoi per aiutare gli sviluppatori che usano la tua API a capire cosa sta succedendo. =

Prima che tutti mi saltino addosso dicendo che qui non c'è una risposta giusta o sbagliata, lasciami spiegare un po 'come sono arrivato alla conclusione.

In questo esempio specifico, la domanda del PO riguarda una richiesta JSON che contiene una chiave diversa da quella prevista. Ora, il nome della chiave ricevuto è molto simile, dal punto di vista del linguaggio naturale, alla chiave attesa, ma è, rigorosamente, diverso, e quindi non (di solito) riconosciuto da una macchina come equivalente.

Come ho detto sopra, il fattore decisivo è cosa si intende per sintassi . Se la richiesta è stata inviata con un Tipo di contenuto di application/json, quindi sì, la richiesta è sintatticamente valida perché è sintassi JSON valida, ma non semanticamente valida, poiché non corrisponde a quanto previsto. (assumendo una definizione rigorosa di ciò che rende semanticamente valida la richiesta in questione).

Se, d'altra parte, la richiesta fosse inviata con un tipo di contenuto personalizzato più specifico come application/vnd.mycorp.mydatatype+jsonquello, forse, specifica esattamente quali campi sono previsti, allora direi che la richiesta potrebbe facilmente essere sintatticamente non valida, quindi la risposta 400.

Nel caso in questione, poiché la chiave era errata, non il valore , c'era un errore di sintassi se c'era una specifica per quali chiavi sono valide. Se non vi fosse alcuna specifica per chiavi valide o l'errore fosse con un valore , sarebbe un errore semantico .


Risposta molto sottovalutata - grazie per la spiegazione ben formulata.
Puiu,

Esattamente i miei pensieri sull'argomento! Vengo dallo sfondo SOAP XML e il concetto di schema è appena entrato nel mio sangue e i documenti JSON piuttosto non annunciano il loro schema. Per me è se il server "capisce" la richiesta o meno. Se il server non sa cosa sia "sales_tax", allora è semplicemente 400: "Non ho idea di cosa mi abbia inviato, ma sicuramente non di ciò che voglio".
Aleksander Stelmaczonek,

4

422 Spiegazione di entità non elaborata aggiornata: 6 marzo 2017

Che cos'è 422 entità non elaborabile?

Un codice di stato 422 si verifica quando una richiesta è ben formata, tuttavia, a causa di errori semantici, non è possibile elaborarla. Questo stato HTTP è stato introdotto in RFC 4918 ed è più specifico per le estensioni HTTP per Web Distributed Authoring and Versioning (WebDAV).

Esistono alcune controversie sul fatto che gli sviluppatori debbano o meno restituire ai client un errore 400 vs 422 (maggiori informazioni sulle differenze tra entrambi gli stati di seguito). Tuttavia, nella maggior parte dei casi, si concorda che lo stato 422 deve essere restituito solo se si supportano le funzionalità WebDAV.

Una definizione parola per parola del codice di stato 422 presa dalla sezione 11.2 in RFC 4918 può essere letta di seguito.

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.

La definizione continua dicendo:

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.

Codici di stato 400 vs 422

Gli errori di richiesta errata fanno uso del codice di stato 400 e devono essere restituiti al client se la sintassi della richiesta non è corretta, contiene un frame di messaggio di richiesta non valido o ha un routing di richiesta ingannevole. Questo codice di stato può sembrare abbastanza simile allo stato di entità non elaborabile 422, tuttavia, una piccola informazione che li distingue è il fatto che la sintassi di un'entità richiesta per un errore 422 è corretta mentre la sintassi di una richiesta che genera un 400 l'errore non è corretto

L'uso dello stato 422 dovrebbe essere riservato solo a casi d'uso molto particolari. Nella maggior parte degli altri casi in cui si è verificato un errore client a causa di una sintassi non corretta, è necessario utilizzare lo stato 400 Richiesta non valida.

https://www.keycdn.com/support/422-unprocessable-entity/


1

Il tuo caso: HTTP 400 è il codice di stato corretto per il tuo caso dal punto di vista REST poiché è sintatticamente errato da inviare sales_taxinvece di tax, sebbene sia un JSON valido. Questo è normalmente applicato dalla maggior parte dei framework lato server quando si associa JSON agli oggetti. Tuttavia, esistono alcune implementazioni REST che ignorano le novità keynell'oggetto JSON. In tal caso, una content-typespecifica personalizzata per accettare solo campi validi può essere applicata dal lato server.

Scenario ideale per 422:

In un mondo ideale, 422 è preferito e generalmente accettabile da inviare come risposta se il server comprende il tipo di contenuto dell'entità richiesta e la sintassi dell'entità richiesta è corretta ma non è stata in grado di elaborare i dati perché è semanticamente errata.

Situazioni da 400 a 422:

Ricordare, il codice di risposta 422 è un codice di stato HTTP (WebDAV) esteso. Ci sono ancora alcuni client / librerie front-end HTTP che non sono pronti a gestire 422. Per loro, è semplice come "HTTP 422 è sbagliato, perché non è HTTP" . Dal punto di vista del servizio, 400 non è del tutto specifico.

Nell'architettura aziendale, i servizi sono distribuiti principalmente su livelli di servizio come SOA, IDM, ecc. In genere servono più client che vanno da un client nativo molto vecchio a un client HTTP più recente. Se uno dei client non gestisce HTTP 422, le opzioni sono quelle che chiedono al client di aggiornare o modificare il codice di risposta in HTTP 400 per tutti. Nella mia esperienza, questo è molto raro in questi giorni, ma ancora una possibilità. Pertanto, è sempre necessario uno studio attento della tua architettura prima di decidere i codici di risposta HTTP.

Per gestire situazioni come queste, i livelli di servizio normalmente utilizzano versioningo impostano il configurationflag per i client di conformità HTTP rigorosi per inviare 400 e inviare 422 per il resto di essi. In questo modo forniscono supporto di compatibilità con le versioni precedenti per i consumatori esistenti ma allo stesso tempo offrono ai nuovi clienti la possibilità di consumare HTTP 422.


L'ultimo aggiornamento di RFC7321 dice:

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).

Ciò conferma che i server possono inviare HTTP 400 per richieste non valide. 400 non si riferisce più solo all'errore di sintassi , tuttavia 422 è ancora una risposta autentica a condizione che i client possano gestirla.


1

Innanzitutto questa è un'ottima domanda.

400 Richiesta non valida: quando una richiesta non contiene informazioni importanti

ad es. l'intestazione dell'autorizzazione o l'intestazione del tipo di contenuto. Che è assolutamente richiesto dal server per comprendere la richiesta. Questo può differire da server a server.

422 Entità non elaborabile: impossibile analizzare il corpo della richiesta.

Questo è meno grave di 400. La richiesta ha raggiunto il server. Il server ha riconosciuto che la richiesta ha la struttura di base corretta. Ma le informazioni nel corpo della richiesta non possono essere analizzate o comprese.

ad es. Content-Type: application/xmlquando il corpo della richiesta è JSON.

Ecco un articolo che elenca i codici di stato e il suo utilizzo nelle API REST. https://metamug.com/article/status-codes-for-rest-api.php


5
422 significa che la sintassi è valida, ma i contenuti non lo sono. L'invio di JSON dove è previsto XML significa che la sintassi è errata, quindi un 400 è la risposta corretta in questo caso.
Dirk,

1
Esattamente come Dirk ha detto 422 significa una richiesta sintatticamente valida (può essere analizzata e compresa) ma semanticamente non valida
Jacek Obarymski,

400: quando la richiesta non può essere elaborata a causa di sintassi non valida (ad es. Errore di analisi); 422: quando la richiesta non può essere elaborata a causa di dati non validi (ad es. Errore di convalida).
Kitanotori,

Il tuo esempio per 422 non è valido perché inviando json con un tipo di supporto application / xml, il corpo è automaticamente sintatticamente errato e la risposta dovrebbe essere 400.
manemarron

-15

Dovresti effettivamente restituire "200 OK" e nel corpo della risposta includi un messaggio su ciò che è accaduto con i dati pubblicati. Quindi spetta alla tua applicazione capire il messaggio.

Il fatto è che i codici di stato HTTP sono esattamente questo: codici di stato HTTP. E quelli hanno significato solo a livello di trasporto, non a livello di applicazione. Il livello dell'applicazione non dovrebbe mai nemmeno sapere che viene utilizzato HTTP. Se il livello di trasporto è passato da HTTP a Homing Pigeons, non dovrebbe influire in alcun modo sul livello dell'applicazione.

Lascia che ti faccia un esempio non virtuale. Diciamo che ti innamori di una ragazza e che ti ama indietro ma la sua famiglia si trasferisce in un paese completamente diverso. Ti dà il suo nuovo indirizzo di posta ordinaria. Naturalmente, decidi di inviarle una lettera d'amore. Quindi scrivi la tua lettera, la metti in una busta, scrivi il suo indirizzo sulla busta, metti un timbro su di essa e la invii. Consideriamo ora questi scenari

  1. Hai dimenticato di scrivere il nome di una via. Riceverai una lettera non aperta con un messaggio scritto su di esso che dice che l'indirizzo non è corretto. Hai rovinato la richiesta e l'ufficio postale ricevente non è in grado di gestirla. Questo è l'equivalente di ricevere "400 Bad Request".
  2. Quindi correggi l'indirizzo e rispedisci la lettera. Ma a causa di qualche sfortuna hai sbagliato a scrivere il nome della strada. Riceverai di nuovo la lettera con un messaggio che dice che l'indirizzo non esiste. Questo è l'equivalente di ricevere "404 Not Found".
  3. Risolvi nuovamente l'indirizzo e questa volta riesci a scrivere l'indirizzo correttamente. La tua ragazza riceve la lettera e ti riscrive. È l'equivalente di ricevere "200 OK". Tuttavia, questo non significa che ti piacerà quello che ha scritto nella sua lettera. Significa semplicemente che ha ricevuto il tuo messaggio e ha una risposta per te. Fino a quando non apri la busta e leggi la sua lettera non puoi sapere se le manchi caro o se vuole lasciarti.

In breve: la restituzione di "200 OK" non significa che l'app del server abbia buone notizie per te. Significa solo che ha alcune notizie.

PS: il codice di stato 422 ha un significato solo nel contesto di WebDAV. Se non stai lavorando con WebDAV, 422 ha esattamente lo stesso significato standard di qualsiasi altro codice non standard = che è nessuno.

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.