miden_node_utils/
panic.rs

1use std::any::Any;
2
3use http::{Response, StatusCode, header};
4use http_body_util::Full;
5pub use tower_http::catch_panic::CatchPanicLayer;
6
7/// Custom callback that is used by Tower to fulfill the
8/// [`tower_http::catch_panic::ResponseForPanic`] trait.
9///
10/// This should be added to tonic server builder as a layer via [`CatchPanicLayer::custom()`].
11pub fn catch_panic_layer_fn(err: Box<dyn Any + Send + 'static>) -> Response<Full<bytes::Bytes>> {
12    // Log the panic error details.
13    let err = stringify_panic_error(err);
14    tracing::error!(panic = true, "{err}");
15
16    // Return generic error response.
17    Response::builder()
18        .status(StatusCode::INTERNAL_SERVER_ERROR)
19        .header(header::CONTENT_TYPE, "application/grpc")
20        .body(Full::from(""))
21        .unwrap()
22}
23
24/// Converts a dynamic panic-related error into a string.
25fn stringify_panic_error(err: Box<dyn Any + Send + 'static>) -> String {
26    if let Some(&msg) = err.downcast_ref::<&str>() {
27        msg.to_string()
28    } else if let Ok(msg) = err.downcast::<String>() {
29        *msg
30    } else {
31        "unknown".to_string()
32    }
33}