I codici di stato HTTP dovrebbero essere utilizzati per rappresentare errori di logica aziendale su un server?

10

Sono a un bivio con un progetto API per un client (JS in un browser) per parlare con un server. Usiamo HTTP 409 Conflict per rappresentare il fallimento di un'azione a causa di un blocco di sicurezza in vigore. Il blocco di satefy impedisce agli sviluppatori di apportare modifiche involontarie nei sistemi di produzione dei nostri clienti. Sono stato incaricato di gestire 409s un po 'più garbatamente sul client per indicare il motivo per cui una particolare chiamata API non è riuscita.

La mia soluzione era di avvolgere i gestori degli errori di tutte le nostre chiamate AJAX che visualizzeranno una notifica sul client quando qualcosa fallisce a causa di 409 - tutto va bene e funziona bene insieme ad altri errori 4XX e 5XX che usano lo stesso meccanismo .

È sorto un problema in cui uno dei nostri gestori di route risponde con 409 quando incontra un errore di business logic: il wrapper AJAX segnala che il blocco di sicurezza è attivo, mentre il gestore di errori esistente del client riporta cosa (pensa) il problema si basa sul corpo della risposta. Una soluzione semplice sarebbe quella di modificare la risposta del gestore o il codice di stato che utilizziamo per rappresentare il blocco di sicurezza.

Il che mi porta al mio bivio: i codici di stato HTTP dovrebbero essere utilizzati anche per rappresentare errori di logica aziendale? Questa domanda risolve lo stesso problema che sto affrontando ma non ha ottenuto molta trazione. Come suggerito nella risposta collegata, mi sto proponendo di utilizzare HTTP 200 OK con un corpo appropriato per rappresentare un errore all'interno della logica di business.

Qualcuno ha qualche opinione strong qui? Qualcuno è in grado di convincermi che questo è il modo sbagliato di rappresentare un fallimento?

    
posta Joe Shanahan 07.02.2017 - 14:57
fonte

4 risposte

9

Kasey copre il punto principale.

L'idea chiave in qualsiasi API web: stai adattando il tuo dominio in modo che assomigli ad un negozio di documenti. GET / PUT / POST / DELETE e così via sono tutti modi di interagire con il negozio di documenti.

Quindi un modo di pensare a quali codici utilizzare, è capire quale sia l'operazione analoga in un archivio di documenti e quale sarebbe l'aspetto di questo errore in quell'analogico.

2xx non è completamente adatto

The 2xx (Successful) class of status code indicates that the client's request was successfully received, understood, and accepted.

5xx non è adatto

The 5xx (Server Error) class of status code indicates that the server is aware that it has erred

In questo caso, il server non ha commesso un errore; è consapevole che in questo momento non si dovrebbe modificare quella risorsa in questo modo.

Errori logici di business (nel senso che l'invarianza di business non consente la modifica proposta in questo momento) sono probabilmente un 409

The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict.

Nota questo ultimo bit: il payload della risposta 409 dovrebbe essere la comunicazione di informazioni al consumatore su ciò che è andato storto, e idealmente include controlli ipermediali che portano il consumatore alle risorse che possono aiutare a risolvere il conflitto.

My solution was to wrap the failure handlers of any of our AJAX calls which will display a notification on the client when something fails due to 409 - this is all fine and works well alongside other 4XX and 5XX errors which use the same mechanism.

E vorrei sottolineare questo come il problema; la tua implementazione presso il cliente presupponeva che il codice di stato fosse sufficiente per definire il problema. Invece, il codice cliente dovrebbe esaminare il carico utile e agire in base alle informazioni disponibili.

Questo è, dopotutto, come un archivio di documenti lo farebbe

409  Conflict

your proposed change has been declined because ${REASON}.  
The following resolution protocols are available: ${LINKS[@]})

Lo stesso approccio con 400 Bad Request sarebbe anche accettabile; che si traduce approssimativamente in "C'è stato un problema con la tua richiesta.Non possiamo essere preoccupati di capire quale codice di stato è la soluzione migliore, quindi eccoci qui.Vedi il payload per i dettagli."

    
risposta data 08.02.2017 - 18:04
fonte
14

Nella mia esperienza, i codici di errore HTTP non sono sufficienti per rappresentare errori di business. Tuttavia, sono utili per rappresentare classi di errori.

Quindi, la mia raccomandazione sarebbe quella di utilizzare i codici di errore HTTP per le categorie di errori, ma scegliere un errore specifico per gli errori della logica di business (es. 409 Conflict ... 200 OK sarebbe fuorviante qui) e includere i dati nella risposta che indica il errore commerciale specifico. Assicurati che faccia parte del contenuto della risposta e non del testo di stato perché alcuni browser ignorano il testo di stato personalizzato. La lingua che mi piace usare ha i Tipi Unione che sono convenienti per rappresentare i messaggi. Ma potresti anche definire costanti di stringa per i casi di errore.

Esempi

// error with text response
409 Conflict "safety_lock_engaged"
409 Conflict "customer_not_eligible_for_selected_discount"
// warning with JSON response
202 Accepted { "backorderedProductIds": [ 37, 476 ] }
    
risposta data 07.02.2017 - 16:45
fonte
4

In generale, eviterei di utilizzare i codici di stato HTTP per rappresentare specifici errori di logica aziendale. Questo perché hanno già un significato semantico definito dallo standard mondiale. Altri sistemi, nuovi sviluppatori e così via saranno confusi dalla tua deviazione dello standard.

Ciò che ho trovato in ricerche recenti, simili, è che è generalmente accettato di usare 400 Bad Request in caso di errori di validazione e simili. In questo modo, utilizzi un codice di stato per tutti gli errori di logica aziendale.

Per inciso, 409 dovrebbe essere usato quando una risorsa è cambiata mentre la stavi modificando e provato a salvarla di nuovo.

    
risposta data 08.02.2017 - 10:40
fonte
0

Puoi utilizzare "Richiesta non valida" e includere l'id della regola aziendale violata, oltre ad alcuni dettagli sul corpo della risposta.

    
risposta data 08.02.2017 - 17:43
fonte

Leggi altre domande sui tag