11use std:: { net:: SocketAddr , sync:: Arc } ;
22
3- use axum:: { routing:: get, Extension , Router , Server } ;
4- use log:: info;
3+ use axum:: {
4+ http:: StatusCode ,
5+ response:: IntoResponse ,
6+ routing:: { get, post} ,
7+ Extension , Router , Server ,
8+ } ;
9+ use tracing:: { error, info} ;
510
611use tera:: Tera ;
712
8- use crate :: routes:: { get_index, get_preview_ad, get_preview_video} ;
13+ use crate :: routes:: { get_index, get_preview_ad, get_preview_video, post_slot_preview } ;
914
1015#[ derive( Debug ) ]
1116pub struct State {
@@ -17,6 +22,66 @@ pub struct Application {
1722 state : Arc < State > ,
1823}
1924
25+ pub struct Error {
26+ error : Box < dyn std:: error:: Error > ,
27+ status : StatusCode ,
28+ }
29+
30+ impl Error {
31+ pub fn new < E > ( error : E , status : StatusCode ) -> Self
32+ where
33+ E : Into < Box < dyn std:: error:: Error > > ,
34+ {
35+ Self {
36+ error : error. into ( ) ,
37+ status,
38+ }
39+ }
40+
41+ /// Create a new [`Error`] from [`anyhow::Error`] with a custom [`StatusCode`]
42+ /// instead of the default [`StatusCode::INTERNAL_SERVER_ERROR`].
43+ pub fn anyhow_status ( error : anyhow:: Error , status : StatusCode ) -> Self {
44+ Self {
45+ error : error. into ( ) ,
46+ status,
47+ }
48+ }
49+ }
50+
51+ impl IntoResponse for Error {
52+ fn into_response ( self ) -> axum:: response:: Response {
53+ let response_tuple = match self . status {
54+ StatusCode :: INTERNAL_SERVER_ERROR => {
55+ error ! ( { error = %self . error} , "Server error" ) ;
56+ ( StatusCode :: INTERNAL_SERVER_ERROR , self . error . to_string ( ) )
57+ }
58+ // we want to log any error that is with status > 500
59+ status_code if status_code. as_u16 ( ) > 500 => {
60+ error ! ( { error = %self . error} , "Server error" ) ;
61+ ( status_code, self . error . to_string ( ) )
62+ }
63+ // anything else is < 500, so it's safe to not log it due to e.g. bad user input
64+ status_code => ( status_code, self . error . to_string ( ) ) ,
65+ } ;
66+
67+ response_tuple. into_response ( )
68+ }
69+ }
70+
71+ impl < E > From < E > for Error
72+ where
73+ E : Into < anyhow:: Error > ,
74+ {
75+ fn from ( err : E ) -> Self {
76+ let anyhow_err: anyhow:: Error = err. into ( ) ;
77+
78+ Self {
79+ error : anyhow_err. into ( ) ,
80+ status : StatusCode :: INTERNAL_SERVER_ERROR ,
81+ }
82+ }
83+ }
84+
2085impl Application {
2186 pub fn new ( ) -> Result < Self , Box < dyn std:: error:: Error > > {
2287 let serve_dir = match std:: env:: current_dir ( ) . unwrap ( ) {
@@ -42,11 +107,15 @@ impl Application {
42107 }
43108
44109 pub async fn run ( & self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
110+ let preview_routes = Router :: new ( )
111+ . route ( "/" , post ( post_slot_preview) )
112+ . route ( "/ad" , get ( get_preview_ad) )
113+ . route ( "/video" , get ( get_preview_video) ) ;
114+
45115 // build our application with a single route
46116 let app = Router :: new ( )
47117 . route ( "/" , get ( get_index) )
48- . route ( "/preview/ad" , get ( get_preview_ad) )
49- . route ( "/preview/video" , get ( get_preview_video) )
118+ . nest ( "/preview" , preview_routes)
50119 . layer ( Extension ( self . state . clone ( ) ) ) ;
51120
52121 let socket_addr: SocketAddr = ( [ 127 , 0 , 0 , 1 ] , 3030 ) . into ( ) ;
0 commit comments