tower-http icon indicating copy to clipboard operation
tower-http copied to clipboard

Make `ServeDir` infallible

Open davidpdrsn opened this issue 3 years ago • 0 comments

Motivation

Previously ServeDir's error type was io::Error. That means users using ServeDir with axum must use .handle_error() to convert any IO errors into responses:

Router::new().nest(
    "/assets",
    get_service(ServeDir::new(".")).handle_error(handle_error),
);

async fn handle_error(_err: io::Error) -> impl IntoResponse {
    (StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong...")
}

Since ServeDir already maps io::ErrorKind::NotFound and io::ErrorKind::PermissionDenied there isn't much you do for error besides returning StatusCode::INTERNAL_SERVER_ERROR.

That is tedious to do and so I think we should make ServeDir handle the error internally and change its error type to Infallible. That would make the axum integration really simple:

Router::new().nest("/", ServeDir::new("."));

Solution

  • Change <ServeDir as Service<_>>::Error to Infallible
  • Convert any errors that happen to StatusCode::INTERNAL_SERVER_ERROR and log the error
  • Add ServeDir::try_call which returns a future that maintains the error. That way users can still customize the error if they want.

The same was done for ServeFile as its just a wrapper around ServeDir.

Note that this is a breaking change. We shipped the last major 3 months ago so probably fine to do another one but we should consider if there are any other breaking changes we wanna make.

davidpdrsn avatar Jul 12 '22 10:07 davidpdrsn