Make `ServeDir` infallible
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<_>>::ErrortoInfallible - Convert any errors that happen to
StatusCode::INTERNAL_SERVER_ERRORand log the error - Add
ServeDir::try_callwhich 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.