File tree Expand file tree Collapse file tree 3 files changed +36
-2
lines changed
tower-http/src/services/fs/serve_dir Expand file tree Collapse file tree 3 files changed +36
-2
lines changed Original file line number Diff line number Diff line change @@ -124,8 +124,19 @@ where
124
124
}
125
125
126
126
Err ( err) => {
127
- if let io:: ErrorKind :: NotFound | io:: ErrorKind :: PermissionDenied =
128
- err. kind ( )
127
+ #[ cfg( unix) ]
128
+ // 20 = libc::ENOTDIR => "not a directory
129
+ // when `io_error_more` landed, this can be changed
130
+ // to checking for `io::ErrorKind::NotADirectory`.
131
+ // https://github.com/rust-lang/rust/issues/86442
132
+ let error_is_not_a_directory = err. raw_os_error ( ) == Some ( 20 ) ;
133
+ #[ cfg( not( unix) ) ]
134
+ let error_is_not_a_directory = false ;
135
+
136
+ if matches ! (
137
+ err. kind( ) ,
138
+ io:: ErrorKind :: NotFound | io:: ErrorKind :: PermissionDenied
139
+ ) || error_is_not_a_directory
129
140
{
130
141
if let Some ( ( mut fallback, request) ) = fallback_and_request. take ( ) {
131
142
call_fallback ( & mut fallback, request)
Original file line number Diff line number Diff line change @@ -35,6 +35,8 @@ const DEFAULT_CAPACITY: usize = 65536;
35
35
/// - The file doesn't exist
36
36
/// - Any segment of the path contains `..`
37
37
/// - Any segment of the path contains a backslash
38
+ /// - On unix, any segment of the path referenced as directory is actually an
39
+ /// existing file (`/file.html/something`)
38
40
/// - We don't have necessary permissions to read the file
39
41
///
40
42
/// # Example
Original file line number Diff line number Diff line change @@ -289,6 +289,27 @@ async fn not_found() {
289
289
assert ! ( body. is_empty( ) ) ;
290
290
}
291
291
292
+ #[ cfg( unix) ]
293
+ #[ tokio:: test]
294
+ async fn not_found_when_not_a_directory ( ) {
295
+ let svc = ServeDir :: new ( "../test-files" ) ;
296
+
297
+ // `index.html` is a file, and we are trying to request
298
+ // it as a directory.
299
+ let req = Request :: builder ( )
300
+ . uri ( "/index.html/some_file" )
301
+ . body ( Body :: empty ( ) )
302
+ . unwrap ( ) ;
303
+ let res = svc. oneshot ( req) . await . unwrap ( ) ;
304
+
305
+ // This should lead to a 404
306
+ assert_eq ! ( res. status( ) , StatusCode :: NOT_FOUND ) ;
307
+ assert ! ( res. headers( ) . get( header:: CONTENT_TYPE ) . is_none( ) ) ;
308
+
309
+ let body = body_into_text ( res. into_body ( ) ) . await ;
310
+ assert ! ( body. is_empty( ) ) ;
311
+ }
312
+
292
313
#[ tokio:: test]
293
314
async fn not_found_precompressed ( ) {
294
315
let svc = ServeDir :: new ( "../test-files" ) . precompressed_gzip ( ) ;
You can’t perform that action at this time.
0 commit comments