Request Guards
Penjelasan
Request guard adalah fitur PALING KHAS Rocket — cara Rocket memvalidasi atau mengekstrak data dari request SEBELUM handler dipanggil, dengan menjadikan tipe data itu sendiri sebagai "penjaga gerbang". Kalau sebuah handler punya parameter bertipe custom yang meng-implementasi trait `FromRequest`, Rocket otomatis menjalankan logic guard tersebut lebih dulu — kalau gagal, handler TIDAK PERNAH dipanggil sama sekali, Rocket langsung mengembalikan response error sesuai yang ditentukan guard. Contoh paling umum: guard `ApiKey` yang memeriksa header `x-api-key` dan menolak request kalau key tidak valid, tanpa handler perlu tahu detail validasinya sama sekali — cukup deklarasikan `api_key: ApiKey` sebagai parameter, dan Rocket menjamin kalau handler dijalankan, berarti API key-nya pasti valid. Ini berbeda secara filosofis dari Axum: di Axum, extractor mengekstrak DATA (Path, Query, Json), sedangkan middleware/layer menangani CROSS-CUTTING CONCERN seperti autentikasi secara terpisah. Di Rocket, request guard MENYATUKAN keduanya — satu tipe data sekaligus jadi mekanisme validasi DAN cara mengakses hasil validasinya di handler.
Contoh Konsep
#[macro_use] extern crate rocket;
use rocket::request::{self, FromRequest, Request, Outcome};
use rocket::http::Status;
struct ApiKey(String);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey {
type Error = ();
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match req.headers().get_one("x-api-key") {
Some(key) if key == "rahasia123" => Outcome::Success(ApiKey(key.to_string())),
Some(_) => Outcome::Error((Status::Unauthorized, ())),
None => Outcome::Error((Status::BadRequest, ())),
}
}
}
#[get("/secret")]
fn secret_data(_key: ApiKey) -> &'static str {
"Data rahasia, hanya untuk pemegang API key valid"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![secret_data])
}
Praktikum
Lengkapi implementasi `FromRequest` untuk guard `AdminUser` yang memeriksa header "x-role" bernilai "admin".
Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.
Tips
Request guard bisa dikombinasikan bertingkat — satu guard bisa memanggil `req.guard::<GuardLain>().await` di dalam implementasinya sendiri untuk membangun guard yang lebih kompleks dari guard yang lebih sederhana. Perbandingan dengan Axum: kalau kamu sudah familiar dengan extractor custom di Axum (implementasi `FromRequestParts`), request guard Rocket melakukan hal serupa tapi lebih terintegrasi dengan sistem tipe Rocket secara keseluruhan, sehingga guard yang gagal bisa langsung menentukan response error-nya sendiri tanpa perlu `IntoResponse` terpisah.