feat: added error handling and login POST route

This commit is contained in:
Jef Roosens 2025-02-23 12:45:40 +01:00
parent 67ad8c2b64
commit 2f8181491a
No known key found for this signature in database
GPG key ID: 21FD3D77D56BAF49
7 changed files with 245 additions and 13 deletions

86
src/server/error.rs Normal file
View file

@ -0,0 +1,86 @@
use std::fmt::{self, Write};
use axum::{http::StatusCode, response::IntoResponse};
use crate::db;
pub type AppResult<T> = Result<T, AppError>;
#[derive(Debug)]
pub enum AppError {
Db(db::DbError),
IO(std::io::Error),
Other(Box<dyn std::error::Error + 'static + Send + Sync>),
BadRequest,
Unauthorized,
NotFound,
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Db(_) => write!(f, "database error"),
Self::IO(_) => write!(f, "io error"),
Self::Other(_) => write!(f, "other error"),
Self::BadRequest => write!(f, "bad request"),
Self::Unauthorized => write!(f, "unauthorized"),
Self::NotFound => write!(f, "not found"),
}
}
}
impl std::error::Error for AppError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Db(err) => Some(err),
Self::IO(err) => Some(err),
Self::Other(err) => Some(err.as_ref()),
Self::NotFound | Self::Unauthorized | Self::BadRequest => None,
}
}
}
pub trait ErrorExt: std::error::Error {
/// Return the full chain of error messages
fn stack(&self) -> String {
let mut msg = format!("{}", self);
let mut err = self.source();
while let Some(src) = err {
write!(msg, " - {}", src).unwrap();
err = src.source();
}
msg
}
}
impl<E: std::error::Error> ErrorExt for E {}
impl From<db::DbError> for AppError {
fn from(value: db::DbError) -> Self {
Self::Db(value)
}
}
impl From<std::io::Error> for AppError {
fn from(value: std::io::Error) -> Self {
Self::IO(value)
}
}
impl IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
match self {
Self::NotFound => StatusCode::NOT_FOUND.into_response(),
Self::Unauthorized => StatusCode::UNAUTHORIZED.into_response(),
Self::BadRequest => StatusCode::BAD_REQUEST.into_response(),
_ => {
tracing::error!("{}", self.stack());
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
}
}
}