1pub mod http;
2
3use http::{Method, Request, Response};
4use std::fmt::Debug;
5use std::io::Read;
6use std::io::Write;
7use std::net::TcpListener;
8
9pub struct Express {
10 mounts: Vec<Mount>,
11}
12
13macro_rules! define_method {
26 ($func_name:ident, $method:expr) => {
27 pub fn $func_name<F: 'static>(&mut self, path: &str, callback: F) -> &mut Self
28 where
29 F: FnMut(&Request, &mut Response),
30 Self: Sized,
31 {
32 let mount = Mount {
33 method: $method,
34 path: path.to_string(),
35 callback: Box::new(callback),
36 };
37 self.mounts.push(mount);
38 self
39 }
40 };
41}
42
43impl Express {
48 pub fn new() -> Self {
49 Express { mounts: Vec::new() }
50 }
51
52 define_method!(get, Method::GET);
53 define_method!(post, Method::POST);
54 define_method!(put, Method::PUT);
55 define_method!(delete, Method::DELETE);
56 define_method!(patch, Method::PATCH);
57
58 pub fn listen(&mut self, port: u16) {
65 if port == 0 {
66 panic!("Port must be between 1-65535")
67 }
68
69 let address = format!("0.0.0.0:{}", port);
70 let listener = TcpListener::bind(address)
71 .unwrap_or_else(|_| panic!("Could not bind to port {}", port));
72
73 for stream in listener.incoming() {
74 if let Ok(mut stream) = stream {
75 let mut buffer = [0; 1024];
76 if let Err(e) = stream.read(&mut buffer) {
77 println!("Could not read to stream: {}", e)
78 }
79 let request =
80 Request::from_string(String::from_utf8_lossy(&buffer[..]).to_string());
81
82 let mut response = Response::new();
83 if let Ok(request) = request {
84 self.mounts
85 .iter_mut()
86 .filter(|mount| mount.matches(&request))
87 .for_each(|mount| (mount.callback)(&request, &mut response));
88
89 let response_text = format!("HTTP/1.1 {} OK\r\n\r\n", response.status);
90 if let Err(e) = stream.write(response_text.as_bytes()) {
91 println!("Could not write to response stream: {}", e)
92 }
93 } else {
94 if let Err(e) = stream.write(b"HTTP/1.1 400 Bad Request\r\n\r\n") {
95 println!("Could not write to response stream: {}", e)
96 }
97 println!("Request could not be handled");
98 }
99
100 if let Err(e) = stream.write(response.stream.as_bytes()) {
101 println!("Could not write to response stream: {}", e)
102 }
103
104 if let Err(e) = stream.flush() {
105 println!("Could not flush response stream: {}", e)
106 }
107 }
108 }
109 }
110}
111
112impl Default for Express {
113 fn default() -> Self {
114 Express::new()
115 }
116}
117
118pub struct Mount {
120 pub method: Method,
121 pub path: String,
122 pub callback: Box<dyn FnMut(&Request, &mut Response)>,
123}
124
125impl Debug for Mount {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
127 f.debug_struct("Mount")
128 .field("method", &self.method)
129 .field("path", &self.path)
130 .finish()
131 }
132}
133
134impl Mount {
135 fn matches(&self, other: &Request) -> bool {
136 self.method == other.method && self.path == other.path
137 }
138}