simple_api/
lib.rs

1use crate::context::Context;
2use crate::middleware::Middleware;
3use crate::types::HttpResonse;
4use crate::view::View;
5use hyper::service::{make_service_fn, service_fn};
6use hyper::{Server, StatusCode};
7use once_cell::sync::Lazy;
8use route::match_view;
9use std::borrow::BorrowMut;
10
11use std::convert::Infallible;
12use std::net::SocketAddr;
13use std::sync::Arc;
14use tokio::sync::Mutex;
15use types::{State, HttpRequest};
16use std::any;
17
18pub mod context;
19pub mod middleware;
20pub mod middlewares;
21pub mod views;
22pub mod response;
23pub mod route;
24pub mod session;
25pub mod types;
26pub mod utils;
27pub mod view;
28
29pub static GLOBAL_SIMPLE_API_INSTANCE: Lazy<SimpleApi> = Lazy::new(|| SimpleApi::new());
30
31pub async fn apply_middlewares_pre(
32    req: &mut HttpRequest,
33    ctx: &mut Context,
34    middlewares: &Vec<Arc<dyn Middleware>>,
35) -> anyhow::Result<Option<HttpResonse>> {
36    for m in middlewares.iter() {
37        match m.pre_process(req, ctx).await {
38            Ok(None) => continue,
39            other => return other,
40        }
41    }
42    Ok(None)
43}
44
45pub async fn apply_middlewares_post(
46    req: &mut HttpRequest,
47    res: &mut HttpResonse,
48    ctx: &mut Context,
49    middlewares: &Vec<Arc<dyn Middleware>>,
50) -> anyhow::Result<Option<HttpResonse>> {
51    for m in middlewares.iter() {
52        match m.post_process(req, res, ctx).await {
53            Ok(None) => continue,
54            other => return other,
55        }
56    }
57    Ok(None)
58}
59
60async fn app_core(mut req: HttpRequest) -> Result<HttpResonse, Infallible> {
61    let path = req.uri().path().to_string();
62    let (view, mut ctx) = {
63        let view_and_vpas = {
64            let _routes = SimpleApi::routes();
65            let _routes = _routes.lock().await;
66
67            match_view(&_routes, &path)
68        };
69        let (view, view_args) = match view_and_vpas {
70            Some(v) => (Some(v.0), Some(v.1)),
71            None => (None, None),
72        };
73
74        let sp = SimpleApi::session_provider().lock().await.clone();
75
76        let state = SimpleApi::state().lock().await.clone();
77
78        let ctx = Context::new(sp, state, view_args);
79        (view, ctx)
80    };
81    
82    let middlewares = SimpleApi::middlewares();
83    match apply_middlewares_pre(&mut req, &mut ctx, &middlewares.lock().await.borrow_mut()).await {
84        Ok(None) => (),
85        Ok(Some(v)) => return Ok(v),
86        Err(e) => return Ok(response::internal_server_error(e).unwrap()),
87    }
88
89    let Some(view) = view else {
90        return Ok(response::build_response(
91            format!("Not found: {}", path),
92            StatusCode::NOT_FOUND,
93            "text/html",
94        )
95        .unwrap());
96    };
97
98    match view.call(&mut req, &mut ctx).await {
99        Ok(r) => {
100            let mut res = r;
101            match apply_middlewares_post(
102                &mut req,
103                &mut res,
104                &mut ctx,
105                &middlewares.lock().await.borrow_mut(),
106            )
107            .await
108            {
109                Ok(None) => (),
110                Ok(Some(v)) => return Ok(v),
111                Err(e) => return Ok(response::internal_server_error(e).unwrap()),
112            }
113            Ok(res)
114        }
115        Err(e) => Ok(response::internal_server_error(e).unwrap()),
116    }
117}
118
119pub struct SimpleApi {
120    routes: Arc<Mutex<Vec<Arc<dyn View>>>>,
121    middlewares: Arc<Mutex<Vec<Arc<dyn Middleware>>>>,
122    session_provider: Arc<Mutex<Option<Arc<dyn session::SessionProvider>>>>,
123    state: Arc<Mutex<State>>,
124}
125
126impl SimpleApi {
127    pub fn new() -> Self {
128        let _middlewares: Vec<Arc<dyn Middleware>> = vec![Arc::new(middlewares::SessionMiddleware)];
129        SimpleApi {
130            routes: Arc::new(Mutex::new(Vec::new())),
131            middlewares: Arc::new(Mutex::new(_middlewares)),
132            session_provider: Arc::new(Mutex::new(None)),
133            state: Arc::new(Mutex::new(Arc::new(()))),
134        }
135    }
136
137    pub fn instance() -> &'static SimpleApi {
138        &GLOBAL_SIMPLE_API_INSTANCE
139    }
140
141    pub fn routes() -> Arc<Mutex<Vec<Arc<dyn View>>>> {
142        Self::instance().routes.clone()
143    }
144
145    pub fn middlewares() -> Arc<Mutex<Vec<Arc<dyn Middleware>>>> {
146        Self::instance().middlewares.clone()
147    }
148
149    pub fn session_provider() -> Arc<Mutex<Option<Arc<dyn session::SessionProvider>>>> {
150        Self::instance().session_provider.clone()
151    }
152
153    pub fn state() -> Arc<Mutex<State>> {
154        Self::instance().state.clone()
155    }
156
157    pub async fn add_route<T: any::Any + View>(view: T) {
158        let routes = SimpleApi::routes();
159        let mut routes = routes.lock().await;
160        routes.push(Arc::new(view));
161    }
162
163    pub async fn run(addr: &str) -> () {
164        let addr = addr.parse::<SocketAddr>().unwrap();
165
166        let make_svc = make_service_fn(|_conn| async {
167            // service_fn converts our function into a `Service`
168            Ok::<_, Infallible>(service_fn(app_core))
169        });
170
171        let server = Server::bind(&addr).serve(make_svc);
172
173        // Run this server for... forever!
174        if let Err(e) = server.await {
175            eprintln!("server error: {}", e);
176        }
177    }
178
179    pub async fn add_middleware(m: Arc<dyn Middleware>) {
180        let middlewares = SimpleApi::middlewares();
181        let mut middlewares = middlewares.lock().await;
182        middlewares.push(m);
183    }
184
185    pub async fn set_session_provider(provider: Arc<dyn session::SessionProvider>) {
186        let sp = SimpleApi::session_provider();
187        let mut session_provider = sp.lock().await;
188        *session_provider = Some(provider);
189    }
190
191    pub async fn set_state(state: State) {
192        let s = SimpleApi::state();
193        let mut s = s.lock().await;
194        *s = state;
195    }
196}