@@ -18,8 +18,17 @@ const RUSTDOC_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/rustdoc.css"))
1818const RUSTDOC_2021_12_05_CSS : & str =
1919 include_str ! ( concat!( env!( "OUT_DIR" ) , "/rustdoc-2021-12-05.css" ) ) ;
2020
21+ /// handle io-errors while serving static files.
22+ ///
23+ /// Some errors can directly converted into a `404 NOT FOUND`,
24+ /// the rest will lead to a server error.
2125async fn handle_error ( err : io:: Error ) -> impl IntoResponse {
22- AxumNope :: InternalError ( err. into ( ) ) . into_response ( )
26+ match err. raw_os_error ( ) {
27+ // ENOTDIR -> "not a directory
28+ Some ( 20 ) => AxumNope :: ResourceNotFound ,
29+ // fallback: raise a server error
30+ _ => AxumNope :: InternalError ( err. into ( ) ) ,
31+ }
2332}
2433
2534fn build_static_css_response ( content : & ' static str ) -> impl IntoResponse {
@@ -133,6 +142,24 @@ mod tests {
133142 } ) ;
134143 }
135144
145+ #[ test]
146+ fn io_error_not_a_directory_leads_to_404 ( ) {
147+ wrapper ( |env| {
148+ let web = env. frontend ( ) ;
149+
150+ // just to be sure that `index.js` exists
151+ assert ! ( web. get( "/-/static/index.js" ) . send( ) ?. status( ) . is_success( ) ) ;
152+
153+ // `index.js` exists, but is not a directory,
154+ // so trying to fetch it via `ServeDir` will lead
155+ // to an IO-error.
156+ let resp = web. get ( "/-/static/index.js/something" ) . send ( ) ?;
157+ assert_eq ! ( resp. status( ) . as_u16( ) , StatusCode :: NOT_FOUND ) ;
158+
159+ Ok ( ( ) )
160+ } ) ;
161+ }
162+
136163 #[ test_case( "/-/static/index.js" , "copyTextHandler" ) ]
137164 #[ test_case( "/-/static/menu.js" , "closeMenu" ) ]
138165 #[ test_case( "/-/static/keyboard.js" , "handleKey" ) ]
0 commit comments