Skip to content

Commit

Permalink
ServeDir: convert io::ErrorKind::NotADirectory to not_found (#331)
Browse files Browse the repository at this point in the history
* ServeDir: convert io::ErrorKind::NotADirectory to not_found

* only check raw OS error on unix OS, add comment.

* mention "is a directory" handling in ServeDir in documentation
  • Loading branch information
syphar authored Feb 21, 2023
1 parent a6d0f7b commit 987f5c9
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
15 changes: 13 additions & 2 deletions tower-http/src/services/fs/serve_dir/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,19 @@ where
}

Err(err) => {
if let io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied =
err.kind()
#[cfg(unix)]
// 20 = libc::ENOTDIR => "not a directory
// when `io_error_more` landed, this can be changed
// to checking for `io::ErrorKind::NotADirectory`.
// https://github.com/rust-lang/rust/issues/86442
let error_is_not_a_directory = err.raw_os_error() == Some(20);
#[cfg(not(unix))]
let error_is_not_a_directory = false;

if matches!(
err.kind(),
io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied
) || error_is_not_a_directory
{
if let Some((mut fallback, request)) = fallback_and_request.take() {
call_fallback(&mut fallback, request)
Expand Down
2 changes: 2 additions & 0 deletions tower-http/src/services/fs/serve_dir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const DEFAULT_CAPACITY: usize = 65536;
/// - The file doesn't exist
/// - Any segment of the path contains `..`
/// - Any segment of the path contains a backslash
/// - On unix, any segment of the path referenced as directory is actually an
/// existing file (`/file.html/something`)
/// - We don't have necessary permissions to read the file
///
/// # Example
Expand Down
21 changes: 21 additions & 0 deletions tower-http/src/services/fs/serve_dir/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,27 @@ async fn not_found() {
assert!(body.is_empty());
}

#[cfg(unix)]
#[tokio::test]
async fn not_found_when_not_a_directory() {
let svc = ServeDir::new("../test-files");

// `index.html` is a file, and we are trying to request
// it as a directory.
let req = Request::builder()
.uri("/index.html/some_file")
.body(Body::empty())
.unwrap();
let res = svc.oneshot(req).await.unwrap();

// This should lead to a 404
assert_eq!(res.status(), StatusCode::NOT_FOUND);
assert!(res.headers().get(header::CONTENT_TYPE).is_none());

let body = body_into_text(res.into_body()).await;
assert!(body.is_empty());
}

#[tokio::test]
async fn not_found_precompressed() {
let svc = ServeDir::new("../test-files").precompressed_gzip();
Expand Down

0 comments on commit 987f5c9

Please sign in to comment.