11use axum:: {
22 body:: { Body , HttpBody } ,
3- error_handling:: HandleError ,
4- response:: IntoResponse ,
5- routing:: { get_service, Route } ,
63 Router ,
74} ;
8- use http:: { Request , StatusCode } ;
95use std:: {
106 any:: type_name,
11- convert:: Infallible ,
127 fmt,
13- future:: { ready, Ready } ,
14- io,
158 marker:: PhantomData ,
169 path:: { Path , PathBuf } ,
1710 sync:: Arc ,
1811} ;
1912use tower_http:: services:: { ServeDir , ServeFile } ;
20- use tower_service:: Service ;
2113
2214/// Router for single page applications.
2315///
@@ -50,10 +42,9 @@ use tower_service::Service;
5042/// - `GET /some/other/path` will serve `index.html` since there isn't another
5143/// route for it
5244/// - `GET /api/foo` will serve the `api_foo` handler function
53- pub struct SpaRouter < S = ( ) , B = Body , T = ( ) , F = fn ( io :: Error ) -> Ready < StatusCode > > {
45+ pub struct SpaRouter < S = ( ) , B = Body > {
5446 paths : Arc < Paths > ,
55- handle_error : F ,
56- _marker : PhantomData < fn ( ) -> ( S , B , T ) > ,
47+ _marker : PhantomData < fn ( ) -> ( S , B ) > ,
5748}
5849
5950#[ derive( Debug ) ]
@@ -63,7 +54,7 @@ struct Paths {
6354 index_file : PathBuf ,
6455}
6556
66- impl < S , B > SpaRouter < S , B , ( ) , fn ( io :: Error ) -> Ready < StatusCode > > {
57+ impl < S , B > SpaRouter < S , B > {
6758 /// Create a new `SpaRouter`.
6859 ///
6960 /// Assets will be served at `GET /{serve_assets_at}` from the directory at `assets_dir`.
@@ -80,13 +71,12 @@ impl<S, B> SpaRouter<S, B, (), fn(io::Error) -> Ready<StatusCode>> {
8071 assets_dir : path. to_owned ( ) ,
8172 index_file : path. join ( "index.html" ) ,
8273 } ) ,
83- handle_error : |_| ready ( StatusCode :: INTERNAL_SERVER_ERROR ) ,
8474 _marker : PhantomData ,
8575 }
8676 }
8777}
8878
89- impl < S , B , T , F > SpaRouter < S , B , T , F > {
79+ impl < S , B > SpaRouter < S , B > {
9080 /// Set the path to the index file.
9181 ///
9282 /// `path` must be relative to `assets_dir` passed to [`SpaRouter::new`].
@@ -114,72 +104,27 @@ impl<S, B, T, F> SpaRouter<S, B, T, F> {
114104 } ) ;
115105 self
116106 }
117-
118- /// Change the function used to handle unknown IO errors.
119- ///
120- /// `SpaRouter` automatically maps missing files and permission denied to
121- /// `404 Not Found`. The callback given here will be used for other IO errors.
122- ///
123- /// See [`axum::error_handling::HandleErrorLayer`] for more details.
124- ///
125- /// # Example
126- ///
127- /// ```
128- /// use std::io;
129- /// use axum_extra::routing::SpaRouter;
130- /// use axum::{Router, http::{Method, Uri}};
131- ///
132- /// let spa = SpaRouter::new("/assets", "dist").handle_error(handle_error);
133- ///
134- /// async fn handle_error(method: Method, uri: Uri, err: io::Error) -> String {
135- /// format!("{} {} failed with {}", method, uri, err)
136- /// }
137- ///
138- /// let app = Router::new().merge(spa);
139- /// # let _: Router = app;
140- /// ```
141- pub fn handle_error < T2 , F2 > ( self , f : F2 ) -> SpaRouter < S , B , T2 , F2 > {
142- SpaRouter {
143- paths : self . paths ,
144- handle_error : f,
145- _marker : PhantomData ,
146- }
147- }
148107}
149108
150- impl < S , B , F , T > From < SpaRouter < S , B , T , F > > for Router < S , B >
109+ impl < S , B > From < SpaRouter < S , B > > for Router < S , B >
151110where
152- F : Clone + Send + Sync + ' static ,
153- HandleError < Route < B , io:: Error > , F , T > : Service < Request < B > , Error = Infallible > ,
154- <HandleError < Route < B , io:: Error > , F , T > as Service < Request < B > > >:: Response : IntoResponse + Send ,
155- <HandleError < Route < B , io:: Error > , F , T > as Service < Request < B > > >:: Future : Send ,
156111 B : HttpBody + Send + ' static ,
157- T : ' static ,
158112 S : Clone + Send + Sync + ' static ,
159113{
160- fn from ( spa : SpaRouter < S , B , T , F > ) -> Router < S , B > {
161- let assets_service = get_service ( ServeDir :: new ( & spa. paths . assets_dir ) )
162- . handle_error ( spa. handle_error . clone ( ) ) ;
163-
114+ fn from ( spa : SpaRouter < S , B > ) -> Router < S , B > {
115+ let assets_service = ServeDir :: new ( & spa. paths . assets_dir ) ;
164116 Router :: new ( )
165117 . nest_service ( & spa. paths . assets_path , assets_service)
166- . fallback_service (
167- get_service ( ServeFile :: new ( & spa. paths . index_file ) ) . handle_error ( spa. handle_error ) ,
168- )
118+ . fallback_service ( ServeFile :: new ( & spa. paths . index_file ) )
169119 }
170120}
171121
172- impl < B , T , F > fmt:: Debug for SpaRouter < B , T , F > {
122+ impl < B , T > fmt:: Debug for SpaRouter < B , T > {
173123 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
174- let Self {
175- paths,
176- handle_error : _,
177- _marker,
178- } = self ;
124+ let Self { paths, _marker } = self ;
179125
180126 f. debug_struct ( "SpaRouter" )
181127 . field ( "paths" , & paths)
182- . field ( "handle_error" , & format_args ! ( "{}" , type_name:: <F >( ) ) )
183128 . field ( "request_body_type" , & format_args ! ( "{}" , type_name:: <B >( ) ) )
184129 . field (
185130 "extractor_input_type" ,
@@ -189,14 +134,10 @@ impl<B, T, F> fmt::Debug for SpaRouter<B, T, F> {
189134 }
190135}
191136
192- impl < B , T , F > Clone for SpaRouter < B , T , F >
193- where
194- F : Clone ,
195- {
137+ impl < B , T > Clone for SpaRouter < B , T > {
196138 fn clone ( & self ) -> Self {
197139 Self {
198140 paths : self . paths . clone ( ) ,
199- handle_error : self . handle_error ,
200141 _marker : self . _marker ,
201142 }
202143 }
@@ -206,10 +147,8 @@ where
206147mod tests {
207148 use super :: * ;
208149 use crate :: test_helpers:: * ;
209- use axum:: {
210- http:: { Method , Uri } ,
211- routing:: get,
212- } ;
150+ use axum:: routing:: get;
151+ use http:: StatusCode ;
213152
214153 #[ tokio:: test]
215154 async fn basic ( ) {
@@ -253,21 +192,6 @@ mod tests {
253192 assert_eq ! ( res. text( ) . await , "<strong>Hello, World!</strong>\n " ) ;
254193 }
255194
256- // this should just compile
257- #[ allow( dead_code) ]
258- fn setting_error_handler ( ) {
259- async fn handle_error ( method : Method , uri : Uri , err : io:: Error ) -> ( StatusCode , String ) {
260- (
261- StatusCode :: INTERNAL_SERVER_ERROR ,
262- format ! ( "{} {} failed. Error: {}" , method, uri, err) ,
263- )
264- }
265-
266- let spa = SpaRouter :: new ( "/assets" , "test_files" ) . handle_error ( handle_error) ;
267-
268- Router :: < ( ) , Body > :: new ( ) . merge ( spa) ;
269- }
270-
271195 #[ allow( dead_code) ]
272196 fn works_with_router_with_state ( ) {
273197 let _: Router = Router :: new ( )
0 commit comments