use axum::{
extract::Path,
http::{header, StatusCode},
response::{Html, IntoResponse, Response},
routing::{get, Router},
};
use rust_embed::Embed;
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(index_handler))
.route("/index.html", get(index_handler))
.route("/dist/{*file}", get(static_handler))
.fallback_service(get(not_found));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
println!("listening on {}", addr);
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app.into_make_service()).await.unwrap();
}
async fn index_handler() -> impl IntoResponse {
static_handler(Path("index.html".to_string())).await
}
async fn static_handler(Path(path): Path<String>) -> impl IntoResponse {
StaticFile(path)
}
async fn not_found() -> Html<&'static str> {
Html("<h1>404</h1><p>Not Found</p>")
}
#[derive(Embed)]
#[folder = "examples/public/"]
struct Asset;
pub struct StaticFile<T>(pub T);
impl<T> IntoResponse for StaticFile<T>
where
T: Into<String>,
{
fn into_response(self) -> Response {
let path = self.0.into();
match Asset::get(path.as_str()) {
Some(content) => {
let mime = mime_guess::from_path(path).first_or_octet_stream();
([(header::CONTENT_TYPE, mime.as_ref())], content.data).into_response()
}
None => (StatusCode::NOT_FOUND, "404 Not Found").into_response(),
}
}
}