58 lines
1.4 KiB
Rust
58 lines
1.4 KiB
Rust
|
|
use axum::{Router, extract::State, response::IntoResponse, routing::get};
|
||
|
|
use maud::html;
|
||
|
|
use tokio::net::TcpListener;
|
||
|
|
|
||
|
|
mod contact;
|
||
|
|
use contact::Contact;
|
||
|
|
|
||
|
|
#[derive(Clone)]
|
||
|
|
struct AppState {
|
||
|
|
contacts: Vec<Contact>,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[axum::debug_handler]
|
||
|
|
async fn contacts(
|
||
|
|
// access the state via the `State` extractor
|
||
|
|
// extracting a state of the wrong type results in a compile error
|
||
|
|
State(state): State<AppState>,
|
||
|
|
) -> impl IntoResponse {
|
||
|
|
html! {
|
||
|
|
ul {
|
||
|
|
@for contact in &state.contacts {
|
||
|
|
li { (&contact.name) }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::main]
|
||
|
|
async fn main() -> Result<(), anyhow::Error> {
|
||
|
|
let state = AppState {
|
||
|
|
contacts: vec![
|
||
|
|
Contact {
|
||
|
|
name: "Foo Bar".to_string(),
|
||
|
|
},
|
||
|
|
Contact {
|
||
|
|
name: "Baz Qux".to_string(),
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
|
||
|
|
let app = Router::new()
|
||
|
|
.route("/", get(|| async { "Hello, World!" }))
|
||
|
|
.route("/contacts", get(contacts))
|
||
|
|
.with_state(state);
|
||
|
|
|
||
|
|
let mut listenfd = listenfd::ListenFd::from_env();
|
||
|
|
let listener = match listenfd.take_tcp_listener(0)? {
|
||
|
|
Some(listener) => {
|
||
|
|
listener.set_nonblocking(true)?;
|
||
|
|
TcpListener::from_std(listener)
|
||
|
|
}
|
||
|
|
None => TcpListener::bind("0.0.0.0:3000").await,
|
||
|
|
}?;
|
||
|
|
axum::serve(listener, app).await.unwrap();
|
||
|
|
|
||
|
|
Ok(())
|
||
|
|
}
|