@@ -15,55 +15,91 @@ use mas_templates::ErrorContext;
1515
1616use crate :: sentry:: SentryEventID ;
1717
18- pub struct FancyError {
19- context : ErrorContext ,
18+ fn build_context ( mut err : & dyn std:: error:: Error ) -> ErrorContext {
19+ let description = err. to_string ( ) ;
20+ let mut details = Vec :: new ( ) ;
21+ while let Some ( source) = err. source ( ) {
22+ err = source;
23+ details. push ( err. to_string ( ) ) ;
24+ }
25+
26+ ErrorContext :: new ( )
27+ . with_description ( description)
28+ . with_details ( details. join ( "\n " ) )
2029}
2130
22- impl FancyError {
23- #[ must_use]
24- pub fn new ( context : ErrorContext ) -> Self {
25- Self { context }
31+ pub struct GenericError {
32+ error : Box < dyn std:: error:: Error + ' static > ,
33+ code : StatusCode ,
34+ }
35+
36+ impl IntoResponse for GenericError {
37+ fn into_response ( self ) -> Response {
38+ tracing:: warn!( message = & * self . error) ;
39+ let context = build_context ( & * self . error ) ;
40+ let context_text = format ! ( "{context}" ) ;
41+
42+ (
43+ self . code ,
44+ TypedHeader ( ContentType :: text ( ) ) ,
45+ Extension ( context) ,
46+ context_text,
47+ )
48+ . into_response ( )
2649 }
2750}
2851
29- impl std:: fmt:: Display for FancyError {
30- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
31- let code = self . context . code ( ) . unwrap_or ( "Internal error" ) ;
32- match ( self . context . description ( ) , self . context . details ( ) ) {
33- ( Some ( description) , Some ( details) ) => {
34- write ! ( f, "{code}: {description} ({details})" )
35- }
36- ( Some ( message) , None ) | ( None , Some ( message) ) => {
37- write ! ( f, "{code}: {message}" )
38- }
39- ( None , None ) => {
40- write ! ( f, "{code}" )
41- }
52+ impl GenericError {
53+ pub fn new ( code : StatusCode , err : impl std:: error:: Error + ' static ) -> Self {
54+ Self {
55+ error : Box :: new ( err) ,
56+ code,
4257 }
4358 }
4459}
4560
46- impl < E : std:: fmt:: Debug + std:: fmt:: Display > From < E > for FancyError {
47- fn from ( err : E ) -> Self {
48- let context = ErrorContext :: new ( )
49- . with_description ( format ! ( "{err}" ) )
50- . with_details ( format ! ( "{err:?}" ) ) ;
51- FancyError { context }
52- }
61+ pub struct InternalError {
62+ error : Box < dyn std:: error:: Error + ' static > ,
5363}
5464
55- impl IntoResponse for FancyError {
65+ impl IntoResponse for InternalError {
5666 fn into_response ( self ) -> Response {
57- tracing:: error!( message = %self . context) ;
58- let error = format ! ( "{}" , self . context) ;
67+ tracing:: error!( message = & * self . error) ;
5968 let event_id = SentryEventID :: for_last_event ( ) ;
69+ let context = build_context ( & * self . error ) ;
70+ let context_text = format ! ( "{context}" ) ;
71+
6072 (
6173 StatusCode :: INTERNAL_SERVER_ERROR ,
6274 TypedHeader ( ContentType :: text ( ) ) ,
6375 event_id,
64- Extension ( self . context ) ,
65- error ,
76+ Extension ( context) ,
77+ context_text ,
6678 )
6779 . into_response ( )
6880 }
6981}
82+
83+ impl < E : std:: error:: Error + ' static > From < E > for InternalError {
84+ fn from ( err : E ) -> Self {
85+ Self {
86+ error : Box :: new ( err) ,
87+ }
88+ }
89+ }
90+
91+ impl InternalError {
92+ /// Create a new error from a boxed error
93+ #[ must_use]
94+ pub fn new ( error : Box < dyn std:: error:: Error + ' static > ) -> Self {
95+ Self { error }
96+ }
97+
98+ /// Create a new error from an [`anyhow::Error`]
99+ #[ must_use]
100+ pub fn from_anyhow ( err : anyhow:: Error ) -> Self {
101+ Self {
102+ error : err. into_boxed_dyn_error ( ) ,
103+ }
104+ }
105+ }
0 commit comments