Gestione degli Errori
Approcci Comuni alla Gestione degli Errori nelle Applicazioni Rust
La gestione degli errori in Rust differisce da linguaggi come Java; manca di costrutti come try...catch. L'approccio tipico consiste nel definire un tipo di errore globale a livello dell'applicazione:
Qui viene utilizzata la libreria thiserror, che facilita la definizione di tipi di errore personalizzati e semplifica il codice. Per brevità, viene anche definito un alias di tipo AppResult.
thiserror vs. anyhow
Nell'ecosistema della gestione degli errori in Rust, due librerie comunemente utilizzate sono thiserror e anyhow:
-
thiserror: Adatta agli sviluppatori di librerie per definire tipi di errore chiari. Utilizza macro derive per aiutare a implementare il tratto
std::error::Errorper tipi di errore personalizzati, consentendo allo stesso tempo di definire le rappresentazioni degli errori. Quando si costruisce una libreria o si forniscono tipi di errore chiari agli utenti,thiserrorè la scelta migliore. -
anyhow: Rivolta agli sviluppatori di applicazioni, fornisce un tipo di errore generico
anyhow::Errorche può incapsulare qualsiasi errore che implementi il trattostd::error::Error. Si concentra più sulla propagazione che sulla definizione degli errori, rendendola particolarmente adatta per il codice a livello applicativo. È possibile convertire rapidamente vari errori inanyhow::Error, riducendo la necessità di codice boilerplate.
In alcuni scenari, potresti utilizzare entrambe le librerie: definire i tipi di errore con thiserror nelle librerie e gestire e propagare questi errori con anyhow nelle applicazioni.
Gestione degli Errori negli Handler
In Salvo, gli Handler incontrano spesso vari errori, come errori di connessione al database, errori di accesso ai file, errori di connessione di rete, ecc. Per questo tipo di errori, è possibile applicare l'approccio di gestione degli errori sopra menzionato:
Qui, home restituisce direttamente un AppResult<()>. Ma come dovrebbe essere visualizzato questo errore? Dobbiamo implementare il tratto Writer per il tipo di errore personalizzato AppResult, dove possiamo decidere come visualizzare l'errore:
In Salvo, un Handler può restituire un Result, a condizione che sia il tipo Ok che il tipo Err all'interno del Result implementino il tratto Writer.
Gestione degli Errori con anyhow
Dato l'uso diffuso di anyhow, Salvo fornisce supporto integrato per anyhow::Error. Quando la feature anyhow è abilitata, anyhow::Error implementa il tratto Writer ed è mappato su InternalServerError:
Per utilizzare la feature anyhow, abilita la feature anyhow di Salvo in Cargo.toml:
Ciò consente alle tue funzioni handler di restituire direttamente anyhow::Result<T>:
Gli errori spesso contengono informazioni sensibili, che generalmente non dovrebbero essere visibili agli utenti normali per motivi di sicurezza e privacy. Tuttavia, se sei uno sviluppatore o un amministratore del sito, potresti preferire che gli errori siano completamente esposti, rivelando le informazioni di errore più accurate.
Come mostrato, nel metodo write, possiamo accedere ai riferimenti a Request e Depot, rendendo conveniente implementare l'approccio sopra descritto:
Visualizzazione delle Pagine di Errore
Le pagine di errore integrate in Salvo soddisfano i requisiti nella maggior parte dei casi, visualizzando pagine Html, Json o Xml in base al tipo di dati della richiesta. Tuttavia, ci sono situazioni in cui si desidera ancora una visualizzazione personalizzata della pagina di errore.
Ciò può essere ottenuto implementando un Catcher personalizzato. Per istruzioni dettagliate, fare riferimento alla sezione Catcher.