Manejo de Errores
Enfoques Comunes para el Manejo de Errores en Aplicaciones Rust
El manejo de errores en Rust difiere de lenguajes como Java; carece de construcciones como try...catch. El enfoque típico es definir un tipo de error global a nivel de la aplicación:
Aquí se utiliza la biblioteca thiserror, que facilita la definición de tipos de error personalizados y simplifica el código. Por brevedad, también se define un alias de tipo AppResult.
thiserror vs. anyhow
En el ecosistema de manejo de errores de Rust, dos bibliotecas de uso común son thiserror y anyhow:
-
thiserror: Adecuada para desarrolladores de bibliotecas para definir tipos de error claros. Utiliza macros derive para ayudar a implementar el trait
std::error::Errorpara tipos de error personalizados, permitiéndote definir representaciones de error. Al construir una biblioteca o proporcionar tipos de error claros a los usuarios,thiserrores la mejor opción. -
anyhow: Orientada a desarrolladores de aplicaciones, proporciona un tipo de error genérico
anyhow::Errorque puede encapsular cualquier error que implemente el traitstd::error::Error. Se centra más en la propagación de errores que en su definición, lo que la hace particularmente adecuada para código a nivel de aplicación. Puedes convertir rápidamente varios errores enanyhow::Error, reduciendo la necesidad de código repetitivo.
En algunos escenarios, podrías usar ambas bibliotecas: definir tipos de error con thiserror en bibliotecas y manejar y propagar estos errores con anyhow en aplicaciones.
Manejo de Errores en Handlers
En Salvo, los Handler a menudo encuentran varios errores, como errores de conexión a base de datos, errores de acceso a archivos, errores de conexión de red, etc. Para este tipo de errores, se puede aplicar el enfoque de manejo de errores mencionado anteriormente:
Aquí, home devuelve directamente un AppResult<()>. Pero, ¿cómo se debe mostrar este error? Necesitamos implementar el trait Writer para el tipo de error personalizado AppResult, donde podemos decidir cómo mostrar el error:
En Salvo, un Handler puede devolver un Result, siempre que tanto el tipo Ok como el tipo Err en el Result implementen el trait Writer.
Manejo de Errores con anyhow
Dado el uso generalizado de anyhow, Salvo proporciona soporte integrado para anyhow::Error. Cuando la característica anyhow está habilitada, anyhow::Error implementa el trait Writer y se asigna a InternalServerError:
Para usar la característica anyhow, habilita la característica anyhow de Salvo en Cargo.toml:
Esto permite que tus funciones handler devuelvan directamente anyhow::Result<T>:
Los errores a menudo contienen información sensible, que generalmente no debería ser visible para usuarios regulares por razones de seguridad y privacidad. Sin embargo, si eres un desarrollador o administrador del sitio, podrías preferir que los errores se expongan completamente, revelando la información de error más precisa.
Como se muestra, en el método write, podemos acceder a referencias de Request y Depot, lo que facilita la implementación del enfoque anterior:
Mostrar Páginas de Error
Las páginas de error integradas de Salvo cumplen con los requisitos en la mayoría de los casos, mostrando páginas Html, Json o Xml según el tipo de datos de la solicitud. Sin embargo, hay situaciones en las que aún se desean pantallas de error personalizadas.
Esto se puede lograr implementando un Catcher personalizado. Para instrucciones detalladas, consulta la sección Catcher.