aws_lambda_router/
request.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Request context from Lambda event
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Context {
8    pub request_id: String,
9    pub user_id: Option<String>,
10    pub email: Option<String>,
11    pub auth_token: Option<String>,
12    pub custom: HashMap<String, Value>,
13}
14
15impl Context {
16    pub fn new(request_id: String) -> Self {
17        Self {
18            request_id,
19            user_id: None,
20            email: None,
21            auth_token: None,
22            custom: HashMap::new(),
23        }
24    }
25    
26    pub fn with_user(mut self, user_id: String, email: Option<String>) -> Self {
27        self.user_id = Some(user_id);
28        self.email = email;
29        self
30    }
31    
32    pub fn with_custom(mut self, key: String, value: Value) -> Self {
33        self.custom.insert(key, value);
34        self
35    }
36}
37
38/// HTTP Request representation
39#[derive(Debug, Clone)]
40pub struct Request {
41    pub method: String,
42    pub path: String,
43    pub headers: HashMap<String, String>,
44    pub query_params: HashMap<String, String>,
45    pub path_params: HashMap<String, String>,
46    pub body: Option<String>,
47    pub context: Context,
48    raw_event: Value,
49}
50
51impl Request {
52    /// Create a new Request from Lambda event
53    pub fn from_lambda_event(event: Value) -> Self {
54        let method = event["requestContext"]["http"]["method"]
55            .as_str()
56            .unwrap_or("GET")
57            .to_string();
58        
59        let path = event["rawPath"]
60            .as_str()
61            .unwrap_or("/")
62            .to_string();
63        
64        let headers = event.get("headers")
65            .and_then(|v| v.as_object())
66            .map(|obj| {
67                obj.iter()
68                    .map(|(k, v)| (k.clone(), v.as_str().unwrap_or("").to_string()))
69                    .collect()
70            })
71            .unwrap_or_default();
72        
73        let query_params = event.get("queryStringParameters")
74            .and_then(|v| v.as_object())
75            .map(|obj| {
76                obj.iter()
77                    .map(|(k, v)| (k.clone(), v.as_str().unwrap_or("").to_string()))
78                    .collect()
79            })
80            .unwrap_or_default();
81        
82        let body = event.get("body")
83            .and_then(|v| v.as_str())
84            .map(|s| s.to_string());
85        
86        let request_id = event["requestContext"]["requestId"]
87            .as_str()
88            .unwrap_or("unknown")
89            .to_string();
90        
91        Self {
92            method,
93            path,
94            headers,
95            query_params,
96            path_params: HashMap::new(),
97            body,
98            context: Context::new(request_id),
99            raw_event: event,
100        }
101    }
102    
103    /// Get header value
104    pub fn header(&self, name: &str) -> Option<&String> {
105        self.headers.get(name)
106            .or_else(|| self.headers.get(&name.to_lowercase()))
107    }
108    
109    /// Get query parameter
110    pub fn query(&self, name: &str) -> Option<&String> {
111        self.query_params.get(name)
112    }
113    
114    /// Get path parameter
115    pub fn path_param(&self, name: &str) -> Option<&String> {
116        self.path_params.get(name)
117    }
118    
119    /// Parse JSON body
120    pub fn json<T: for<'de> Deserialize<'de>>(&self) -> Result<T, serde_json::Error> {
121        match &self.body {
122            Some(body) => serde_json::from_str(body),
123            None => serde_json::from_str("{}"),
124        }
125    }
126    
127    /// Get raw body
128    pub fn body(&self) -> Option<&str> {
129        self.body.as_deref()
130    }
131    
132    /// Get raw Lambda event
133    pub fn raw_event(&self) -> &Value {
134        &self.raw_event
135    }
136    
137    /// Check if request is CORS preflight
138    pub fn is_preflight(&self) -> bool {
139        self.method == "OPTIONS"
140    }
141    
142    /// Set path parameters (used internally by router)
143    pub(crate) fn set_path_params(&mut self, params: HashMap<String, String>) {
144        self.path_params = params;
145    }
146    
147    /// Set context (used internally by middleware)
148    pub fn set_context(&mut self, context: Context) {
149        self.context = context;
150    }
151}