Urutan Extractor
Penjelasan
Extractor di Axum diproses SESUAI URUTAN kemunculannya dalam signature handler, dari kiri ke kanan. Ini penting karena beberapa extractor (seperti `Json<T>`, `String`, `Bytes`) mengonsumsi body request — begitu dikonsumsi, tidak ada lagi body tersisa untuk extractor lain di belakangnya. Aturan praktisnya: extractor yang MENGONSUMSI BODY (seperti `Json<T>`) harus ditempatkan PALING TERAKHIR dalam signature handler. Extractor yang tidak menyentuh body (`Path<T>`, `Query<T>`, `State<T>`, `HeaderMap`) boleh berada di posisi mana saja sebelum extractor body. Kalau kamu melanggar aturan ini (misalnya `Json<T>` diikuti `Path<T>` di belakangnya), kompilasi akan gagal dengan pesan error yang menyebut trait `FromRequest` tidak terpenuhi untuk kombinasi tersebut — pesan errornya tidak selalu jelas, jadi mengingat aturan urutan ini akan menghemat banyak waktu debugging.
Contoh Konsep
use axum::{extract::{Path, State}, routing::put, Json, Router};
use serde::Deserialize;
use std::sync::Arc;
#[derive(Deserialize)]
struct UpdateNote {
title: String,
}
struct AppState;
// URUTAN BENAR: Path, State (tidak menyentuh body) -> Json (menyentuh body, PALING TERAKHIR)
async fn update_note(
Path(id): Path<u32>,
State(_state): State<Arc<AppState>>,
Json(payload): Json<UpdateNote>,
) -> String {
format!("Catatan {} diupdate jadi '{}'", id, payload.title)
}
// URUTAN SALAH (tidak akan kompilasi):
// async fn broken(Json(payload): Json<UpdateNote>, Path(id): Path<u32>) -> String { ... }
#[tokio::main]
async fn main() {
let state = Arc::new(AppState);
let app = Router::new()
.route("/notes/{id}", put(update_note))
.with_state(state);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Praktikum
Perbaiki urutan parameter pada handler di bawah supaya bisa dikompilasi — `Json<T>` harus di posisi paling akhir.
Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.
Tips
Kalau butuh membaca body DAN beberapa extractor lain yang sama-sama "istimewa" (misalnya `Request` mentah), letakkan extractor paling generik/mentah di posisi paling akhir juga. Aturan sederhananya: makin spesifik/aman extractor-nya (Path, Query, State, header), makin awal boleh diletakkan; makin dia "melahap" seluruh request, makin ke belakang.