Skip to main content

rustbasic_core/
requests.rs

1use serde_json::{json, Value};
2use std::collections::HashMap;
3use crate::validator::Validate;
4use crate::router::{Response, IntoResponse, Json};
5use crate::session::Session;
6
7#[derive(Clone)]
8pub struct Request {
9    pub inputs: Value,
10    pub method: http::Method,
11    pub path: String,
12    pub headers: HashMap<String, String>,
13    pub session: Session,
14    pub state: crate::AppState,
15    pub ip_address: String,
16    /// Route parameters, misal dari "/user/{id}" → params["id"] = "123"
17    pub params: HashMap<String, String>,
18}
19
20impl Request {
21    pub fn input(&self, key: &str) -> Option<&Value> {
22        self.inputs.get(key)
23    }
24
25    pub fn input_as_str(&self, key: &str) -> Option<&str> {
26        self.inputs.get(key).and_then(|v| v.as_str())
27    }
28
29    pub fn query(&self, key: &str) -> Option<&str> {
30        self.input_as_str(key)
31    }
32
33    pub fn all(&self) -> &Value {
34        &self.inputs
35    }
36
37    /// Ambil route parameter, misal `req.param("id")` dari route "/user/{id}"
38    pub fn param(&self, key: &str) -> Option<&str> {
39        self.params.get(key).map(|s| s.as_str())
40    }
41
42    pub fn validate<T: Validate + serde::de::DeserializeOwned>(&self) -> Result<T, Box<(http::StatusCode, Response)>> {
43        let data: T = serde_json::from_value(self.inputs.clone()).map_err(|e| {
44            Box::new((http::StatusCode::UNPROCESSABLE_ENTITY, 
45             Json(json!({ "error": "Invalid format", "detail": e.to_string() })).into_response()))
46        })?;
47
48        data.validate().map_err(|errors| {
49            // Simpan input lama ke session untuk repopulasi form (Flash Input)
50            self.session.set("old", self.inputs.clone());
51            
52            // Simpan error di session untuk keperluan Inertia/Redirect
53            self.session.set("errors", errors.clone());
54            
55            Box::new((http::StatusCode::UNPROCESSABLE_ENTITY, 
56             Json(json!({ "errors": errors })).into_response()))
57        })?;
58
59        Ok(data)
60    }
61}