http_server_rs/
httpserver.rs1use std::{collections::BTreeMap, io::Error, net::{TcpListener, TcpStream, ToSocketAddrs}, sync::{Arc, Mutex}};
2
3use crate::{executor::Executor, httpreader::HttpReader};
4
5
6pub struct HttpServer<T : Executor>
7{
8 listener : Option<TcpListener>,
9 handler : BTreeMap<String, HttpHandlerWrap>,
10 started : bool,
11 executor : T,
12 max_client_timeout_ms : u64,
13}
14
15impl<T : Executor> HttpServer<T>
16
17{
18
19 pub fn new(max_client_timeout_ms : u64, executor : T) -> Self {
20 let server : HttpServer<T> = HttpServer {
21 listener : Option::None,
22 handler : BTreeMap::new(),
23 started : false,
24 executor,
25 max_client_timeout_ms,
26 };
27 return server;
28 }
29
30 pub fn add_endpoint<F>(&mut self, path : &str, handler : F)
31 where F : Sized + FnMut(HttpReader) + Send + Sync + 'static {
32 let value = Arc::new(Mutex::new(handler));
33 self.handler.insert(String::from(path), value);
34 }
35
36 pub fn init_listener<SA : ToSocketAddrs>(&mut self, socket_address : SA) -> Result<TcpListener, Error> {
37 let listener = TcpListener::bind(socket_address);
38 if listener.is_err() {
39 return Result::Err(listener.unwrap_err());
40 } else {
41 let l = listener.unwrap();
42 let result : Result<TcpListener, Error> = Result::Ok(l.try_clone().unwrap());
43 self.listener = Option::Some(l);
44 return result;
45 }
46 }
47
48 pub fn start<SA : ToSocketAddrs>(&mut self, socket_address : SA) -> Result<bool, Error> {
49 if self.listener.is_none() {
50 let init = self.init_listener(socket_address);
51 if init.is_err() {
52 return Result::Err(init.unwrap_err());
53 }
54 }
55
56 if !self.started {
57 self.started = true;
58 let listener_copy : &TcpListener = self.listener.as_ref().unwrap();
59 let max_client_timeout_ms = self.max_client_timeout_ms;
60 let map_copy = self.handler.clone();
61 for tcpstream in listener_copy.incoming() {
62 let map_copy_copy = map_copy.clone();
63 self.executor.execute_mut(move || {
64 if tcpstream.is_ok() {
65 HttpServer::<T>::handle_connection(tcpstream.unwrap(), map_copy_copy, max_client_timeout_ms);
66 }
67 });
68 }
69 }
70
71 return Result::Ok(true);
72 }
73
74 fn handle_connection(tcpstream : TcpStream, mut handler_map : BTreeMap<String, HttpHandlerWrap>, max_client_timeout_ms : u64) {
75 let pre_check_http_reader = HttpReader::new(tcpstream, max_client_timeout_ms);
76 if pre_check_http_reader.is_ok() {
77 let http_reader = pre_check_http_reader.unwrap();
78 let handler = handler_map.get_mut(&http_reader.get_request_path());
79 if handler.is_none() {
80 let fallback_key = &String::from("*");
81 let fallback = handler_map.get_mut(fallback_key);
82 if fallback.is_some() {
83 let mut unwrapped = fallback.unwrap().lock().unwrap();
84 (unwrapped)(http_reader);
85 } else {
86 http_reader.respond_404();
87 }
88 } else {
89 let mut unwrapped = handler.unwrap().lock().unwrap();
90 (unwrapped)(http_reader);
91 }
92 }
93 }
94
95}
96
97type HttpHandler = dyn FnMut(HttpReader) + Send + Sync;
98type HttpHandlerWrap = Arc<Mutex<HttpHandler>>;