1use crate::{
2 routes::{RequestProcessor, RouteContext, RouteMethod},
3 server::Server,
4};
5use serde::{Serialize, de::DeserializeOwned};
6use serde_json::Value;
7use std::{collections::HashMap, error::Error, net::SocketAddr};
8
9pub struct Request(pub http::Request<Value>);
10pub struct Response(pub http::Response<Value>);
11
12pub trait Route: FnMut(Request) -> Response + 'static {}
14impl<T> Route for T where T: FnMut(Request) -> Response + 'static {}
15
16pub trait TextRoute: FnMut() -> String + 'static {}
22impl<T> TextRoute for T where T: FnMut() -> String + 'static {}
23
24#[derive(Default)]
43pub struct Mise {
44 routes: HashMap<RouteMethod, HashMap<String, RouteContext>>,
45 text_routes: HashMap<String, Box<dyn TextRoute>>,
46}
47
48impl Mise {
49 #[must_use]
51 pub fn new() -> Self {
52 Self::default()
53 }
54
55 #[must_use]
60 pub fn text<F: TextRoute>(mut self, path: &str, f: F) -> Self {
61 self.text_routes.insert(path.to_string(), Box::new(f));
62 self
63 }
64
65 #[must_use]
67 pub fn get<F: Route>(mut self, path: &str, f: F) -> Self {
68 self.regiser_method(RouteMethod::Get, path, f);
69 self
70 }
71
72 #[must_use]
74 pub fn delete<F: Route>(mut self, path: &str, f: F) -> Self {
75 self.regiser_method(RouteMethod::Delete, path, f);
76 self
77 }
78
79 #[must_use]
82 pub fn post<F: Route>(mut self, path: &str, f: F) -> Self {
83 self.regiser_method(RouteMethod::Post, path, f);
84 self
85 }
86
87 #[must_use]
90 pub fn put<F: Route>(mut self, path: &str, f: F) -> Self {
91 self.regiser_method(RouteMethod::Put, path, f);
92 self
93 }
94
95 #[must_use]
98 pub fn patch<F: Route>(mut self, path: &str, f: F) -> Self {
99 self.regiser_method(RouteMethod::Patch, path, f);
100 self
101 }
102
103 pub fn serve(self, addr: SocketAddr) {
106 Server::serve(
107 RequestProcessor {
108 routes: self.routes,
109 text_routes: self.text_routes,
110 },
111 addr,
112 )
113 .run();
114 }
115
116 fn regiser_method<F: Route>(&mut self, method: RouteMethod, path: &str, f: F) {
117 let routes = self.routes.entry(method).or_default();
118 let d: Box<dyn Route> = Box::new(f);
119 routes.insert(path.to_string(), (path, d).into());
120 }
121}
122
123impl From<Request> for Value {
124 fn from(value: Request) -> Self {
125 value.0.body().to_owned()
126 }
127}
128
129impl From<Value> for Response {
130 fn from(value: Value) -> Self {
131 Response(http::Response::new(value))
132 }
133}
134
135impl From<http::StatusCode> for Response {
136 fn from(value: http::StatusCode) -> Self {
137 Response(
138 http::Response::builder()
139 .status(value)
140 .body(Value::Null)
141 .expect("Statically built body should not fail"),
142 )
143 }
144}
145
146pub trait Serializable: Serialize {
147 fn to_response(&self) -> Result<Response, Box<dyn Error>> {
151 Ok(Response(http::Response::new(serde_json::to_value(self)?)))
152 }
153}
154impl<T> Serializable for T where T: Serialize {}
155
156pub trait Deserializable: DeserializeOwned {
157 fn from_request(r: Request) -> Result<Self, Box<dyn Error>> {
161 Ok(serde_json::from_value(r.body().to_owned())?)
162 }
163}
164impl<T> Deserializable for T where T: DeserializeOwned {}
165
166impl Request {
167 pub fn path(&self) -> &str {
169 self.0.uri().path()
170 }
171
172 pub fn query(&self) -> Option<&str> {
173 self.0.uri().query()
174 }
175
176 pub fn query_param(&self, name: &str) -> Option<&str> {
178 let q = self.0.uri().query()?;
179 let f = format!("{name}=");
180 let idx = q.find(&f)?;
181 let end = q[idx..].find('&').unwrap_or(q.len());
182 Some(&q[idx + f.len()..end])
183 }
184
185 pub fn base(&self) -> &str {
191 let p = self.0.uri().path();
192 let n = self.name();
193 p[..p.len() - n.len()].trim_end_matches('/')
194 }
195
196 pub fn name(&self) -> &str {
202 if !self.0.uri().path().contains('/') {
203 return "";
204 }
205 self.0.uri().path().split('/').next_back().unwrap_or("")
206 }
207
208 pub fn body(&self) -> &Value {
212 self.0.body()
213 }
214
215 pub(crate) fn base_star(&self) -> Option<String> {
216 if self.name().is_empty() {
217 return None;
219 }
220 Some(format!("{}/*", self.base()))
221 }
222}
223
224#[cfg(test)]
225mod test {
226 use super::*;
227 use serde::Deserialize;
228 use serde_json::json;
229
230 #[derive(Serialize, Deserialize)]
231 struct My {
232 val: usize,
233 }
234
235 #[test]
236 fn test_serde() {
237 let m = My { val: 1 };
238 let r = m.to_response().unwrap();
239 assert_eq!(r.0.body()["val"].clone(), 1);
240
241 let r = Request(http::Request::new(json!({"val":2})));
242 let m = My::from_request(r).unwrap();
243 assert_eq!(m.val, 2);
244 }
245
246 #[test]
247 fn test_paths() {
248 assert_eq!(requri("/").name(), "");
249 assert_eq!(requri("/a").name(), "a");
250 assert_eq!(requri("/a/b").name(), "b");
251
252 assert_eq!(requri("/").base(), "");
253 assert_eq!(requri("/a").base(), "");
254 assert_eq!(requri("/a/b").base(), "/a");
255
256 assert_eq!(requri("/").base_star(), None);
257 assert_eq!(requri("/a").base_star(), Some("/*".to_string()));
258 assert_eq!(requri("/a/b").base_star(), Some("/a/*".to_string()));
259
260 assert_eq!(requri("/?b=a").query_param("b"), Some("a"));
261 }
262
263 fn requri(uri: &str) -> Request {
264 Request(http::Request::builder().uri(uri).body(Value::Null).unwrap())
265 }
266}