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:: {
14+ get_index, get_preview_ad, get_preview_video, post_slot_preview,
15+ } ;
916
1017#[ derive( Debug ) ]
1118pub struct State {
@@ -17,6 +24,68 @@ pub struct Application {
1724 state : Arc < State > ,
1825}
1926
27+ pub struct Error {
28+ error : Box < dyn std:: error:: Error > ,
29+ status : StatusCode ,
30+ }
31+
32+ impl Error {
33+ pub fn new < E > ( error : E , status : StatusCode ) -> Self
34+ where
35+ E : Into < Box < dyn std:: error:: Error > > ,
36+ {
37+ Self {
38+ error : error. into ( ) ,
39+ status,
40+ }
41+ }
42+
43+ /// Create a new [`Error`] from [`anyhow::Error`] with a custom [`StatusCode`]
44+ /// instead of the default [`StatusCode::INTERNAL_SERVER_ERROR`].
45+ pub fn anyhow_status ( error : anyhow:: Error , status : StatusCode ) -> Self {
46+ Self {
47+ error : error. into ( ) ,
48+ status,
49+ }
50+ }
51+ }
52+
53+ impl IntoResponse for Error {
54+ fn into_response ( self ) -> axum:: response:: Response {
55+ let response_tuple = match self . status {
56+ StatusCode :: INTERNAL_SERVER_ERROR => {
57+ error ! ( { error = %self . error} , "Server error" ) ;
58+ ( StatusCode :: INTERNAL_SERVER_ERROR , self . error . to_string ( ) )
59+ }
60+ // we want to log any error that is with status > 500
61+ status_code if status_code. as_u16 ( ) > 500 => {
62+ error ! ( { error = %self . error} , "Server error" ) ;
63+ ( status_code, self . error . to_string ( ) )
64+ } ,
65+ // anything else is < 500, so it's safe to not log it due to e.g. bad user input
66+ status_code => {
67+ ( status_code, self . error . to_string ( ) )
68+ }
69+ } ;
70+
71+ response_tuple. into_response ( )
72+ }
73+ }
74+
75+ impl < E > From < E > for Error
76+ where
77+ E : Into < anyhow:: Error > ,
78+ {
79+ fn from ( err : E ) -> Self {
80+ let anyhow_err: anyhow:: Error = err. into ( ) ;
81+
82+ Self {
83+ error : anyhow_err. into ( ) ,
84+ status : StatusCode :: INTERNAL_SERVER_ERROR ,
85+ }
86+ }
87+ }
88+
2089impl Application {
2190 pub fn new ( ) -> Result < Self , Box < dyn std:: error:: Error > > {
2291 let serve_dir = match std:: env:: current_dir ( ) . unwrap ( ) {
@@ -42,11 +111,15 @@ impl Application {
42111 }
43112
44113 pub async fn run ( & self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
114+ let preview_routes = Router :: new ( )
115+ . route ( "/" , post ( post_slot_preview) )
116+ . route ( "/ad" , get ( get_preview_ad) )
117+ . route ( "/video" , get ( get_preview_video) ) ;
118+
45119 // build our application with a single route
46120 let app = Router :: new ( )
47121 . route ( "/" , get ( get_index) )
48- . route ( "/preview/ad" , get ( get_preview_ad) )
49- . route ( "/preview/video" , get ( get_preview_video) )
122+ . nest ( "/preview" , preview_routes)
50123 . layer ( Extension ( self . state . clone ( ) ) ) ;
51124
52125 let socket_addr: SocketAddr = ( [ 127 , 0 , 0 , 1 ] , 3030 ) . into ( ) ;
0 commit comments