aero/
application.rs

1// use crate::httpresponse::HttpResponse;
2use super::request::HttpRequest;
3use super::response::HttpResponse;
4use super::router::Router;
5use serde::{Deserialize, Serialize};
6
7use std::error::Error;
8use std::sync::{Arc, Mutex};
9use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
10use tokio::net::TcpListener;
11
12#[derive(Debug, Clone)]
13pub struct Context<'a> {
14    pub req: &'a HttpRequest,
15    pub res: &'a HttpResponse<'a>,
16    pub body: String,
17    pub content_type: String,
18}
19
20pub type Next<'a> = &'a mut dyn FnMut(&mut Context);
21
22impl<'a> Context<'a> {
23    pub fn send_text(&mut self, content: &'a str) {
24        self.body = content.to_string();
25        self.content_type = "text/html".to_string()
26    }
27    pub fn send_json(&mut self, content: impl Serialize) {
28        let xs = serde_json::to_string(&content).unwrap();
29        self.body = xs;
30        self.content_type = "application/json".to_string()
31    }
32}
33
34#[derive(Clone)]
35pub struct Handler {
36    pub path: String,
37    pub method: String,
38    pub func: fn(&mut Context, &mut dyn FnMut(&mut Context)),
39}
40
41#[derive(Clone)]
42pub struct Aero<'a> {
43    pub layers: Vec<Handler>,
44    pub socket_addr: &'a str,
45}
46
47impl<'a> Aero<'a> {
48    pub fn new(port: &'a str) -> Self {
49        Aero {
50            layers: vec![],
51            socket_addr: port,
52        }
53    }
54
55    pub async fn run(self) -> Result<(), Box<dyn Error>> {
56        let listener = TcpListener::bind(self.socket_addr).await?;
57        let layers = Arc::new(self.layers);
58
59        loop {
60            // Asynchronously wait for an inbound socket.
61            let (mut socket, _) = listener.accept().await?;
62            let cop = layers.clone();
63
64            tokio::spawn(async move {
65                let mut buf = [0; 1024];
66
67                loop {
68                    let n = socket
69                        .read(&mut buf)
70                        .await
71                        .expect("failed to read data from socket");
72
73                    if n == 0 {
74                        return;
75                    }
76
77                    let req: HttpRequest = String::from_utf8(buf.to_vec()).unwrap().into();
78                    // println!("{},{}", req.method, req.path);
79                    let mut handlers = vec![];
80                    for layer in cop.to_vec() {
81                        // println!("{},{}", req.path, elem.path);
82                        if req.path.starts_with(layer.path.as_str()) {
83                            // println!("{},{}", req.method, elem.method);
84                            if req.method == layer.method || layer.method == "ALL" {
85                                handlers.push(layer.func)
86                            }
87                        }
88                    }
89
90                    // println!("{}", handlers.len());
91                    let mut handler = compose(handlers, 0);
92                    let res: HttpResponse = HttpResponse::new("200", None, "", Some("OK".into()));
93                    let ctx = &mut Context {
94                        req: &req,
95                        res: &res,
96                        body: "".to_string(),
97                        content_type: "".to_string(),
98                    };
99
100                    handler(ctx, &mut |ctx| {});
101
102                    let result = ctx.body.as_str();
103                    let content_type = ctx.content_type.as_str();
104                    // println!("------{} out", result);
105                    if result == "" {
106                        let res = HttpResponse::new("404", None, "", Some("Not Found".into()));
107                        socket
108                            .write_all(String::from(res).as_bytes())
109                            .await
110                            .expect("failed to write data to socket");
111                    } else {
112                        let res = HttpResponse::new("200", None, content_type, Some(result.into()));
113                        socket
114                            .write_all(String::from(res).as_bytes())
115                            .await
116                            .expect("failed to write data to socket");
117                    }
118                }
119            });
120        }
121    }
122
123    pub fn get(&mut self, path: &'a str, func: fn(&mut Context, &mut dyn FnMut(&mut Context))) {
124        &self.layers.push(Handler {
125            method: "GET".to_string(),
126            path: path.to_string(),
127            func: func,
128        });
129    }
130
131    pub fn post(&mut self, path: &'a str, func: fn(&mut Context, &mut dyn FnMut(&mut Context))) {
132        &self.layers.push(Handler {
133            method: "POST".to_string(),
134            path: path.to_string(),
135            func: func,
136        });
137    }
138
139    pub fn hold(&mut self, path: &'a str, func: fn(&mut Context, &mut dyn FnMut(&mut Context))) {
140        &self.layers.push(Handler {
141            method: "ALL".to_string(),
142            path: path.to_string(),
143            func: func,
144        });
145    }
146
147    pub fn mount(&mut self, router: Router) {
148        // add router handler
149        for x in router.layers {
150            &self.layers.push(Handler {
151                method: x.method,
152                path: format!("{}{}", router.prefix, x.path),
153                func: x.func,
154            });
155        }
156    }
157}
158
159type MidwareFn = fn(&mut Context, &mut dyn FnMut(&mut Context));
160
161fn compose(
162    midwares: Vec<MidwareFn>,
163    i: usize,
164) -> impl FnMut(&mut Context, &mut dyn FnMut(&mut Context)) {
165    move |ctx: &mut Context, next: &mut dyn FnMut(&mut Context)| {
166        let len = midwares.len();
167        if len == 0 {
168            return next(ctx);
169        }
170        if i >= len - 1 {
171            return midwares[i](ctx, next);
172        }
173        midwares[i](ctx, &mut |ctx| {
174            compose(midwares.clone(), i + 1)(ctx, next);
175        });
176    }
177}