]> git.cworth.org Git - rust-learning/commitdiff
Add a single route at /race
authorCarl Worth <cworth@cworth.org>
Tue, 10 Mar 2026 06:11:05 +0000 (23:11 -0700)
committerCarl Worth <cworth@cworth.org>
Thu, 12 Mar 2026 04:14:58 +0000 (21:14 -0700)
That returns the complete race state, which, for now, is only the name
of the race.

New rust features seen for the first time as of this commit:

  * std::sync::Arc for atomically-reference-counted pointers (with
    thread-safe reference counting as you would expect from the name).

  * "crate::" in 'use' paths to reference the root of the current project

  * impl: For creating functions associated with a struct

  * Destructuring in a function parameter: State(state): State<Arc<AppState>>

  * clone() to carefully give the RaceResponse a string it
    owns. (Note: The rust compiler wouldn't even accept the code
    without this clone(): "cannot move out of an `Arc`)

src/handlers.rs [new file with mode: 0644]
src/main.rs
src/state.rs [new file with mode: 0644]

diff --git a/src/handlers.rs b/src/handlers.rs
new file mode 100644 (file)
index 0000000..3586d64
--- /dev/null
@@ -0,0 +1,17 @@
+use axum::Json;
+use axum::extract::State;
+use serde::Serialize;
+use std::sync::Arc;
+
+use crate::state::AppState;
+
+#[derive(Serialize)]
+pub struct RaceResponse {
+    pub name: String,
+}
+
+pub async fn get_race(State(state): State<Arc<AppState>>) -> Json<RaceResponse> {
+    Json(RaceResponse {
+        name: state.race_name.clone(),
+    })
+}
index baca8fea87c950cee7ba2387232eb6fc02d68ff8..ecb0dcda36e88a60fdcecf96275e69b9c967fead 100644 (file)
@@ -1,5 +1,9 @@
 mod config;
+mod handlers;
+mod state;
 
+use axum::Router;
+use axum::routing::get;
 use std::error::Error;
 
 #[tokio::main]
@@ -17,12 +21,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
 
     eprintln!("Race: {}", config.name);
 
+    let state = state::AppState::new(config);
+
+    // Public read routes
+    let read_routes = Router::new().route("/race", get(handlers::get_race));
+
     let bind = "0.0.0.0:3000";
     eprintln!("Listening on {}", bind);
 
     let listener = tokio::net::TcpListener::bind(&bind).await?;
 
-    let app = axum::Router::new();
+    let app = Router::new().merge(read_routes).with_state(state);
 
     axum::serve(listener, app)
         .with_graceful_shutdown(async move {
diff --git a/src/state.rs b/src/state.rs
new file mode 100644 (file)
index 0000000..0efa810
--- /dev/null
@@ -0,0 +1,15 @@
+use std::sync::Arc;
+
+use crate::config::ConfigFile;
+
+pub struct AppState {
+    pub race_name: String,
+}
+
+impl AppState {
+    pub fn new(config: ConfigFile) -> Arc<Self> {
+        Arc::new(Self {
+            race_name: config.name,
+        })
+    }
+}