sgd-praktikum/src/error.rs

65 lines
1.8 KiB
Rust

use std::convert::Infallible;
use axum::{response::IntoResponse, body::{Full, Bytes}, Json};
use hyper::StatusCode;
use serde::{Serializer, Serialize};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ApplicationError {
#[error("File read error: {0}")]
Read(#[from] std::io::Error),
#[error("Deserialize error: {0}")]
Deserialize(#[from] toml::de::Error),
#[error("Database connection error: {0}")]
Database(#[from] sibyl::Error),
#[error("Axum error: {0}")]
Axum(#[from] hyper::Error),
}
#[derive(Error, Debug)]
pub enum ServiceError {
#[error("SQL error: {0}")]
Database(#[from] sibyl::Error),
#[error("Response code: {0}")]
ErrorResponse(StatusCode, Option<String>),
}
fn serialize_status<S>(x: &StatusCode, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_u16(x.as_u16())
}
#[derive(Serialize)]
pub struct ErrorResponse {
#[serde(serialize_with = "serialize_status")]
pub status: StatusCode,
pub error: String,
}
impl IntoResponse for ServiceError {
type Body = Full<Bytes>;
type BodyError = Infallible;
fn into_response(self) -> axum::http::Response<Self::Body> {
let res = match self {
ServiceError::Database(err) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Some(err.to_string())),
ServiceError::ErrorResponse(code, reason) => ErrorResponse::new(code, reason),
};
let status = res.status;
(status, Json(res)).into_response()
}
}
impl ErrorResponse {
fn new(status: StatusCode, message: Option<String>) -> Self {
let reason = status.canonical_reason().unwrap_or_default();
Self {
status,
error: message.unwrap_or_else(|| reason.to_string()),
}
}
}