-
Notifications
You must be signed in to change notification settings - Fork 85
/
axum.rs
70 lines (59 loc) · 2.02 KB
/
axum.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use axum::{
http::{header, StatusCode, Uri},
response::{Html, IntoResponse, Response},
routing::{get, Router},
};
use rust_embed::Embed;
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
// Define our app routes, including a fallback option for anything not matched.
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));
// Start listening on the given address.
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();
}
// We use static route matchers ("/" and "/index.html") to serve our home
// page.
async fn index_handler() -> impl IntoResponse {
static_handler("/index.html".parse::<Uri>().unwrap()).await
}
// We use a wildcard matcher ("/dist/*file") to match against everything
// within our defined assets directory. This is the directory on our Asset
// struct below, where folder = "examples/public/".
async fn static_handler(uri: Uri) -> impl IntoResponse {
let mut path = uri.path().trim_start_matches('/').to_string();
if path.starts_with("dist/") {
path = path.replace("dist/", "");
}
StaticFile(path)
}
// Finally, we use a fallback route for anything that didn't match.
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(),
}
}
}