Study
Axum

Shared State dengan State<T>

Penjelasan

Kebanyakan aplikasi web butuh data yang dipakai bersama oleh banyak handler — koneksi database, konfigurasi, atau cache in-memory. Axum menyediakan extractor `State<T>` untuk kebutuhan ini. Alurnya: kamu membuat nilai state (misalnya `struct AppState`), lalu mendaftarkannya ke router lewat `.with_state(state)`. Setelah itu, handler mana pun bisa menerima state tersebut cukup dengan menambahkan parameter `State(state): State<AppState>`. Karena Rust punya aturan ownership yang ketat, dan state ini dipakai bersamaan oleh banyak task async, state biasanya dibungkus `Arc<T>` (Atomic Reference Counted) supaya bisa di-clone murah (hanya menambah reference count, bukan meng-copy datanya) dan aman diakses dari banyak thread sekaligus. Kalau field di dalam state perlu diubah (bukan cuma dibaca), tambahkan `Mutex` atau `RwLock` di dalamnya — tapi untuk kebanyakan kasus (misalnya pool koneksi database), state cukup dibungkus `Arc` saja karena pool sendiri sudah aman diakses concurrent.

Contoh Konsep

use axum::{extract::State, routing::get, Router};
use std::sync::Arc;

struct AppState {
    app_name: String,
}

async fn show_name(State(state): State<Arc<AppState>>) -> String {
    format!("Nama aplikasi: {}", state.app_name)
}

#[tokio::main]
async fn main() {
    let shared_state = Arc::new(AppState {
        app_name: "Catatan API".to_string(),
    });

    let app = Router::new()
        .route("/", get(show_name))
        .with_state(shared_state);

    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Praktikum

Buat `AppState` dengan field `version: String`, lalu handler `show_version` yang menampilkannya, dan daftarkan state ke router.

Editor Latihan

Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.

Tips

Kalau lupa memanggil `.with_state(...)` setelah handler memakai extractor `State<T>`, kompilasi akan gagal dengan pesan error yang cukup panjang soal trait `Handler` tidak terpenuhi. Ini normal — cukup pastikan `.with_state()` dipanggil PALING TERAKHIR setelah semua `.route()` didaftarkan.