use std::any::Any;
use axum::{
body::Body,
http::{header, StatusCode},
response::Response,
};
use tower_http::catch_panic::{CatchPanicLayer, ResponseForPanic};
use super::http_error::ErrorResponseData;
fn handle_panic(production: bool, err: Box<dyn Any + Send + 'static>) -> Response {
let body = if production {
ErrorResponseData::new(
"internal_server_error",
"Server error",
serde_json::Value::Null,
)
} else {
let details = if let Some(s) = err.downcast_ref::<String>() {
s.clone()
} else if let Some(s) = err.downcast_ref::<&str>() {
s.to_string()
} else {
"Unknown panic message".to_string()
};
ErrorResponseData::new("panic", details, serde_json::Value::Null)
};
let body = serde_json::to_string(&body).unwrap_or_default();
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(body))
.unwrap()
}
pub fn panic_handler(
production: bool,
) -> CatchPanicLayer<impl ResponseForPanic<ResponseBody = Body>> {
CatchPanicLayer::custom(move |err| handle_panic(production, err))
}