Routing & Handler Signatures
1. Welcome and Icebreaker:
What’s your favorite HTTP method (GET, POST, PUT, DELETE, etc.) and why?
2. Outline the Session:
Agenda:
- Concept Explanation: Routing in Axum and handler function signatures.
- Live Coding: Add multiple routes and experiment with handler return types.
- Tasks: Practice by creating your own routes and handlers.
Learning Outcomes:
- Understand how to define routes for different HTTP methods.
- Learn about handler function signatures and return types in Axum.
Expectations: Feel free to experiment and ask questions!
3. Concept Explanation:
Routing is how Axum directs incoming HTTP requests to the correct handler function. Each route is associated with an HTTP method (GET, POST, etc.) and a path. Handlers are async functions that process requests and return responses. Axum supports various return types, such as String, &'static str, or any type that implements IntoResponse.
You can also nest routers for better organization, and use async functions for all handlers.
4. Live Coding Demonstration:
Let’s add more routes, see different handler signatures, and demonstrate nesting routers.
use axum::{Router, routing::{get, post, put}};
async fn hello() -> &'static str {
"Hello, Axum!"
}
async fn create() -> String {
"Created!".to_string()
}
async fn update() -> &'static str {
"Updated!"
}
async fn ping() -> &'static str {
"pong"
}
#[tokio::main]
async fn main() {
// Create a nested API router
let api_router = Router::new()
.route("/ping", get(ping));
let app = Router::new()
.route("/", get(hello))
.route("/create", post(create))
.route("/update", put(update))
.nest("/api", api_router);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Step-by-step explanation:
- We define handlers for different routes and HTTP methods:
hello(GET),create(POST),update(PUT), andping(GET under/api). - The
updatehandler demonstrates aPUTroute. - We create a nested router for
/apiand add a/api/pingroute. - Handlers return different types (
String,&'static str), showing Axum’s flexibility with any type that implementsIntoResponse. - All handler functions are async.
Best Practices:
- Prefer resource-oriented route names for real APIs (e.g.,
POST /items,PUT /items/{id});/createand/updatehere only illustrate method routing. - Return types should implement
IntoResponsefor flexibility (e.g.,String,&'static str, or custom types). - Use router nesting to organize related endpoints (e.g., group all API routes under
/api). - Keep handler functions small and focused.
Common Pitfalls:
- Mismatching HTTP method and handler (e.g., using GET for a create operation).
- Forgetting to make handler functions async.
- Not using router nesting for related endpoints, leading to a flat and hard-to-maintain route structure.
- Not handling different response types properly (e.g., always returning
&'static strwhen you may need to return aResult).
5. Tasks
- Add a new
PUTroute/updatethat returns a message like “Updated!”. - Try nesting a router under
/apiand add a route/api/pingthat returns “pong”. - Experiment with returning different types from handlers (e.g.,
String,&'static str). - Bonus: Try returning a custom struct as JSON from a handler using
Jsonfromaxum::Json. - Bonus: Add error handling to a handler and return a custom error response.