1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use crate::{Request, Response, StatusCode};
use std::fmt::{Debug, Formatter};
use tokio::{
io::AsyncWriteExt,
net::{TcpListener, TcpStream},
};
pub mod route_handler;
pub mod testing;
use route_handler::{HandlerResult, RouteHandler};
#[doc = include_str!("../docs/core/server.md")]
pub struct Server {
route_handlers: Vec<Box<dyn RouteHandler + Send>>,
address: String,
}
impl Server {
/// Creates a new server instance
///
/// # Example
///
/// ```no_run
/// use krustie::Server;
///
/// let server = Server::create();
///
/// server.listen(8080);
/// ```
pub fn create() -> Self {
Self {
route_handlers: Vec::new(),
address: String::from(""),
}
}
/// Adds a middleware or a router to the server
///
/// `Middleware` are functions that are executed before or after the request is handled by the server.
/// They can be used to modify the request or response.
///
/// `Router` is a collection of routes that can be used to handle requests.
///
/// # Example
///
/// ```rust
/// use krustie::{ Server, Router, Response, StatusCode, Middleware, middleware::gzip::GzipEncoder };
///
/// let mut server = Server::create();
/// let mut router = Router::new();
///
/// server.use_handler(router);
/// server.use_handler(GzipEncoder);
/// ```
pub fn use_handler(&mut self, handler: impl RouteHandler + 'static) {
self.route_handlers.push(Box::new(handler));
}
/// Listens for incoming requests on the specified IP and port
///
/// # Example
///
/// ```no_run
/// use krustie::Server;
///
/// let mut server = Server::create();
///
/// server.listen(8080);
/// ```
pub async fn listen(self, port: u16) {
Listener::listen(port, self).await;
}
/// Handles data stream comes from TcpListener
///
/// Use this if you to use your own listener for the server
///
/// # Example
///
/// ```no_run
/// use krustie::Server;
/// use tokio::net::TcpListener;
///
/// #[tokio::main]
/// async fn main() {
/// let mut server = Server::create();
/// let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
///
/// for (mut stream, _) in listener.accept().await {
/// server.handle_stream(&mut stream).await;
/// }
/// }
///
/// ```
pub async fn handle_stream(&mut self, stream: &mut TcpStream) {
let mut response = Response::default();
let request_result = Request::parse(stream).await;
match request_result {
Ok(request) => {
for handler in &mut self.route_handlers {
let result = handler.handle(&request, &mut response);
if result == HandlerResult::End {
break;
}
}
}
Err(err) => {
response
.status(StatusCode::BadRequest)
.debug_msg(&err.to_string());
}
}
let response_stream: Vec<u8> = response.into();
match stream.write_all(&response_stream).await {
Ok(_) => {}
Err(e) => {
eprintln!("error: {}", e);
}
}
}
}
impl Clone for Server {
fn clone(&self) -> Self {
Self {
route_handlers: self.route_handlers.clone(),
address: self.address.clone(),
}
}
}
impl Debug for Server {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "Server {{ Address: {} }}", self.address)
}
}
#[derive(Debug)]
struct Listener {}
impl Listener {
async fn listen(port: u16, handler: Server) {
let address = format!("127.0.0.1:{}", port);
let listener = TcpListener::bind(address).await.unwrap_or_else(|err| {
panic!("Error while binding to port {}: {}", port, err);
});
println!("Listening on http://localhost:{port}");
while let Ok((mut stream_result, _)) = listener.accept().await {
let mut handler = handler.clone();
tokio::spawn(async move {
dbg!(
"Handling stream from {}",
stream_result.peer_addr().unwrap()
);
handler.handle_stream(&mut stream_result).await;
});
}
}
}