Codici di stato HTTP REST per convalida non riuscita o duplicato non valido


826

Sto creando un'applicazione con un'API basata su REST e sono arrivato al punto in cui sto specificando i codici di stato per ogni richiesta.

Quale codice di stato devo inviare per richieste che non hanno superato la convalida o in cui una richiesta sta tentando di aggiungere un duplicato nel mio database?

Ho cercato su http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html ma nessuno di loro sembra giusto.

Esiste una pratica comune quando si inviano codici di stato?



14
Apri httpstatus.es , fai clic destro >> Scheda Pin: P
Salman von Abbas

Risposte:


780

Per errore di convalida dell'input: 400 richiesta non valida + descrizione facoltativa. Questo è suggerito nel libro " RESTful Web Services ". Per doppio invio: 409 Conflitto


Aggiornamento giugno 2014

La specifica pertinente era RFC2616 , che forniva l'uso di 400 (Bad Request) piuttosto restrittivamente

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

Quindi si sarebbe potuto sostenere che non era appropriato per errori semantici. Ma non più; da giugno 2014 la pertinente norma RFC 7231 , che sostituisce la precedente RFC2616, prevede l'uso di 400 (Bad Request) in senso lato come

il server non può o non elabora la richiesta a causa di qualcosa che viene percepito come un errore client


3
Sì, il corpo della richiesta fa parte della sintassi.
Deamon,

62
Una cattiva richiesta è sicuramente la risposta più comune a questo tipo di problema. L'unica altra alternativa è 422 entità non elaborabile. In realtà proviene da WebDav ma è perfettamente valido per riutilizzare qualsiasi codice di stato che è stato registrato con IANA.
Darrel Miller,

19
Quindi, come si fa a distinguere tra dati non validi che il server non può nemmeno analizzare e un errore di convalida? Un client gestirà queste due risposte in modo completamente diverso. Per la convalida, probabilmente visualizzerebbero gli errori per l'utente. Per dati veramente "non validi", registrerebbero l'errore in modo che il bug nel metodo che genera la richiesta possa essere corretto.
Josh Noe,

18
Non sono d'accordo con la tua interpretazione di RFC7231, anche se afferma che something perceived to be a client errortutti gli esempi forniti in questo paragrafo sono violazioni del protocollo HTTP, non errori logici: sintassi, framing, routing. Pertanto, ritengo che le specifiche HTTP non consentano 400 per la convalida non riuscita a livello di applicazione.
Dima Tisnek,

2
perché non utilizzare un 422 - entità non elaborabile? Mi sembra più logico
java_geek il

278
  • Convalida non riuscita: 403 Proibito ("Il server ha compreso la richiesta, ma si rifiuta di soddisfarla"). Contrariamente all'opinione popolare, RFC2616 non dice "403 è inteso solo per l'autenticazione fallita", ma "403: so cosa vuoi, ma non lo farò". Tale condizione potrebbe essere dovuta o meno all'autenticazione.
  • Tentativo di aggiungere un duplicato: 409 Conflict ("Impossibile completare la richiesta a causa di un conflitto con lo stato corrente della risorsa.")

Dovresti assolutamente dare una spiegazione più dettagliata nelle intestazioni e / o nel corpo della risposta (ad es. Con un'intestazione personalizzata - X-Status-Reason: Validation failed).


17
@deamon: Questa non è la specifica, questa è Wikipedia, cioè l'opinione di qualcuno su "cosa significano i codici di stato HTTP"; nota che la pagina dice essenzialmente "questo è ciò che Apache significa con 403, questo è ciò che IIS significa con 403", e da nessuna parte fa riferimento alla RFC ufficiale. Sembra che tu stia ripetendo "403 significa qualunque cosa Apache dice". NON. L'attuale RFC (che è il documento rilevante, non l'implementazione di Apache, non l'implementazione di IIS, non l'implementazione di qualcun altro) è qui: w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvor ha lasciato l'edificio il

57
"10.4.4 403 Proibito Il server ha compreso la richiesta, ma si rifiuta di soddisfarla. L'autorizzazione non sarà di aiuto e la richiesta NON DOVREBBE essere ripetuta. Se il metodo di richiesta non era HEAD e il server desidera rendere pubblico il motivo per cui la richiesta non ha stato soddisfatto, DOVREBBE descrivere il motivo del rifiuto nell'entità. Se il server non desidera rendere disponibili queste informazioni al client, è possibile utilizzare invece il codice di stato 404 (Non trovato). " Non vedo alcuna enfasi lì ("DOVREBBE / NON DOVREBBE" sono parole chiave RFC 2119, non enfasi); questa è la tua idea di cosa significhi "proibito", non di RFC.
Piskvor ha lasciato l'edificio il

10
Mi piace questa risposta, ma vedo ancora un piccolo problema. Secondo le specifiche , quando viene restituito un 403 , "la richiesta NON DOVREBBE essere ripetuta". Tuttavia, la restituzione di un 409 "è consentita solo in situazioni in cui si prevede che l'utente possa essere in grado di risolvere il conflitto e inviare nuovamente la richiesta". Nel caso di un duplicato, penso che 403 sia quindi più appropriato, in quanto non è possibile veramente risolvere il conflitto (tranne eliminando l'istanza precedente della risorsa).
pablobm,

2
Per il messaggio di errore stesso, è necessario modificare la frase di motivazione, quindi inviare l'intestazione HTTP/1.0 403 Form validation errorsè il modo più semplice di procedere.
aleemb,

6
IMO, 422 "Entità non elaborabile" ha molto più senso. Il mio ragionamento è che non è che il server rifiuta di soddisfare la richiesta, è che il server non può soddisfare la richiesta.
tybro0103,

225

Raccomando il codice di stato 422, "Entità non elaborabile" .

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.


11
Ovviamente si tratta di un codice di stato HTTP, consultare iana.org/assignments/http-status-codes . Esistono più codici di stato di quelli definiti in RFC 2616.
Julian Reschke,

7
WebDAV è un'estensione HTTP . "Estensioni HTTP per Web Distributed Authoring and Versioning (WebDAV)" Quindi, il codice di stato 422 non è un codice di stato http, ma un codice di stato di una uscita di http.
Deamon,

16
Deamon, non ha senso. HTTP definisce come definire nuovi codici, ed è quello che sta facendo WebDAV. C'è un registro dei codici di stato per un motivo.
Julian Reschke,

14
FYI - Descrizione RFC di 422: 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 Il codice di stato (Richiesta errata) 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.
Steve Kallestad,

6
E i thread non "scadono". Devono essere mantenuti in vita o i migliori risultati di ricerca di Google iniziano a diventare imprecisi.
James Billingham,

81

200.300, 400, 500 sono tutti molto generici. Se vuoi generico, 400 è OK.

422 viene utilizzato da un numero crescente di API e viene persino utilizzato da Rails immediatamente.

Indipendentemente dal codice di stato che scegli per la tua API, qualcuno non sarà d'accordo. Ma preferisco 422 perché penso che "400 + stato del testo" sia troppo generico. Inoltre, non stai sfruttando un parser pronto per JSON; al contrario, un 422 con una risposta JSON è molto esplicito e possono essere trasmesse molte informazioni di errore.

A proposito della risposta JSON, tendo a standardizzare la risposta all'errore di Rails per questo caso, che è:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

Questo formato è perfetto per la convalida dei moduli, che considero il caso più complesso da supportare in termini di "ricchezza nella segnalazione degli errori". Se la tua struttura degli errori è questa, probabilmente gestirà tutte le tue esigenze di segnalazione degli errori.


2
Che dire degli errori derivanti dalle interazioni tra gli arg. Cioè, arg1è valido ed arg2è valido, ma la combinazione dei due, con i valori specifici inviati, non è valida.
Giona,

1
Non ci penserei troppo; scegline uno che sembra possedere la relazione.
sethcall

o anche solo errore su entrambi gli arg. Come utente, penso che vorrei vedere l'errore su ciascuno dei campi che sono in conflitto, credo.
coccole

Bello!. esplicito è meglio di implicito
bhathiya-perera,

46

200

Ugh ... (309, 400, 403, 409, 415, 422) ... molte risposte cercando di indovinare, discutere e standardizzare qual è il miglior codice di ritorno per una richiesta HTTP corretta ma una chiamata REST fallita .

È errato mescolare codici di stato HTTP e codici di stato REST.

Tuttavia, ho visto molte implementazioni mescolarle e molti sviluppatori potrebbero non essere d'accordo con me.

I codici di ritorno HTTP sono correlati a HTTP Requestse stesso. Una chiamata REST viene eseguita utilizzando una richiesta del protocollo di trasferimento Hypertext e funziona a un livello inferiore rispetto al metodo REST richiamato stesso. REST è un concetto / approccio e il suo output è un risultato aziendale / logico , mentre il codice risultato HTTP è un trasporto .

Ad esempio, restituendo "404 Non trovato" quando si chiama / users / è confuso, perché può significare:

  • URI errato (HTTP)
  • Nessun utente trovato (REST)

"403 Proibito / Accesso negato" può significare:

  • È richiesta un'autorizzazione speciale. I browser possono gestirlo chiedendo l'utente / password. (HTTP)
  • Autorizzazioni di accesso errate configurate sul server. (HTTP)
  • Devi essere autenticato (REST)

E l'elenco potrebbe continuare con "Errore del server 500" (un errore HTTP generato da Apache / Nginx o un errore di vincolo aziendale in REST) ​​o altri errori HTTP ecc ...

Dal codice, è difficile capire quale fosse la ragione dell'errore, un errore HTTP (trasporto) o un errore REST (logico).

Se la richiesta HTTP è stata eseguita correttamente, dovrebbe sempre restituire 200 codice, indipendentemente dal record trovato o meno. Perché la risorsa URI è stata trovata ed è stata gestita dal server HTTP. Sì, potrebbe restituire un set vuoto. È possibile ricevere una pagina Web vuota con 200 come risultato HTTP, giusto?

Invece di questo puoi restituire 200 codice HTTP con alcune opzioni:

  • Oggetto "errore" nel risultato JSON se qualcosa va storto
  • Matrice / oggetto JSON vuota se nessun record trovato
  • Un risultato bool / flag di successo in combinazione con le opzioni precedenti per una migliore gestione.

Inoltre, alcuni provider di servizi Internet potrebbero intercettare le tue richieste e restituirti un codice HTTP 404. Ciò non significa che i tuoi dati non vengano trovati, ma è qualcosa di sbagliato a livello di trasporto.

Da Wiki :

Nel luglio 2004, il fornitore di telecomunicazioni britannico BT Group ha implementato il sistema di blocco dei contenuti Cleanfeed, che restituisce un errore 404 a qualsiasi richiesta di contenuto identificata come potenzialmente illegale da Internet Watch Foundation. Altri ISP restituiscono un errore HTTP 403 "vietato" nelle stesse circostanze. La pratica di impiegare falsi errori 404 come mezzo per nascondere la censura è stata segnalata anche in Tailandia e Tunisia. In Tunisia, dove la censura era severa prima della rivoluzione del 2011, la gente divenne consapevole della natura dei falsi errori 404 e creò un personaggio immaginario chiamato "Ammar 404" che rappresenta "il censore invisibile".

Perché non rispondere semplicemente con qualcosa del genere?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

Google restituisce sempre 200 come codice di stato nell'API di geocodifica, anche se la richiesta fallisce logicamente: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

Facebook restituisce sempre 200 per le richieste HTTP riuscite, anche se la richiesta REST fallisce: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

È semplice, i codici di stato HTTP sono per richieste HTTP. L'API REST è tua, definisci i tuoi codici di stato.


3
In realtà, l'utilizzo dei codici di stato HTTP per REST è ancora più confuso lungo la strada: 1) vedi 4xx nella casella degli strumenti dello sviluppatore e non puoi dire semplicemente controllando se il server ha restituito un valore ragionevole o non è riuscito a elaborare la tua richiesta e quindi 2) tutti i gestori di errori / eccezioni / catch dovrebbero verificare quale server ha restituito una risposta (per lo più non lo sono poiché dovresti farlo ad ogni chiamata di servizio) e molte volte 3) ottieni lo stesso payload ( tipo) sia sul percorso di successo che su quello dell'errore che portano a codice complicato / duplicato ... Davvero molto confuso.
szczepanpp,

9
Questa risposta confonde la semantica originale del protocollo HTTP rispetto al modo in cui REST su HTTP come stile architettonico riutilizza HTTP per implementare le API dei servizi Web. Come stile architettonico, REST non è uno standard da seguire rigorosamente, è un approccio suggerito. L'uso di una risposta 200 per un errore di convalida non è giusto o sbagliato, tuttavia è confuso per i tuoi clienti rispondere che la richiesta è riuscita, ma in realtà non è riuscita a causa di un errore di convalida, un dettaglio importante che viene oscurato nel corpo della risposta, la semantica di cui il cliente deve analizzare per capire.
Kevin Hooke,

5
@Marcodor se la tua chiamata API fallisce ma tu restituisci 200 indicando il successo, come è una buona idea? non è chiaro e confonde per i consumatori della tua API.
Kevin Hooke,

3
Corretto per molte ragioni, non solo la separazione degli errori HTTP vs REST. La convalida REST richiede spesso più sfumature. Ad esempio, record accettato ma contrassegnato come duplicato o rifiutato per una violazione dell'indice univoca. Volete anche un modello di ritorno coerente. Il BadRequest()metodo .NET ha un proprio modello di restituzione che differirà dal tuo normale modello di restituzione. È un incubo da analizzare. @KevinHooke, restituire HTTP 200 per un errore di convalida REST è come dire "Ho ricevuto il tuo messaggio, la risposta è no, ed ecco perché". Restituendo HTTP 400 dice "Non so di cosa stai parlando."
Neil Laslett,

5
l'argomento "perché google lo fa, deve essere giusto" è pazzo per me..è ok per sfidare qualcosa che Google ha implementato i bambini. Restituire HTTP 200 per una chiamata di riposo non riuscita confonde il chiamante dell'API che dovrebbe essere 4xx e uno può includere un bel JSON / XML nel corpo ... consente di fermare insieme la follia.
Jeryl Cook,

43

Un duplicato nel database dovrebbe essere a 409 CONFLICT.

Consiglio di utilizzare 422 UNPROCESSABLE ENTITYper errori di convalida.

Fornisco una spiegazione più lunga dei codici 4xx qui .


6

Il codice di stato 304 non modificato fornirebbe anche una risposta accettabile a una richiesta duplicata. Ciò è simile all'elaborazione di un'intestazione If-None-Matchdell'utilizzo di un tag di entità.

A mio avviso, la risposta di @ Piskvor è la scelta più ovvia a ciò che percepisco è l'intento della domanda originale, ma ho un'alternativa che è anche rilevante.

Se si desidera trattare una richiesta duplicata come un avviso o una notifica anziché come un errore, un codice dello stato della risposta di 304Non modificato e l' Content-Locationintestazione che identifica la risorsa esistente sarebbero altrettanto validi. Quando l'intento è semplicemente quello di garantire l'esistenza di una risorsa, una richiesta duplicata non sarebbe un errore ma una conferma. La richiesta non è errata, ma è semplicemente ridondante e il client può fare riferimento alla risorsa esistente.

In altre parole, la richiesta è buona, ma poiché la risorsa esiste già, il server non deve eseguire ulteriori elaborazioni.


6
Ho capito che 304 è destinato alle operazioni GET per facilitare la memorizzazione nella cache.
Sinaestetico il


0

406 - Non accettabile

Ciò significa che questa risposta viene inviata quando il server Web, dopo aver eseguito la negoziazione del contenuto guidata dal server, non trova alcun contenuto conforme ai criteri forniti dall'agente utente.

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.