1use crate::server::Server;
2use http::StatusCode;
3use serde_json::Value;
4use std::{collections::HashMap, net::SocketAddr};
5use tracing::trace;
6
7pub struct Request(pub http::Request<Value>);
8pub struct Response(pub http::Response<Value>);
9
10pub trait Route: Fn(Request) -> Response + 'static {}
12impl<T> Route for T where T: Fn(Request) -> Response + 'static {}
13
14#[derive(Default)]
16pub struct Mise {
17 routes: HashMap<String, Box<dyn Route>>,
18}
19
20impl Mise {
21 pub fn new() -> Self {
23 Self::default()
24 }
25
26 pub fn get<F: Route>(mut self, path: &str, f: F) -> Self {
28 self.routes.insert(path.to_string(), Box::new(f));
29 self
30 }
31
32 pub fn serve(self, addr: SocketAddr) {
35 Server::serve(
36 RequestProcessor {
37 routes: self.routes,
38 },
39 addr,
40 )
41 .run();
42 }
43}
44
45impl From<Request> for Value {
46 fn from(value: Request) -> Self {
47 value.0.body().to_owned()
48 }
49}
50
51impl From<Value> for Response {
52 fn from(value: Value) -> Self {
53 Response(http::Response::new(value))
54 }
55}
56
57impl From<http::StatusCode> for Response {
58 fn from(value: http::StatusCode) -> Self {
59 Response(
60 http::Response::builder()
61 .status(value)
62 .body(Value::Null)
63 .expect("Statically built body should not fail"),
64 )
65 }
66}
67
68pub(crate) struct RequestProcessor {
69 routes: HashMap<String, Box<dyn Route>>,
70}
71
72impl RequestProcessor {
73 pub(crate) fn process(&self, req: Request) -> Response {
74 let Some(route) = self.routes.get(&req.0.uri().to_string()) else {
75 return StatusCode::NOT_FOUND.into();
76 };
77 trace!("Received {:?}", req.0);
78 let resp = route(req);
79 trace!("Sending {:?}", resp.0);
80 resp
81 }
82}