1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use axum::http::{HeaderMap, Uri};
5
6#[derive(Serialize, Debug)]
8pub struct Location {
9 href: String,
10 pathname: String,
11 #[serde(rename(serialize = "searchStr"))]
12 search_str: String,
13 search: HashMap<String, String>,
14}
15
16impl Location {
17 pub fn pathname(&self) -> &String {
18 &self.pathname
19 }
20}
21
22impl From<Uri> for Location {
23 fn from(uri: Uri) -> Self {
24 let query = uri.query().unwrap_or("");
25 Location {
26 href: uri.to_string(),
28 pathname: uri.path().to_string(),
29 search_str: query.to_string(),
30 search: serde_urlencoded::from_str(query).unwrap_or(HashMap::new()),
31 }
32 }
33}
34
35#[derive(Debug, Clone)]
36pub struct Request {
37 pub uri: Uri,
38 pub headers: HeaderMap,
39 pub params: HashMap<String, String>,
40}
41
42impl Request {
43 pub fn new(uri: Uri, headers: HeaderMap, params: HashMap<String, String>) -> Request {
44 Request {
45 uri,
46 headers,
47 params,
48 }
49 }
50
51 pub fn location(&self) -> Location {
52 Location::from(self.uri.to_owned())
53 }
54
55 pub fn body<'de, T: Deserialize<'de>>(&'de self) -> Result<T, BodyParseError> {
56 if let Some(body) = self.headers.get("body") {
57 if let Ok(body) = body.to_str() {
58 let body = serde_json::from_str::<T>(body)?;
59 return Ok(body);
60 }
61 return Err(BodyParseError::Io(std::io::Error::new(
62 std::io::ErrorKind::InvalidData,
63 "Failed to read body",
64 )));
65 }
66 Err(BodyParseError::Io(std::io::Error::new(
67 std::io::ErrorKind::InvalidData,
68 "No body found",
69 )))
70 }
71}
72
73#[derive(Debug)]
74pub enum BodyParseError {
75 Io(std::io::Error),
76 Serde(serde_json::Error),
77}
78
79impl From<serde_json::Error> for BodyParseError {
80 fn from(err: serde_json::Error) -> BodyParseError {
81 BodyParseError::Serde(err)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87
88 use super::*;
89
90 #[derive(Debug, Deserialize)]
91 struct FakeBody {
92 field1: bool,
93 field2: String,
94 }
95
96 #[test]
97 fn it_correctly_parse_the_body() {
98 let mut request = Request::new(
99 Uri::from_static("http://localhost:3000"),
100 HeaderMap::new(),
101 HashMap::new(),
102 );
103
104 request.headers.insert(
105 "body",
106 r#"{"field1": true, "field2": "hello"}"#.parse().unwrap(),
107 );
108
109 let body: FakeBody = request.body().expect("Failed to parse body");
110
111 assert!(body.field1);
112 assert_eq!(body.field2, "hello".to_string());
113 }
114
115 #[test]
116 fn it_should_trigger_an_error_when_no_body_is_found() {
117 let request = Request::new(
118 Uri::from_static("http://localhost:3000"),
119 HeaderMap::new(),
120 HashMap::new(),
121 );
122
123 let body: Result<FakeBody, BodyParseError> = request.body();
124
125 assert!(body.is_err());
126 }
127
128 #[test]
129 fn it_should_trigger_an_error_when_body_is_invalid() {
130 let mut request = Request::new(
131 Uri::from_static("http://localhost:3000"),
132 HeaderMap::new(),
133 HashMap::new(),
134 );
135
136 request
137 .headers
138 .insert("body", r#"{"field1": true"#.parse().unwrap());
139
140 let body: Result<FakeBody, BodyParseError> = request.body();
141
142 assert!(body.is_err());
143 }
144}