rs_express/
core.rs

1use crate::middleware::matchable_middleware::MatchableMiddleware;
2use crate::{ErrorMiddleware, Middleware, Request, Response};
3use hyper::{http::StatusCode, Body};
4
5struct Chain<'a, T> {
6    middleware: &'a Vec<Middleware<T>>,
7    error_middleware: &'a Vec<ErrorMiddleware<T>>,
8}
9
10#[derive(PartialEq)]
11enum NextFunctionResult {
12    None,
13    Success,
14    Failure(String),
15}
16
17impl<'a, T> Chain<'a, T> {
18    pub fn new(
19        middleware: &'a Vec<Middleware<T>>,
20        error_middleware: &'a Vec<ErrorMiddleware<T>>,
21    ) -> Chain<'a, T> {
22        Chain {
23            middleware,
24            error_middleware,
25        }
26    }
27
28    pub fn run(&mut self, req: &mut Request<T>, res: &mut Response) {
29        let matching_middleware: Vec<&Middleware<T>> = self
30            .middleware
31            .into_iter()
32            .filter(|m| m.is_match(req))
33            .collect();
34
35        if matching_middleware.len() > 0 {
36            self.handle_success(matching_middleware, req, res);
37        } else {
38            self.handle_error("Not found".to_string(), req, res, StatusCode::NOT_FOUND);
39        }
40    }
41
42    fn handle_success(
43        &self,
44        matching_middleware: Vec<&Middleware<T>>,
45        req: &mut Request<T>,
46        res: &mut Response,
47    ) {
48        for middleware in matching_middleware.iter() {
49            let mut next_function_result = NextFunctionResult::None;
50
51            let mut next = |result: Result<(), String>| {
52                if let Err(err) = result {
53                    next_function_result = NextFunctionResult::Failure(err)
54                } else {
55                    next_function_result = NextFunctionResult::Success;
56                }
57            };
58
59            req.set_base_url(middleware.base_url);
60            middleware.invoke(req, res, &mut next);
61
62            match next_function_result {
63                NextFunctionResult::Success => (),
64                NextFunctionResult::Failure(err) => {
65                    self.handle_error(err, req, res, StatusCode::INTERNAL_SERVER_ERROR)
66                }
67                NextFunctionResult::None => {
68                    // TODO: Find a better way to handle this.
69                    if !res.ended {
70                        panic!("next function never called.")
71                    }
72                }
73            }
74        }
75    }
76
77    fn handle_error(
78        &self,
79        error: String,
80        req: &mut Request<T>,
81        res: &mut Response,
82        fallback_status_code: StatusCode,
83    ) {
84        let mut error = error;
85        let matching_error_middleware: Vec<&ErrorMiddleware<T>> = self
86            .error_middleware
87            .into_iter()
88            .filter(|m| m.is_match(req))
89            .collect();
90
91        res.status(fallback_status_code);
92
93        if matching_error_middleware.len() > 0 {
94            for middleware in matching_error_middleware.iter() {
95                let mut next_function_result = NextFunctionResult::None;
96
97                let mut next = |result: Result<(), String>| {
98                    if let Err(err) = result {
99                        next_function_result = NextFunctionResult::Failure(err)
100                    } else {
101                        next_function_result = NextFunctionResult::Success;
102                    }
103                };
104
105                req.set_base_url(middleware.base_url);
106                middleware.invoke(&error, req, res, &mut next);
107
108                match next_function_result {
109                    // TODO: Find a better way to handle this.
110                    NextFunctionResult::Success => {
111                        panic!("next function can not be called without an error in use_err");
112                    }
113                    NextFunctionResult::Failure(new_error) => {
114                        error = new_error;
115                    }
116                    NextFunctionResult::None => {
117                        // TODO: Find a better way to handle this.
118                        if !res.ended {
119                            panic!("next function never called.")
120                        }
121                    }
122                }
123            }
124        } else {
125            res.end();
126        }
127    }
128}
129
130pub async fn run<T>(
131    _req: hyper::Request<Body>,
132    middleware: &Vec<Middleware<T>>,
133    error_middleware: &Vec<ErrorMiddleware<T>>,
134    app_locals: &Option<T>,
135) -> hyper::Response<Body> {
136    let mut req = Request::from(_req);
137    req.with_app_locals(app_locals);
138    let mut res = Response::new();
139
140    let mut chain = Chain::new(middleware, error_middleware);
141    chain.run(&mut req, &mut res);
142
143    res.into()
144}