နားလည်ထားရမယ့် အချက်
Axum ဟာ `tokio` runtime ပေါ်တွင် တည်ဆောက်ထားတဲ့ Rust web framework တစ်ခုဖြစ်ပြီး Lesson 19 ရဲ့ async fundamentals ကို production-shaped HTTP server တစ်ခုအဖြစ် direct application လုပ်တာပါ—route handler တစ်ခုစီက `async fn` ဖြစ်ပြီး request ရာနှင့်ချီကို OS thread အနည်းငယ်တည်းနဲ့ concurrently handle နိုင်ပါတယ်။ Axum ရဲ့ core design idea က "extractor" pattern ဖြစ်ပြီး handler function ရဲ့ parameter type ကနေတစ်ဆင့် request ရဲ့ ဘယ် part (path parameter, query string, JSON body) ကို လိုချင်လဲ declare လုပ်ပါတယ်—`Path(id): Path<u32>` ဆိုရင် URL path ကနေ `id` ကို auto-extract/parse လုပ်ပေးပါတယ်၊ parse မအောင်မြင်ရင် Axum က 400 Bad Request ကို automatic response ပြန်ပေးလို့ manual validation code ရေးစရာ မလိုတော့ပါ။ Response ကို JSON အဖြစ် serialize ချင်ရင် `serde::Serialize` trait ကို struct ပေါ် `#[derive(Serialize)]` ဖြင့် auto-implement ပေးလို့ရပါတယ်—Lesson 14 ရဲ့ trait implementation ကို compiler-generated code (derive macro) ဖြင့် manual boilerplate မရေးဘဲ ရနိုင်တဲ့ pattern တစ်ခုပါ။ Node.js/Express လို framework တွေနှင့် ဆင်တူတဲ့ route/handler concept ဖြစ်ပေမယ့် Axum ရဲ့ handler ဟာ type-checked—wrong extractor type ရေးမိရင် runtime error အစား compile error ရမှာဖြစ်ပါတယ်—ဒါက ဒီ site ရဲ့ backend logic ကို ပိုပြီး memory-safe, type-safe implementation ဖြင့် complement လုပ်ပေးနိုင်တဲ့ shape ကို ဖော်ပြနေတာပါ။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Tutorial Platform ရဲ့ `GET /lessons/{id}` endpoint ကို `async fn get_lesson(Path(id): Path<u32>) -> Json<LessonMetadata>` handler ဖြင့် ဆောက်မယ်—`id` ကို URL path ကနေ auto-parse (invalid id ဆိုရင် Axum က automatic 400 response ပေးမယ်) လုပ်ပြီး `LessonStat` (Lesson 21 ရဲ့ project) data ကနေ metadata ကို lookup ကာ `Json(...)` wrapper ဖြင့် serialize ပြန်ပေးမယ်။ Router ကို `Router::new().route("/lessons/{id}", get(get_lesson))` ဖြင့် define ပြီး `#[tokio::main]` main function ထဲမှာ `axum::serve(listener, router).await` ဖြင့် server ကို run မယ်—Lesson 19 ရဲ့ tokio runtime setup ကို ဒီနေရာမှာ ထပ်တွေ့ရပါလိမ့်မယ်။ Lesson ID ရှာမတွေ့ရင် (Lesson 10 ရဲ့ `Option<T>` ကို ပြန်လက်တွေ့ကျင့်ကြည့်မယ်) HTTP 404 status code ကို explicit ပြန်ပေးမယ်—`None` case ကို handle မလုပ်ဘဲ unwrap ချည်းသုံးရင် server whole thread panic ဖြစ်နိုင်ပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
use axum::{extract::Path, http::StatusCode, routing::get, Json, Router};
use serde::Serialize;
#[derive(Serialize)]
struct LessonMetadata {
id: u32,
title: String,
word_count: u32,
}
async fn get_lesson(Path(id): Path<u32>) -> Result<Json<LessonMetadata>, StatusCode> {
let lessons = [
LessonMetadata { id: 1, title: "Ownership".into(), word_count: 620 },
LessonMetadata { id: 2, title: "Borrowing".into(), word_count: 540 },
];
lessons
.into_iter()
.find(|lesson| lesson.id == id)
.map(Json)
.ok_or(StatusCode::NOT_FOUND)
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/lessons/{id}", get(get_lesson));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}`GET /lessons/1` ကို request ပို့လိုက်ရင် `{"id":1,"title":"Ownership","word_count":620}` JSON response ရမည်၊ `GET /lessons/99` လိုမျိုး dataset ထဲမရှိတဲ့ id အတွက်တော့ HTTP 404 status ပြန်ရမည်။၅ မိနစ် စမ်းကြည့်
`GET /lessons?difficulty=basic` ဆိုတဲ့ query-parameter route တစ်ခု ထပ်ထည့်ပါ—`Query<HashMap<String, String>>` extractor ကို သုံးပြီး `difficulty` value ကို ဖတ်ကာ matching lesson list (dummy data) ကို JSON array အဖြစ် ပြန်ပေးပါ။
သတိလေးတစ်ချက်
Lesson id ကို data store ထဲ ရှာမတွေ့ရင် `Option::unwrap()` ကို ခေါ်ပြီး Json response ပြန်ပေးကြိုးစားခြင်း—None case ကနေ panic ဖြစ်ပြီး HTTP 500 (internal server error) response client ဆီ ရောက်သွားနိုင်ပါတယ်—404 status ကို explicit ပြန်ပေးသင့်ပါတယ်။
Handler function ကို `fn` (non-async) အဖြစ် ရေးမိပြီး `.await` လိုအပ်တဲ့ database/file operation ကို ခေါ်ကြိုးစားခြင်း—compile error ရနိုင်ပါတယ်—Axum handler အားလုံးကို `async fn` ဖြစ်ရမည်။
Axum Documentation — Rust