use axum::extract::Request;
use axum::handler::HandlerWithoutStateExt;
use axum::response::IntoResponse;
use http::StatusCode;
use std::convert::Infallible;
use std::path::Path;
use tower::Service;
use tower_http::services::ServeDir;
pub fn file_and_error_handler(
file_dir: &Path,
) -> impl Service<
Request,
Error = Infallible,
Future = impl Send + 'static,
Response = impl IntoResponse,
> + Clone
+ Send
+ 'static {
async fn handle_404() -> (StatusCode, &'static str) {
(StatusCode::NOT_FOUND, "File Not found")
}
let serve_dir = ServeDir::new(file_dir)
.not_found_service(handle_404.into_service());
tower::ServiceBuilder::new()
.layer_fn(|mut svc: ServeDir<_>| {
tower::service_fn(move |req: Request| {
let mut req = req;
let mut uri = req.uri().to_string();
if !uri
.split('/')
.last()
.map(|p| p.contains('.'))
.unwrap_or(false)
{
if uri.ends_with('/') {
uri.pop();
}
uri.push_str("/index.html");
*req.uri_mut() = uri.parse().unwrap();
}
svc.call(req)
})
})
.service(serve_dir)
}