Errore REST API restituire buone pratiche [chiuso]


623

Sto cercando una guida sulle buone pratiche quando si tratta di restituire errori da un'API REST. Sto lavorando a una nuova API in modo da poter prendere qualsiasi direzione in questo momento. Il mio tipo di contenuto è XML al momento, ma ho intenzione di supportare JSON in futuro.

Ora sto aggiungendo alcuni casi di errore, come ad esempio un client tenta di aggiungere una nuova risorsa ma ha superato la sua quota di archiviazione. Sto già gestendo alcuni casi di errore con codici di stato HTTP (401 per l'autenticazione, 403 per l'autorizzazione e 404 per URI di richieste non valide). Ho esaminato i codici di errore HTTP benedetti, ma nessuno dell'intervallo 400-417 sembra corretto segnalare errori specifici dell'applicazione. Quindi all'inizio sono stato tentato di restituire il mio errore dell'applicazione con 200 OK e un payload XML specifico (cioè. Pagaci di più e otterrai lo spazio di cui hai bisogno!) Ma mi sono fermato a pensarci e sembra insaponato (/ scrollata di spalle per l'orrore). Inoltre mi sembra di dividere le risposte agli errori in casi distinti, poiché alcuni sono guidati dal codice di stato http e altri dal contenuto.

Quindi quali sono le raccomandazioni del settore? Buone pratiche (spiegare perché!) E anche, da un client pov, che tipo di gestione degli errori nell'API REST semplifica la vita del codice client?


7
Giusto per chiarire: non sono molto interessato a quale particolare codice di stato HTTP restituire, ma se è una buona pratica REST combinare errori di payload con codici di stato HTTP o è meglio fare affidamento esclusivamente sul payload.
Remus Rusanu,

3
Il Manuale di progettazione dell'API REST tratta abbastanza bene questo argomento.
Remus Rusanu,

12
La domanda non richiede un parere, ma una guida / raccomandazioni e dovrebbe essere riaperta e utilizzata come riferimento. Qual è stato il punto di chiudere nel 2016 la domanda, che è stata creata nel 2009, ha più di 400 voti e nessuna delle risposte esistenti basate su opinioni
Michael Freidgeim,

4
La maggior parte non ha menzionato, ma l'uso dei codici di errore HTTP può portare a problemi riguardanti la causa principale di un problema. HTTP è il protocollo di trasporto e un 404 dovrebbe indicare che si è verificato un problema con il livello di trasporto URLon (ad es. Percorso errato). Se l'applicazione non riesce a trovare un set di dati in base al suo ID, si tratta di un errore a livello di applicazione (non un errore a livello di trasporto) e un 404, come suggerito da utenti di codice di stato http riposanti, potrebbe portare a una conclusione errata. Generalmente non mi piace il mixup di trasporto e livello applicativo nell'uso dei codici di stato.
SCI

Risposte:


220

Quindi all'inizio sono stato tentato di restituire il mio errore dell'applicazione con 200 OK e un payload XML specifico (cioè. Pagaci di più e otterrai lo spazio di cui hai bisogno!) Ma mi sono fermato a pensarci e sembra insaponato (/ scrollata di spalle per l'orrore).

Non restituirei un 200 a meno che non ci fosse davvero nulla di sbagliato nella richiesta. Da RFC2616 , 200 significa "la richiesta è riuscita".

Se la quota di archiviazione del client è stata superata (per qualsiasi motivo), restituirei un 403 (proibito):

Il server ha compreso la richiesta, ma si rifiuta di soddisfarla. L'autorizzazione non aiuterà 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 è stata soddisfatta, 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 (Not Found).

Questo dice al client che la richiesta era OK, ma che non è riuscita (qualcosa che un 200 non fa). Questo ti dà anche l'opportunità di spiegare il problema (e la sua soluzione) nel corpo della risposta.

Quali altre condizioni di errore specifiche avevi in ​​mente?


6
Dovrei includere il mio messaggio di errore dettagliato nel corpo, ad es. una coppia codice / stringa XML? In che modo i clienti si occupano meglio di questo? Ad esempio, so che i client basati su WebRequest di C # lancerebbero "Richiesta non valida" o "Proibito" e non forniranno il corpo della risposta.
Remus Rusanu,

18
Il corpo di un 403 "dovrebbe" contenere i dettagli dell'errore. Se un cliente è pronto a utilizzare le informazioni è un'altra storia. Ha più senso che questo formato sia lo stesso di tutti gli altri payload (ad es. XML, JSON).
Rich Apodaca,

1
... e se i dettagli non vengono restituiti nel 403, al suo posto è possibile utilizzare un 404 "(" non mi sembra l'opzione migliore per me).
Rich Apodaca,

6
L'opzione 404 è per l'evento in cui un 403 potrebbe rivelare dettagli sull'applicazione di cui non si desidera che gli utenti non autorizzati siano a conoscenza - se un utente non amministrativo colpisce un URL di solo amministratore, ad esempio, potresti non volerlo sapere che è un URL valido per amministratori, ecc. In questo caso, tuttavia, il 403 è del tutto appropriato.
Greg Campbell,

16
Penso che questa sia una risposta piuttosto inutile. Avrei pensato che l'aspetto più importante riguardasse se gli stati dovessero essere usati esclusivamente, o se le informazioni di errore dovessero essere restituite nel payload, o entrambi, ecc. E poi COME le informazioni dovrebbero essere aggiunte nel payload. Lo stato specifico utilizzato è quello di affinare solo un aspetto specifico della domanda.
Manachi,

584

Un'ottima risorsa per scegliere il codice di errore HTTP corretto per la tua API: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Un estratto dall'articolo:

Dove iniziare:

inserisci qui la descrizione dell'immagine

2XX / 3XX:

inserisci qui la descrizione dell'immagine

4XX:

inserisci qui la descrizione dell'immagine

5XX:

inserisci qui la descrizione dell'immagine


1
422 È specificamente un'estensione WebDAV. Penso che non dovrebbe essere qui.
Mario,

@Mario È idiomatico nelle API di Ruby on Rails restituire 422 in risposta alle condizioni qui specificate. Molto bene seguendo già questo approccio. Per cosa sostituiresti gli usi di 422?
Kelsey Hannan,

normale 400
Andbdrew

Grazie. Che cosa significa "Stai abbandonando la rabbia di Internet?"?
RoutesMaps.com il


87

La scelta principale è se vuoi trattare il codice di stato HTTP come parte dell'API REST o no.

Entrambi i modi funzionano bene. Concordo sul fatto che, in senso stretto, una delle idee di REST è che è necessario utilizzare il codice di stato HTTP come parte dell'API (restituire 200 o 201 per un'operazione riuscita e un 4xx o 5xx a seconda dei vari casi di errore). Tuttavia , non ci sono polizia REST. Puoi fare quello che vuoi. Ho visto API molto più eclatanti non REST essere chiamate "RESTful".

A questo punto (agosto 2015) ti consiglio di utilizzare il codice di stato HTTP come parte dell'API. Ora è molto più facile vedere il codice di ritorno quando si usano i framework di quanto non fosse in passato. In particolare, ora è più facile vedere il caso di ritorno non 200 e il corpo di risposte non 200 rispetto al passato.

Il codice di stato HTTP fa parte di api

  1. Dovrai scegliere attentamente i codici 4xx che si adattano alle tue condizioni di errore. Puoi includere un messaggio di riposo, xml o in chiaro come payload che include un sottocodice e un commento descrittivo.

  2. I client dovranno utilizzare un framework software che consenta loro di accedere al codice di stato a livello HTTP. Di solito fattibile, non sempre diretto.

  3. I client dovranno distinguere tra i codici di stato HTTP che indicano un errore di comunicazione e i propri codici di stato che indicano un problema a livello di applicazione.

Il codice di stato HTTP NON fa parte dell'API

  1. Il codice di stato HTTP sarà sempre 200 se l'app ha ricevuto la richiesta e quindi ha risposto (casi di successo e di errore)

  2. TUTTE le tue risposte dovrebbero includere informazioni "busta" o "intestazione". In genere qualcosa come:

    envelope_ver: 1.0
    status: # usa tutti i codici che ti piacciono. Prenota un codice per il successo.
    msg: "ok" # Una stringa umana che riflette il codice. Utile per il debug.
    data: ... # I dati della risposta, se presenti.
  3. Questo metodo può essere più semplice per i client poiché lo stato della risposta è sempre nello stesso posto (non sono necessari sottocodici), nessun limite sui codici, non è necessario recuperare il codice di stato a livello HTTP.

Ecco un post con un'idea simile: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Problemi principali:

  1. Assicurati di includere i numeri di versione in modo da poter successivamente modificare la semantica dell'API, se necessario.

  2. Documento...


8
Ty. L'opzione 2 sembra SAPONE nei vestiti a riposo ...
Remus Rusanu,

138
No, scavare in tunnel tutto attraverso un 200 non è affatto riposante. Impedisce agli intermediari di comprendere il risultato di un'operazione che ucciderà qualsiasi forma di memorizzazione nella cache, nasconde la semantica dell'operazione e impone la comprensione del contenuto del messaggio per elaborare un errore, violando il vincolo dei messaggi autonomi.
SerialSeb,

13
Restituire i dettagli dell'errore con un 200 potrebbe non essere RESTful, ma questa è comunque una risposta utile (se si ignora l'osservazione "Entrambi i modi sono riposanti") ... Il punto più grande potrebbe essere che un'API RESTful potrebbe non essere l'opzione migliore per l'OP.
MB.

3
Sembra esserci una comprensione generale che puoi fare quello che vuoi con il protocollo HTTP ed essere ancora "RESTy", è falso. Usa il protocollo per quello che è scritto, questa è una delle idee principali di REST. Quindi il codice di stato deve far parte del protocollo.
Ariel M.,

Il punto dei codici di stato è fornire un linguaggio comune di comprensione tra diversi linguaggi di programmazione, quadri e approcci. I significati del codice di stato sono vicini a quelli universali: il tuo corpo personalizzato - che aggiunge intrinsecamente più complessità tramite la sintassi personalizzata che i consumatori API devono imparare - non lo è.
Kelsey Hannan,

40

Ricorda che ci sono più codici di stato di quelli definiti nelle RFC HTTP / 1.1, il registro IANA è su http://www.iana.org/assignments/http-status-codes . Nel caso in cui hai menzionato il codice di stato 507 suona bene.


3
Hmm, mentre a prima vista "507 Insufficient Storage" sembra che potrebbe essere appropriato, sarei diffidente nell'usarlo poiché è inteso come un'estensione WebDAV (abbastanza specifica) e non un generale "hey sei fuori dallo spazio" eccezione. Suppongo comunque che potresti usarlo.
Max

1
No, non è affatto specifico di WebDAV. C'è un motivo per cui esiste un registro per i codici di stato HTTP.
Julian Reschke,

26
Non sono d'accordo con 507questo scopo. La mia interpretazione 507è che il server ha esaurito lo spazio, non che l'account ha esaurito lo spazio.
Patrick,

12
Sono d'accordo con Patrick. 5xxgli errori hanno a che fare con gli errori del server.
Sean,

10
418: "Sono una teiera", il che implica che lo spazio di archiviazione è troppo piccolo (come una teiera è piccola) piuttosto che grande e quindi è fuori spazio.
Steve Konves,

22

Come altri hanno sottolineato, avere un'entità di risposta in un codice di errore è perfettamente consentito.

Ricorda che gli errori 5xx sono sul lato server, ovvero il client non può modificare nulla nella sua richiesta per far passare la richiesta. Se la quota del client viene superata, questo non è sicuramente un errore del server, quindi 5xx dovrebbe essere evitato.


Non sarei d'accordo. La quota superata sarebbe un errore del server (5xx) perché: la richiesta del client è valida e avrebbe avuto esito positivo se sotto quota, il che esclude la serie 400.
mikek3332002,

4
Ma il server non ha fatto nulla di male.
Charlie Schliesser,

19

Esistono due tipi di errori. Errori dell'applicazione ed errori HTTP. Gli errori HTTP servono solo a far sapere al gestore AJAX che le cose sono andate bene e non dovrebbero essere usate per nient'altro.

5xx Errore del server

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx successo

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Tuttavia, come progettare gli errori dell'applicazione dipende davvero da te. Stack Overflow per esempio invia un oggetto con response, datae messagele proprietà. Credo che la risposta contenga trueo falseper indicare se l'operazione è andata a buon fine (di solito per le operazioni di scrittura). I dati contengono il payload (in genere per le operazioni di lettura) e il messaggio contiene eventuali metadati aggiuntivi o messaggi utili (come i messaggi di errore quando lo responsesono false).


2
400 è anche utile per indicare un problema nell'applicazione client.
dolmen,

19

So che è molto tardi per la festa, ma ora, nel 2013, abbiamo alcuni tipi di media per coprire la gestione degli errori in un modo distribuito (RESTful) comune. Vedere "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) e "Dettagli del problema per le API HTTP", application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).


2
Grazie per i collegamenti. draft-nottingham-http-problem è ora uno standard proposto: datatracker.ietf.org/doc/rfc7807
seanf

9

Concordato. La filosofia di base di REST è quella di utilizzare l'infrastruttura web. I codici di stato HTTP sono il framework di messaggistica che consente alle parti di comunicare tra loro senza aumentare il payload HTTP. Sono già stati stabiliti codici universali che trasmettono lo stato della risposta e, pertanto, per essere veramente RESTful, le applicazioni devono utilizzare questo framework per comunicare lo stato della risposta.

L'invio di una risposta di errore in una busta HTTP 200 è fuorviante e impone al client (consumatore API) di analizzare il messaggio, molto probabilmente in modo non standard o proprietario. Anche questo non è efficiente: costringerai i tuoi clienti ad analizzare il payload HTTP ogni volta per capire lo stato di risposta "reale". Ciò aumenta l'elaborazione, aumenta la latenza e crea un ambiente in cui il client può commettere errori.


3
Che tu abbia una risposta corretta o una risposta non riuscita, molto probabilmente analizzerai la risposta. Se si tratta di un errore, si desidera analizzarlo per ottenere il messaggio di errore. Le risposte agli errori sono generalmente piccole e veloci da analizzare. Non penso che dovremmo preoccuparci di cercare di ottimizzare per evitare l'analisi delle risposte agli errori. Getteresti via la risposta all'errore senza analizzarla? Non saggio secondo me.
AgilePro

3
Se ricevi 200 OK, puoi anche scegliere di non analizzarlo, a seconda delle regole aziendali. Il punto non è se lo analizziamo sempre o no. Il punto è l'intento: qual è l'intento di 200 OK? Stai danneggiando l'intento inviando messaggi di errore racchiusi in 200 OK.
Kingz,

1
"Qual è l'intento di 200 OK?" - indicando il successo del livello di trasporto. La richiesta è stata ricevuta e risposta correttamente, c'era solo un problema specifico dell'applicazione che non aveva nulla a che fare con HTTP. +++ Metti il ​​contrario: inviare 404 nel mondo REST significa che qualcosa non è stato trovato, forse l'URL è chiaramente sbagliato o la risorsa da elaborare o qualsiasi altra cosa non è stata trovata. Senza analizzare il messaggio, non puoi. IMHO REST è solo strati di fusione.
maaartinus

Conflazione è la norma. Ti fornisce una sintassi da affrontare adatta al tuo ragionamento e ti libera di concentrarti sul livello aziendale. Concordato sullo stato del trasporto in seguito viene comunicato - questo è quello che lo scopo era in primo luogo - REST non è stato inventato / proposto contemporaneamente con HTTP - è arrivato dopo e ha semplicemente deciso di utilizzare l'infrastruttura esistente per rappresentare gli STATI e i loro CAMBIAMENTI.
Kingz,


5

Attenersi alla semantica del protocollo. Utilizzare 2xx per risposte di successo e 4xx, 5xx per risposte di errore, siano esse eccezioni aziendali o altro. Se l'utilizzo di 2xx per qualsiasi risposta fosse stato il caso d'uso previsto nel protocollo, in primo luogo non avrebbero avuto altri codici di stato.


3

Non dimenticare anche gli errori 5xx per errori dell'applicazione.

In questo caso, che dire di 409 (conflitto)? Ciò presuppone che l'utente possa risolvere il problema eliminando le risorse memorizzate.

In caso contrario, potrebbe funzionare anche 507 (non del tutto standard). Non userei 200 se non usassi 200 per errori in generale.


-2

Se viene superata la quota client, si tratta di un errore del server, evitare 5xx in questa istanza.


3
Perché evitare gli errori della serie 5xx quando sono per errori del server?
mikek3332002,

7
'quota client superata' non è un imho di errore del server, è una restrizione client e dovrebbe essere inferiore a 4xx.
MyGGaN,
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.