Validasi Request Body
Penjelasan
Extractor `Json<T>` hanya memastikan body request BERBENTUK JSON yang sesuai struktur, tapi tidak memvalidasi ATURAN BISNIS — misalnya "email harus valid", "password minimal 8 karakter", atau "title tidak boleh kosong". Validasi semacam ini perlu ditangani terpisah. Cara paling sederhana adalah memvalidasi manual di dalam handler dengan if/else, lalu mengembalikan `AppError::BadRequest(...)` yang sudah kamu buat di topik Error Handling kalau validasi gagal. Untuk aplikasi yang lebih besar, crate `validator` (dengan `#[derive(Validate)]` dan atribut seperti `#[validate(length(min = 1))]`, `#[validate(email)]`) mempermudah validasi deklaratif tanpa menulis banyak `if` manual. Pola umum: panggil `.validate()` pada payload segera setelah di-extract dari `Json<T>`, sebelum data itu dipakai untuk query database atau logic lain — supaya data yang tidak valid tidak pernah sampai menyentuh lapisan bawahnya.
Contoh Konsep
// cargo add validator --features derive
use axum::{routing::post, Json, Router};
use serde::Deserialize;
use validator::Validate;
#[derive(Deserialize, Validate)]
struct CreateNote {
#[validate(length(min = 1, message = "title tidak boleh kosong"))]
title: String,
#[validate(length(min = 1, message = "body tidak boleh kosong"))]
body: String,
}
async fn create_note(Json(payload): Json<CreateNote>) -> Result<String, String> {
payload.validate().map_err(|e| e.to_string())?;
Ok(format!("Catatan '{}' valid dan disimpan", payload.title))
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/notes", post(create_note));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Praktikum
Tambahkan validasi supaya field `email` pada struct `RegisterRequest` harus berformat email valid.
Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.
Tips
Untuk pengalaman error yang lebih rapi ke client, ubah hasil `.validate()` yang gagal menjadi `AppError::BadRequest(...)` (dari topik Error Handling) alih-alih `String` mentah — supaya semua error di aplikasimu tetap konsisten dalam satu format JSON.