Les 1 · Module 1 · Async en Axum-basis
Je eerste Axum-service
Een Axum-project opzetten en een eerste endpoint maken dat JSON teruggeeft.
🎯 Na deze les kun je
- een Cargo-project met Axum en Tokio opzetten
- een handler schrijven die tekst en JSON teruggeeft
- uitleggen waarom main async is
In Een beetje Rust schreef je command-line tools. Een webservice is een programma dat blijft draaien en op verzoeken wacht. Dat wachten gebeurt asynchroon: terwijl het ene verzoek op de database wacht, kan het programma een ander verzoek afhandelen. Axum is een webframework bovenop de Tokio-runtime dat daar goed gebruik van maakt.
Wat je nodig hebt
- Rust via rustup (
cargo --version) - Kennis van ownership, structs, enums en
Resultuit Een beetje Rust
Project maken
cargo new kassa-api && cd kassa-api
cargo add axum
cargo add tokio --features full
cargo add serde --features derive
Uitgewerkt voorbeeld
src/main.rs:
use axum::{extract::Path, routing::get, Json, Router};
use serde::Serialize;
#[derive(Serialize)]
struct Totaal {
bedrag: u32,
btw: f64,
}
async fn home() -> &'static str {
"Kassa"
}
async fn totaal(Path(bedrag): Path<u32>) -> Json<Totaal> {
Json(Totaal { bedrag, btw: bedrag as f64 * 0.21 })
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(home))
.route("/totaal/:bedrag", get(totaal));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
println!("Luistert op http://127.0.0.1:3000");
axum::serve(listener, app).await.unwrap();
}
Let op: vanaf Axum 0.8 schrijf je padparameters als
/totaal/{bedrag}. Kijk welke versiecargo addheeft geïnstalleerd (Cargo.toml) en gebruik de bijbehorende notatie.
Voorspel eerst: wat geeft curl http://127.0.0.1:3000/totaal/100 terug? En /totaal/-5?
cargo run
curl -i http://127.0.0.1:3000/totaal/100
Je krijgt {"bedrag":100,"btw":21.0} met content-type: application/json. Bij -5 past de waarde
niet in een u32. Axum geeft dan zelf een 400 Bad Request terug, nog voordat je handler draait.
Het type van je parameter is dus ook je eerste validatie.
Wat is er nieuw?
#[tokio::main]start de async-runtime; zonder runtime kan eenasync fnniet worden uitgevoerd.- Een handler is een gewone
async fn. Wat hij teruggeeft, moet Axum kunnen omzetten naar een antwoord (&str,Json<T>,StatusCode, …). Path(bedrag)is een extractor: Axum haalt het stuk uit de URL en zet het om naar het type dat je vraagt.
Oefenen
- Voeg
/totaal/:bedrag/incltoe dat ook het bedrag inclusief btw teruggeeft. - Geef bij bedrag
0eenStatusCode::BAD_REQUESTterug (tip: return typeResult<Json<Totaal>, StatusCode>). - Meet met
time curl …hoe snel een antwoord is incargo run --releasetegenover debug.
Typische fouten
the trait Handler<_, _> is not implemented: meestal geeft je handler een type terug dat Axum niet kent, of is de functie nietasync.- Versieverschillen: voorbeelden online gebruiken soms een oudere Axum-API (
axum::Server). Volg de versie in jeCargo.toml. Address already in use: er draait nog een vorigecargo run.
Samenvatting
Een Axum-service is een Router met handlers, gestart op de Tokio-runtime. In de volgende les kijk je
wat async in Rust echt betekent en waarom dat voor een webservice uitmaakt.