A server is a program that listens for requests and sends responses over a network. A web server makes this interaction available through browser-friendly paths, called routes. A small local server can turn a familiar word-guessing game into an interactive web project. section 24.0 section 24.1.1
A basic web server brings together a few practical pieces:
- A router records paths such as / and /game/:guess. section 24.1.1
- An HTTP GET request arrives when someone views a webpage. section 24.1.1
- A handler is an async function that produces the response. section 24.1.1
- The server binds to an address such as 127.0.0.1:8080, where localhost means your own computer and 8080 is the port. section 24.1.1
- An extractor such as Path<String> reads part of a requested path and passes it to the handler. section 24.1.1
A tiny Axum server
The root path can return “The server works!”, while /double/:number parses a path value and returns either “10 times 2 is 20!” or a helpful error for invalid input. Running cargo run starts the server locally; visiting an unknown path produces a 404 response. 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.
Inspect the complete Rust example to see routes, Path extraction, async handlers, binding, serving, and response handling together. section 24.1.1










