Skip to main content

ullun/
request.rs

1//! Request types and extractors
2
3use crate::error::{Error, Result};
4use serde::de::DeserializeOwned;
5use std::collections::HashMap;
6
7/// Path parameters extracted from route
8#[derive(Debug, Clone)]
9pub struct Params {
10    inner: HashMap<String, String>,
11}
12
13impl Params {
14    pub fn new() -> Self {
15        Self {
16            inner: HashMap::new(),
17        }
18    }
19
20    pub fn insert(&mut self, key: String, value: String) {
21        self.inner.insert(key, value);
22    }
23
24    pub fn get(&self, key: &str) -> Result<&str> {
25        self.inner
26            .get(key)
27            .map(|s| s.as_str())
28            .ok_or_else(|| Error::bad_request(format!("Missing param: {}", key)))
29    }
30
31    pub fn get_opt(&self, key: &str) -> Option<&str> {
32        self.inner.get(key).map(|s| s.as_str())
33    }
34}
35
36impl Default for Params {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42/// Query parameters from URL
43#[derive(Debug, Clone)]
44pub struct Query {
45    inner: HashMap<String, String>,
46}
47
48impl Query {
49    pub fn new() -> Self {
50        Self {
51            inner: HashMap::new(),
52        }
53    }
54
55    pub fn parse_query_string(query: &str) -> Self {
56        let mut q = Query::new();
57        for pair in query.split('&') {
58            if let Some((key, value)) = pair.split_once('=') {
59                q.inner.insert(
60                    key.to_string(),
61                    urlencoding::decode(value).unwrap_or_default().to_string(),
62                );
63            }
64        }
65        q
66    }
67
68    pub fn get(&self, key: &str) -> Option<&str> {
69        self.inner.get(key).map(|s| s.as_str())
70    }
71
72    pub fn parse<T: DeserializeOwned>(&self) -> Result<T> {
73        let value = serde_json::to_value(&self.inner)
74            .map_err(|e| Error::internal(format!("Failed to serialize query params: {}", e)))?;
75        serde_json::from_value(value)
76            .map_err(|e| Error::bad_request(format!("Invalid query params: {}", e)))
77    }
78}
79
80impl Default for Query {
81    fn default() -> Self {
82        Self::new()
83    }
84}
85
86/// HTTP Request wrapper
87pub struct Request {
88    pub method: http::Method,
89    pub uri: http::Uri,
90    pub headers: http::HeaderMap,
91    pub body: bytes::Bytes,
92    pub params: Params,
93    pub query: Query,
94}
95
96impl Request {
97    pub fn new(
98        method: http::Method,
99        uri: http::Uri,
100        headers: http::HeaderMap,
101        body: bytes::Bytes,
102    ) -> Self {
103        let query = uri
104            .query()
105            .map(Query::parse_query_string)
106            .unwrap_or_default();
107
108        Self {
109            method,
110            uri,
111            headers,
112            body,
113            params: Params::new(),
114            query,
115        }
116    }
117
118    /// Parse JSON body
119    pub fn json<T: DeserializeOwned>(&self) -> Result<T> {
120        serde_json::from_slice(&self.body)
121            .map_err(|e| Error::bad_request(format!("Invalid JSON: {}", e)))
122    }
123}