Axum is a Rust web framework for building small HTTP services. It provides routing, asynchronous request handlers, and request extractors. Its connection with Tokio makes it a practical choice for an asynchronous server. section 24.1 section 24.1.1
Start with axum::Router::new(), add paths with .route(), and pair each path with an HTTP method such as get. Bind the router to an address such as 127.0.0.1:8080, then call async .serve(). The server keeps running until it shuts down. section 24.1.1
use axum::{extract::Path, routing::get}; async fn double(Path(input): Path<String>) -> String { #1 match input.parse::<i32>() { #2 Ok(num) => format!("{} times 2 is {}!", num, num * 2), Err(e) => format!("Uh oh, weird input: {e}") } } #[tokio::main] async fn main() { let app = axum::Router::new() .route("/", get(|| async { "The server works!" })) #3 .route( #4 "/game/:guess", get(|Path(guess): Path<String>| async move { format!("The guess is {guess}") }), ) .route("/double/:number", get(double)); #5 axum::Server::bind(&"127.0.0.1:8080".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); } #1 The signature here may look a bit odd, but it is just deconstructing the input inside the function signature. Axum uses this syntax a lot, so we’ll copy it. #2 Nothing else in this function is particularly surprising: it tries to parse a string into an <kbd>i32</kbd> and doubles it if it can. #3 This first route just lets us know that the server works, and we handle the response inside an async closure. #4 For the second route, we will also use an async function. The colon in <kbd>:guess</kbd> means to pass in whatever is after <kbd>/game/</kbd> to the function under the variable name <kbd>guess</kbd>. This time, we need <kbd>async move</kbd> because we want the function to take ownership of <kbd>guess</kbd>. Then we will return the guess to the user. #5 For the third route, we will use the previous doubling function. Here, as well, we pass in the path as the variable <kbd>number</kbd>, but inside the function itself, it will have a different name.
A compact runnable example combines a root route, a path parameter, and a handler that parses a number before returning a response. section 24.1.1
The example demonstrates three useful pieces:
- A route at / returns “The server works!”. section 24.1.1
- Path<String> extracts text following a route parameter, such as MyGuess from /game/MyGuess. section 24.1.1
- A handler can parse extracted text and return either a calculated result or a readable error. section 24.1.1
A small guessing-game server
A web version of a word-guessing game replaces command-line interaction with browser requests. The demonstrated routes return a greeting, echo a guess, or double a numeric path parameter. Invalid input produces messages such as “invalid digit found in string” or “number too large to fit in target type.” section 24.1 section 24.1.1
After the basic server works, replace global state with .with_state(), use Arc<Mutex> when shared values must change, add per-user sessions, or deploy the application online. section 24.1.4

