mini_server/
lib.rs

1use std::collections::HashMap;
2use std::io::{BufRead, Read, Write};
3use std::iter::zip;
4use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream};
5use std::sync::Arc;
6use std::sync::atomic::{AtomicBool, Ordering};
7
8#[macro_use]
9mod macros;
10pub mod worker;
11
12/// `CRLF` represents the Carriage Return (CR) and Line Feed (LF)
13/// characters combined ("\r\n"). It is commonly used as the
14/// end-of-line sequence in HTTP requests and responses.
15///
16/// `CRLF` is utilized to signify the end of a line in HTTP messages,
17/// ensuring compatibility with the HTTP protocol.
18///
19/// ```rust
20/// use mini_server::CRLF;
21///
22/// let http_line = format!("--- boundry{}{}", CRLF, CRLF);
23/// ```
24pub const CRLF: &str = "\r\n";
25
26/// `MAX_BUFFER` defines the maximum size, in bytes, for a request
27/// in your web server. Requests exceeding this size may be rejected or
28/// handled differently based on your server's implementation.
29///
30/// ## Determining the appropriate buffer size
31///
32/// Determining an appropriate value for `MAX_BUFFER` depends on several
33/// factors, including the typical size of requests the web server
34/// expects to handle, the available system resources, and the desired
35/// trade-off between memory usage and potential denial-of-service (DoS)
36/// protection.
37///
38/// Here are some considerations:
39///
40/// 1. Resource Constraints:
41///     Consider the available system memory. Setting MAX_BUFFER too high
42///     might lead to excessive memory usage, especially if the
43///     server handles a large number of concurrent requests.
44///
45/// 2. Denial-of-Service (DoS) Protection:
46///     A smaller MAX_BUFFER can provide a level of protection against
47///     certain types of DoS attacks that involve sending large,
48///     resource-consuming requests. However, it's essential to strike
49///     a balance to avoid false positives or impacting legitimate
50///     requests.
51///
52/// ## Note
53/// > The max_buffer is configurable when configurating a new server instance
54/// > It is only used in the [TcpServer]
55pub const MAX_BUFFER: usize = 16384;
56
57/// The `HTTPRequest` struct represents an HTTP request received by
58/// the web server. It encapsulates various components of an HTTP request,
59/// including the HTTP method, request path, headers, and body.
60#[derive(Debug, Clone)]
61pub struct HTTPRequest {
62    /// The HTTP method used in the request (e.g., GET, POST).
63    pub method: HTTPMethod,
64    /// The decoded path portion of the request URL.
65    pub path: String,
66    /// The raw, percent-encoded path from the request URL.
67    pub raw_path: String,
68    /// A collection of URL parameters parsed from the request.
69    pub params: URLSearchParams,
70    /// The version of the HTTP protocol used in the request (e.g., "1.1").
71    pub http_version: String,
72    /// A collection of HTTP headers included in the request.
73    pub headers: Headers,
74    /// The body of the HTTP request. (Note: Consider changing body to a sequence of bytes (***`Vec<u8>`***)
75    /// for more flexibility and efficiency.)
76    pub body: Vec<u8>,
77}
78
79impl Default for HTTPRequest {
80    fn default() -> Self {
81        Self {
82            method: HTTPMethod::GET,
83            path: String::from("/"),
84            raw_path: String::new(),
85            params: HashMap::new(),
86            http_version: String::from("1.1"),
87            headers: HashMap::new(),
88            body: Vec::new(),
89        }
90    }
91}
92
93/// The `URLSearchParams` type alias represents a collection of URL parameters parsed from an HTTP request's
94/// query string. It is implemented as a HashMap<String, String> where keys are parameter names, and values
95/// are parameter values.
96pub type URLSearchParams = HashMap<String, String>;
97
98/// The `Headers` type alias represents a collection of HTTP headers in key-value pairs. It is implemented
99/// as a HashMap<String, String>, where keys are header names, and values are header values.
100pub type Headers = HashMap<String, String>;
101
102/// The parse_path function takes a string representing an HTTP request path and extracts the path and URL
103/// parameters (if any) from it. It returns a tuple containing the path and a URLSearchParams
104/// `(HashMap<String, String>)` representing the parsed URL parameters.
105fn parse_path(data: &str) -> (String, URLSearchParams) {
106    let split_data = data.split_once('?');
107    if split_data.is_none() {
108        (data.into(), HashMap::new())
109    } else {
110        let (ph, pr) = split_data.unwrap();
111        let params: URLSearchParams = pr
112            .split('&')
113            .filter_map(|param| {
114                let mut parts = param.split('=');
115                let key = parts.next()?.to_string();
116                let value = parts.next()?.to_string();
117                Some((key, value))
118            })
119            .collect();
120
121        (ph.to_string(), params)
122    }
123}
124
125fn get_method(raw: Option<&str>) -> HTTPMethod {
126    if let Some(raw) = raw {
127        match raw {
128            "GET" => HTTPMethod::GET,
129            "HEAD" => HTTPMethod::HEAD,
130            "POST" => HTTPMethod::POST,
131            "PUT" => HTTPMethod::PUT,
132            "DELETE" => HTTPMethod::DELETE,
133            "CONNECT" => HTTPMethod::CONNECT,
134            "OPTIONS" => HTTPMethod::OPTIONS,
135            "TRACE" => HTTPMethod::TRACE,
136            "PATCH" => HTTPMethod::PATCH,
137            _ => HTTPMethod::GET,
138        }
139    } else {
140        HTTPMethod::GET
141    }
142}
143
144fn get_version(v: Option<u8>) -> String {
145    if let Some(v) = v {
146        if v == 1 {
147            return "1.1".into();
148        } else {
149            return "1.2".into();
150        }
151    } else {
152        "1.1".into()
153    }
154}
155
156/// The `HTTPResponse` struct represents an HTTP response that the web server can send to clients.
157/// It encapsulates various components of an HTTP response, including the response body, headers,
158/// status code, status text, and the HTTP version.
159///
160/// ```rust
161/// use mini_server::{HTTPResponse, Headers};
162///
163/// fn create_http_response() -> HTTPResponse {
164///     let mut headers = Headers::new();
165///     headers.insert("Content-Type".into(), "text/plain".into());
166///
167///     HTTPResponse {
168///         body: b"Hello, World!".to_vec(),
169///         headers,
170///         status: 200,
171///         status_text: "OK".to_string(),
172///         http_version: "1.1".to_string(),
173///     }
174/// }
175/// ```
176#[derive(Debug, Clone)]
177pub struct HTTPResponse {
178    /// The response body as a vector of bytes.
179    pub body: Vec<u8>,
180    /// A collection of HTTP headers included in the response.
181    pub headers: Headers,
182    ///  The HTTP status code indicating the outcome of the request.
183    pub status: u16,
184    /// The human-readable status text associated with the status code.
185    pub status_text: String,
186    /// The version of the HTTP protocol used for the response.
187    pub http_version: String,
188}
189
190fn default_headers() -> Headers {
191    let mut h = Headers::new();
192    h.insert("Server".into(), "miniserver".into());
193    h
194}
195
196impl Default for HTTPResponse {
197    fn default() -> Self {
198        HTTPResponse {
199            body: Vec::new(),
200            headers: default_headers(),
201            status: 200,
202            status_text: String::from("OK"),
203            http_version: String::from("1.1"),
204        }
205    }
206}
207
208response_from_for!(&[u8]);
209response_from_for!(&str);
210response_from_for!(Vec<u8>);
211response_from_for!(String);
212
213impl HTTPResponse {
214    /// Get a new HTTPResponse struct
215    pub fn new() -> Self {
216        HTTPResponse::default()
217    }
218
219    /// Allows updating the body of an HTTPResponse instance
220    /// with a new vector of bytes (`Vec<u8>`). Additionally, it automatically
221    /// updates the "Content-Length" header to reflect the length of the new body.
222    pub fn set_body(&mut self, body: Vec<u8>) {
223        self.body = body;
224        self.headers
225            .insert("Content-Length".to_string(), self.body.len().to_string());
226    }
227
228    /// Update the headers of an HTTPResponse instance with a new set of headers
229    /// provided as a Headers collection.
230    pub fn set_headers(&mut self, headers: Headers) {
231        for (key, value) in headers {
232            self.headers.insert(key, value);
233        }
234    }
235
236    /// Insert/Update the `HTTPResponse` header
237    pub fn set_header(&mut self, k: &str, v: &str) {
238        self.headers.insert(k.into(), v.into());
239    }
240
241    fn apply_status(&mut self, status: u16, text: &str) {
242        self.status = status;
243        self.status_text = text.to_string();
244    }
245
246    /// The set_status method allows setting the HTTP status code for an HTTPResponse instance.
247    /// It updates both the numeric status code (status) and the associated human-readable
248    /// status text.
249    pub fn set_status(&mut self, status: u16) {
250        match status {
251            100 => self.apply_status(status, "Continue"),
252            101 => self.apply_status(status, "Switching Protocols"),
253            102 => self.apply_status(status, "Processing"),
254            103 => self.apply_status(status, "Early Hints"),
255
256            200 => self.apply_status(status, "OK"),
257            201 => self.apply_status(status, "Created"),
258            202 => self.apply_status(status, "Accepted"),
259            203 => self.apply_status(status, "Non-Authoritative Information"),
260            204 => self.apply_status(status, "No Content"),
261            205 => self.apply_status(status, "Reset Content"),
262            206 => self.apply_status(status, "Partial Content"),
263            207 => self.apply_status(status, "Multi-Status"),
264            208 => self.apply_status(status, "Already Reported"),
265            226 => self.apply_status(status, "IM Used"),
266
267            300 => self.apply_status(status, "Multiple Choices"),
268            301 => self.apply_status(status, "Moved Permanently"),
269            302 => self.apply_status(status, "Found"),
270            303 => self.apply_status(status, "See Other"),
271            304 => self.apply_status(status, "Not Modified"),
272            305 => self.apply_status(status, "Use Proxy"),
273            306 => self.apply_status(status, "Switch Proxy"),
274            307 => self.apply_status(status, "Temporary Redirect"),
275            308 => self.apply_status(status, "Permanent Redirect"),
276
277            400 => self.apply_status(status, "Bad Request"),
278            401 => self.apply_status(status, "Unauthorized"),
279            402 => self.apply_status(status, "Payment Required"),
280            403 => self.apply_status(status, "Forbidden"),
281            404 => self.apply_status(status, "Not Found"),
282            405 => self.apply_status(status, "Method Not Allowed"),
283            406 => self.apply_status(status, "Not Acceptable"),
284            407 => self.apply_status(status, "Proxy Authentication Required"),
285            408 => self.apply_status(status, "Request Timeout"),
286            409 => self.apply_status(status, "Conflict"),
287            410 => self.apply_status(status, "Gone"),
288            411 => self.apply_status(status, "Length Required"),
289            412 => self.apply_status(status, "Precondition Failed"),
290            413 => self.apply_status(status, "Payload Too Large"),
291            414 => self.apply_status(status, "URI Too Long"),
292            415 => self.apply_status(status, "Unsupported Media Type"),
293            416 => self.apply_status(status, "Range Not Satisfiable"),
294            417 => self.apply_status(status, "Expectation Failed"),
295            418 => self.apply_status(status, "I'm a teapot"),
296            421 => self.apply_status(status, "Misdirected Request"),
297            422 => self.apply_status(status, "Unprocessable Entity"),
298            423 => self.apply_status(status, "Locked"),
299            424 => self.apply_status(status, "Failed Dependency"),
300            425 => self.apply_status(status, "Too Early"),
301            426 => self.apply_status(status, "Upgrade Required"),
302            428 => self.apply_status(status, "Precondition Required"),
303            429 => self.apply_status(status, "Too Many Requests"),
304            431 => self.apply_status(status, "Request Header Fields Too Large"),
305            451 => self.apply_status(status, "Unavailable For Legal Reasons"),
306
307            500 => self.apply_status(status, "Internal Server Error"),
308            501 => self.apply_status(status, "Not Implemented"),
309            502 => self.apply_status(status, "Bad Gateway"),
310            503 => self.apply_status(status, "Service Unavailable"),
311            504 => self.apply_status(status, "Gateway Timeout"),
312            505 => self.apply_status(status, "HTTP Version Not Supported"),
313            506 => self.apply_status(status, "Variant Also Negotiates"),
314            507 => self.apply_status(status, "Insufficient Storage"),
315            508 => self.apply_status(status, "Loop Detected"),
316            510 => self.apply_status(status, "Not Extended"),
317            511 => self.apply_status(status, "Network Authentication Required"),
318
319            _ => self.apply_status(500, "Internal Server Error"),
320        }
321    }
322
323    /// Set the HTTPResponse version (e.g. '1.1')
324    pub fn set_version(&mut self, version: String) {
325        self.http_version = version;
326    }
327
328    fn format_header(&self) -> String {
329        let mut headers = String::new();
330        for (key, value) in &self.headers {
331            headers.push_str(format!("{}: {}{}", key, value, CRLF).as_str());
332        }
333        headers
334    }
335
336    /// The raw method generates the raw representation of an HTTP response, including
337    /// the status line, headers, and body. It returns the
338    /// formatted HTTP response as a vector of bytes (`Vec<u8>`).
339    /// ```rust
340    /// use mini_server::HTTPResponse;
341    /// fn get_raw_response(response: &mut HTTPResponse) -> Vec<u8> {
342    ///     let raw_response = response.raw();
343    ///
344    ///     // Accessing the raw HTTP response
345    ///     println!("Raw Response: {:?}", raw_response);
346    ///     raw_response
347    /// }
348    /// ```
349    pub fn raw(&mut self) -> Vec<u8> {
350        let mut bytes = format!(
351            "HTTP/{version} {status} {status_text}{CRLF}{headers}{CRLF}",
352            version = self.http_version,
353            status = self.status,
354            status_text = self.status_text,
355            CRLF = CRLF,
356            headers = self.format_header(),
357        )
358        .as_bytes()
359        .to_vec();
360
361        bytes.extend(self.body.iter());
362
363        bytes
364    }
365}
366
367/// Get the value of a path dynamic variable
368/// ```rust
369/// use mini_server::*;
370/// let mut app = HTTPServer::new("localhost:4221");
371///
372/// app.get("/hello/@name/#age", |_, exprs| {
373///     let name = expand!(exprs, "name", PathExpr::String);
374///     let age = expand!(exprs, "age", PathExpr::Number);
375///
376///     format!("Hello {name}, you are {age}!").into()
377/// });
378/// ```
379#[macro_export]
380macro_rules! expand {
381    ($exprs: expr, $name: expr, $against: path) => {
382        match $exprs.get(&String::from($name)).unwrap() {
383            $against(value) => value,
384            _ => unreachable!(),
385        }
386    };
387}
388
389/// An hash map of `PathExpr`
390pub type PathMap = HashMap<String, PathExpr>;
391
392/// RequestHandler type is a function type that defines the signature for handling HTTP requests.
393/// It takes `HTTPRequest` and `HashMap<String, PathExpr>` as a parameter and returns an `HTTPResponse`
394pub struct RequestHandler(
395    Arc<Box<dyn Fn(HTTPRequest, PathMap) -> HTTPResponse + Send + Sync + 'static>>,
396);
397
398impl Clone for RequestHandler {
399    fn clone(&self) -> Self {
400        Self(self.0.clone())
401    }
402}
403
404/// EventHandler type is a function type that defines the signature for handling events triggered
405/// by HTTP requests. It takes references to an `HTTPRequest` and a mutable `HTTPResponse` as parameters.
406pub struct EventHandler(Arc<Box<dyn Fn(&HTTPRequest, &mut HTTPResponse) + Send + Sync + 'static>>);
407
408impl Clone for EventHandler {
409    fn clone(&self) -> Self {
410        Self(self.0.clone())
411    }
412}
413
414pub struct SimpleEventHandler(
415    Arc<Box<dyn Fn(&mut TcpStream, Request) -> Option<Response> + Send + Sync + 'static>>,
416);
417
418impl Clone for SimpleEventHandler {
419    fn clone(&self) -> Self {
420        Self(self.0.clone())
421    }
422}
423
424/// The SoftEventHandler type is a function type that defines the signature for handling soft events,
425/// typically without specific request or response parameters.
426pub struct SoftEventHandler(Arc<Box<dyn Fn() + Send + Sync + 'static>>);
427
428impl Clone for SoftEventHandler {
429    fn clone(&self) -> Self {
430        Self(self.0.clone())
431    }
432}
433
434pub struct ErrorEventHandler(Arc<Box<dyn Fn(RunError) + Send + Sync + 'static>>);
435
436impl Clone for ErrorEventHandler {
437    fn clone(&self) -> Self {
438        Self(self.0.clone())
439    }
440}
441/// The HTTPMethod enum represents the HTTP methods that can be used in HTTP requests.
442/// Each variant corresponds to a standard HTTP method.
443#[derive(Debug, PartialEq, Clone)]
444pub enum HTTPMethod {
445    /// Used to establish a network connection to a resource.
446    CONNECT,
447    /// Requests that a resource be removed.
448    DELETE,
449    /// Requests a representation of a resource.
450    GET,
451    /// Requests the headers of a resource without the body.
452    HEAD,
453    /// Describes the communication options for the target resource.
454    OPTIONS,
455    /// Applies partial modifications to a resource.
456    PATCH,
457    /// Submits data to be processed to a specified resource.
458    POST,
459    /// Updates a resource or creates a new resource if it does not exist.
460    PUT,
461    /// Performs a message loop-back test along the path to the target resource.
462    TRACE,
463}
464
465/// A path expression represent a dynamic variable of a path
466#[derive(Debug, Clone)]
467pub enum PathExpr {
468    String(String),
469    Number(i32),
470}
471
472pub struct Path {
473    pub expr: String,
474    pub handler: RequestHandler,
475    pub method: HTTPMethod,
476}
477
478impl Clone for Path {
479    fn clone(&self) -> Self {
480        Self {
481            expr: self.expr.clone(),
482            handler: self.handler.clone(),
483            method: self.method.clone(),
484        }
485    }
486}
487
488impl PartialEq for Path {
489    fn eq(&self, other: &Self) -> bool {
490        self.r#match(other.expr.clone()) && self.method == other.method
491    }
492}
493
494pub struct Listener {
495    handler: EventHandler,
496}
497
498impl Clone for Listener {
499    fn clone(&self) -> Self {
500        Self {
501            handler: self.handler.clone(),
502        }
503    }
504}
505
506pub struct SoftListener {
507    handler: SoftEventHandler,
508}
509
510impl Clone for SoftListener {
511    fn clone(&self) -> Self {
512        Self {
513            handler: self.handler.clone(),
514        }
515    }
516}
517
518pub struct ErrorListener {
519    handler: ErrorEventHandler,
520}
521
522impl Clone for ErrorListener {
523    fn clone(&self) -> Self {
524        Self {
525            handler: self.handler.clone(),
526        }
527    }
528}
529
530impl Path {
531    pub fn new<T>(expr: &str, handler: T, method: HTTPMethod) -> Self
532    where
533        T: Fn(HTTPRequest, PathMap) -> HTTPResponse + Send + Sync + 'static,
534    {
535        Path {
536            expr: expr.to_string(),
537            handler: RequestHandler(Arc::new(Box::new(handler))),
538            method,
539        }
540    }
541
542    fn parse(&self, expr: String) -> PathMap {
543        let mut exprs = PathMap::new();
544        if self.r#match(expr.clone()) {
545            let other_part: Vec<_> = expr.split('/').filter(|x| !x.is_empty()).collect();
546            let self_part: Vec<_> = self.expr.split('/').filter(|x| !x.is_empty()).collect();
547
548            for (o_chunck, s_chunck) in zip(other_part, self_part) {
549                if s_chunck.starts_with('#') {
550                    let name = s_chunck.strip_prefix('#').unwrap().to_string();
551                    let value = o_chunck.parse::<i32>().unwrap();
552                    exprs.insert(name, PathExpr::Number(value));
553                } else if s_chunck.starts_with('@') {
554                    let name = s_chunck.strip_prefix('@').unwrap().to_string();
555                    let value = o_chunck.to_string();
556                    exprs.insert(name, PathExpr::String(value));
557                } else {
558                    continue;
559                }
560            }
561        }
562
563        exprs
564    }
565
566    fn r#match(&self, expr: String) -> bool {
567        if expr == self.expr {
568            true
569        } else {
570            let other_part: Vec<_> = expr.split('/').filter(|x| !x.is_empty()).collect();
571            let self_part: Vec<_> = self.expr.split('/').filter(|x| !x.is_empty()).collect();
572
573            if other_part.len() != self_part.len() {
574                false
575            } else {
576                for (o_chunck, s_chunck) in zip(other_part, self_part) {
577                    if s_chunck.starts_with('#') {
578                        if o_chunck.parse::<i32>().is_ok() {
579                            continue;
580                        } else {
581                            return false;
582                        }
583                    } else if s_chunck.starts_with('@') {
584                        continue;
585                    } else if o_chunck != s_chunck {
586                        return false;
587                    }
588                }
589
590                true
591            }
592        }
593    }
594
595    fn handle_request(&self, request: HTTPRequest) -> HTTPResponse {
596        let exprs = self.parse(request.path.clone());
597        (self.handler.0)(request, exprs)
598    }
599}
600
601impl Listener {
602    pub fn new<T>(handler: T) -> Self
603    where
604        T: Fn(&HTTPRequest, &mut HTTPResponse) + Send + Sync + 'static,
605    {
606        Listener {
607            handler: EventHandler(Arc::new(Box::new(handler))),
608        }
609    }
610
611    pub fn notify(&self, req: &HTTPRequest, res: &mut HTTPResponse) {
612        (self.handler.0)(req, res)
613    }
614}
615
616impl SoftListener {
617    pub fn new<T>(handler: T) -> Self
618    where
619        T: Fn() + Send + Sync + 'static,
620    {
621        SoftListener {
622            handler: SoftEventHandler(Arc::new(Box::new(handler))),
623        }
624    }
625
626    pub fn notify(&self) {
627        (self.handler.0)()
628    }
629}
630
631impl ErrorListener {
632    pub fn new<T>(handler: T) -> Self
633    where
634        T: Fn(RunError) + Send + Sync + 'static,
635    {
636        Self {
637            handler: ErrorEventHandler(Arc::new(Box::new(handler))),
638        }
639    }
640
641    pub fn notify(&self, error: RunError) {
642        (self.handler.0)(error)
643    }
644}
645
646pub trait Server<U, V> {
647    fn handle_request(&self, stream: U, req: V);
648    fn run(&self);
649}
650
651/// `Vec<u8>`
652pub type Request = Vec<u8>;
653/// `Vec<u8>`
654pub type Response = Vec<u8>;
655
656/// This struct provide a simple http server
657/// that handle many of the use cases
658///
659/// ## Example
660///
661/// ```rust
662/// use mini_server::*;
663///
664/// let mut app = HTTPServer::default();
665///
666/// app.get("/", |_, _| {
667///     "Hello World!".into()
668/// });
669///
670/// ```
671///
672/// ## Path
673///
674/// The path is an expression that can contains dynamic variables.
675/// - Basic paths: `/`, `/this/is/a/path`, ...
676/// - Dynamic path: `/this/is/a/@varibale`, `/this/is/another/#variable`
677///
678/// `#` and `@` are prefixes for dynamic values. `#` for denoting numbers
679/// and `@` for strings
680pub struct HTTPServer {
681    pub addr: Vec<SocketAddr>,
682    pub paths: Vec<Path>,
683    pub listeners: Vec<Listener>,
684    pub on_ready: Option<SoftListener>,
685    pub on_shutdown: Option<SoftListener>, // TODO: Implement on_shutdown
686    pub on_error: Option<ErrorListener>,
687    pub thread_pool: worker::ThreadPool,
688    pub should_shutdown: ShutdownWrapper,
689}
690
691pub struct ShutdownWrapper(AtomicBool);
692
693impl Default for HTTPServer {
694    fn default() -> Self {
695        Self {
696            addr: vec![SocketAddr::new(
697                std::net::IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
698                4221,
699            )],
700            paths: vec![],
701            listeners: vec![],
702            on_ready: None,
703            on_shutdown: None,
704            on_error: None,
705            thread_pool: worker::ThreadPool::new(14),
706            should_shutdown: ShutdownWrapper(AtomicBool::new(false)),
707        }
708    }
709}
710
711impl Clone for HTTPServer {
712    fn clone(&self) -> Self {
713        let new_should_shutdown = self.should_shutdown.0.load(Ordering::Relaxed);
714
715        Self {
716            addr: self.addr.clone(),
717            paths: self.paths.clone(),
718            listeners: self.listeners.clone(),
719            on_ready: self.on_ready.clone(),
720            on_shutdown: self.on_shutdown.clone(),
721            on_error: self.on_error.clone(),
722            thread_pool: worker::EMPTY_POOL,
723            should_shutdown: ShutdownWrapper(AtomicBool::new(new_should_shutdown)),
724        }
725    }
726}
727
728pub enum RunError {
729    CannotBindToAddr(Vec<SocketAddr>),
730}
731
732impl std::fmt::Display for RunError {
733    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
734        match self {
735            RunError::CannotBindToAddr(addr) => {
736                write!(f, "Unable to bind to those addresses: {addr:?}")
737            }
738        }
739    }
740}
741
742impl Server<&mut TcpStream, HTTPRequest> for HTTPServer {
743    fn handle_request(&self, stream: &mut TcpStream, req: HTTPRequest) {
744        let mut handled = false;
745        for path in &self.paths {
746            if path.method == req.method && path.r#match(req.path.clone()) {
747                let mut response = path.handle_request(req.clone());
748                for listener in &self.listeners {
749                    listener.notify(&req, &mut response);
750                }
751                let _ = stream.write(response.raw().as_slice());
752                handled = true;
753                break;
754            }
755        }
756        if !handled {
757            let mut response = HTTPResponse::default();
758            response.set_status(404);
759
760            let data: String = format!(
761                "Unreachable path `{:?} - {}`. Resource NOT FOUND",
762                req.method, req.path
763            );
764
765            let data_bytes: Vec<u8> = data.into_bytes();
766            response.set_body(data_bytes);
767            for listener in &self.listeners {
768                listener.notify(&req, &mut response);
769            }
770            let _ = stream.write(response.raw().as_slice());
771        }
772    }
773
774    fn run(&self) {
775        if let Ok(listener) = TcpListener::bind(self.addr.as_slice()) {
776            if let Some(ready_fn) = &self.on_ready {
777                ready_fn.notify();
778            }
779
780            for stream in listener.incoming() {
781                match stream {
782                    Ok(stream) => {
783                        let self_clone = Arc::new(self.clone());
784                        self.thread_pool.execute(move || {
785                            let s = self_clone.clone();
786                            let mut st = stream;
787                            s.handle_connection(&mut st);
788                        });
789                    }
790                    Err(e) => {
791                        eprintln!("{e}")
792                    }
793                }
794            }
795        } else {
796            if let Some(onerror) = &self.on_error {
797                onerror.notify(RunError::CannotBindToAddr(self.addr.clone()));
798            }
799        }
800    }
801}
802
803macro_rules! define_all_route_methods {
804    ($($name:ident => $method:expr),* $(,)?) => {
805        impl HTTPServer {
806            $(
807                pub fn $name<T>(&mut self, path: &'static str, handler: T)
808                where
809                    T: Fn(HTTPRequest, PathMap) -> HTTPResponse + Send + Sync + 'static,
810                {
811                    self.add_path(Path::new(path, handler, $method));
812                }
813            )*
814        }
815    };
816}
817
818define_all_route_methods! {
819    get => HTTPMethod::GET,
820    post => HTTPMethod::POST,
821    put => HTTPMethod::PUT,
822    delete => HTTPMethod::DELETE,
823    patch => HTTPMethod::PATCH,
824    options => HTTPMethod::OPTIONS,
825    head => HTTPMethod::HEAD,
826    trace => HTTPMethod::TRACE,
827    connect => HTTPMethod::CONNECT,
828}
829
830impl HTTPServer {
831    pub fn new<A>(addr: A) -> Self
832    where
833        A: std::net::ToSocketAddrs,
834    {
835        Self {
836            addr: addr.to_socket_addrs().unwrap().collect(),
837            paths: Vec::new(),
838            listeners: Vec::new(),
839            on_ready: None,
840            on_shutdown: None,
841            on_error: None,
842            thread_pool: worker::ThreadPool::new(14),
843            should_shutdown: ShutdownWrapper(AtomicBool::new(false)),
844        }
845    }
846
847    pub fn on_ready<T>(&mut self, handler: T)
848    where
849        T: Fn() + Send + Sync + 'static,
850    {
851        self.on_ready = Some(SoftListener::new(handler));
852    }
853
854    pub fn shutdown(&self) {
855        self.should_shutdown.0.store(true, Ordering::Relaxed)
856    }
857
858    pub fn on_shutdown<T>(&mut self, handler: T)
859    where
860        T: Fn() + Send + Sync + 'static,
861    {
862        self.on_shutdown = Some(SoftListener::new(handler));
863    }
864
865    pub fn on_error<T>(&mut self, handler: T)
866    where
867        T: Fn(RunError) + Send + Sync + 'static,
868    {
869        self.on_error = Some(ErrorListener::new(handler));
870    }
871
872    fn add_path(&mut self, path: Path) {
873        let path_name = path.expr.clone();
874        if !self.paths.contains(&path) {
875            self.paths.push(path);
876        } else {
877            eprintln!(
878                "..warn `{}` path redefinition is not allowed. Only the first definition matter",
879                path_name
880            );
881        }
882    }
883
884    fn handle_connection(&self, stream: &mut TcpStream) {
885        match stream.try_clone() {
886            Ok(s) => {
887                let mut reader = std::io::BufReader::new(s);
888                let mut head = String::new();
889                'read_req_head: loop {
890                    let mut temp = String::new();
891                    let _ = reader.read_line(&mut temp);
892
893                    if temp.trim().is_empty() {
894                        break 'read_req_head;
895                    } else {
896                        head.push_str(&temp);
897                    }
898                }
899
900                let mut headers = [httparse::EMPTY_HEADER; 16];
901                let mut req = httparse::Request::new(&mut headers);
902                let is_complete = req.parse(&head.as_bytes()).unwrap().is_complete();
903                let raw_path = match req.path {
904                    Some(p) => p.to_string(),
905                    None => String::from("/"),
906                };
907                let (path, params) = parse_path(&raw_path);
908
909                let mut parsed_headers: HashMap<String, String> = HashMap::new();
910                for field in req.headers {
911                    parsed_headers.insert(
912                        field.name.to_lowercase(),
913                        String::from_utf8(field.value.to_vec()).unwrap(),
914                    );
915                }
916
917                let body_len: Option<usize> =
918                    if let Some(len) = parsed_headers.get("content-length") {
919                        Some(len.parse().unwrap())
920                    } else {
921                        None
922                    };
923
924                let method = get_method(req.method);
925
926                if let Some(body_size) = body_len {
927                    let mut body_buf = vec![0; body_size];
928                    let _ = reader.read_exact(&mut body_buf);
929                    if is_complete {
930                        self.handle_request(
931                            stream,
932                            HTTPRequest {
933                                method,
934                                path,
935                                raw_path,
936                                params,
937                                http_version: if req.version.unwrap() == 1 {
938                                    "1.1".into()
939                                } else {
940                                    "1.2".into()
941                                },
942                                headers: parsed_headers,
943                                body: body_buf,
944                            },
945                        );
946                    };
947                } else {
948                    let request = HTTPRequest {
949                        method,
950                        path,
951                        raw_path,
952                        params,
953                        http_version: get_version(req.version),
954                        headers: parsed_headers,
955                        body: vec![],
956                    };
957                    self.handle_request(stream, request);
958                }
959            }
960            Err(e) => {
961                eprintln!("{e}");
962            }
963        }
964    }
965
966    pub fn on_any<T>(&mut self, handler: T)
967    where
968        T: Fn(&HTTPRequest, &mut HTTPResponse) + Send + Sync + 'static,
969    {
970        self.listeners.push(Listener::new(handler));
971    }
972}
973
974pub struct TcpServer {
975    pub addr: Vec<SocketAddr>,
976    listeners: Vec<SimpleEventHandler>,
977    on_ready: Option<SoftListener>,
978    on_shutdown: Option<SoftListener>, // TODO: Implement on_shutdown
979    max_buffer: Option<usize>,
980}
981
982impl Default for TcpServer {
983    fn default() -> Self {
984        Self {
985            addr: vec![SocketAddr::new(
986                std::net::IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
987                4221,
988            )],
989            listeners: vec![],
990            on_ready: None,
991            on_shutdown: None,
992            max_buffer: None,
993        }
994    }
995}
996
997impl Server<&mut TcpStream, Request> for TcpServer {
998    fn handle_request(&self, stream: &mut TcpStream, req: Request) {
999        for listener in &self.listeners {
1000            if let Some(response) = listener.0(stream, req.clone()) {
1001                let _ = stream.write(&response);
1002            }
1003        }
1004    }
1005
1006    fn run(&self) {
1007        let listener = TcpListener::bind(self.addr.as_slice()).unwrap();
1008        if let Some(ready_fn) = &self.on_ready {
1009            ready_fn.notify();
1010        }
1011
1012        for stream in listener.incoming() {
1013            let mut max_buffer = MAX_BUFFER;
1014            if let Some(mxb) = self.max_buffer {
1015                max_buffer = mxb;
1016            }
1017            match stream {
1018                Ok(mut stream) => {
1019                    let mut data = vec![0; max_buffer];
1020                    let _ = stream.read(&mut data);
1021                    self.handle_request(&mut stream, data);
1022                }
1023                Err(e) => {
1024                    eprintln!("{e}")
1025                }
1026            }
1027        }
1028    }
1029}
1030
1031impl TcpServer {
1032    pub fn new<A>(addr: A) -> Self
1033    where
1034        A: std::net::ToSocketAddrs,
1035    {
1036        Self {
1037            addr: addr.to_socket_addrs().unwrap().collect(),
1038            on_ready: None,
1039            listeners: Vec::new(),
1040            on_shutdown: None,
1041            max_buffer: None,
1042        }
1043    }
1044
1045    pub fn on_ready<T>(&mut self, handler: T)
1046    where
1047        T: Fn() + Send + Sync + 'static,
1048    {
1049        self.on_ready = Some(SoftListener::new(handler));
1050    }
1051
1052    pub fn on_shutdown<T>(&mut self, handler: T)
1053    where
1054        T: Fn() + Send + Sync + 'static,
1055    {
1056        self.on_shutdown = Some(SoftListener::new(handler));
1057    }
1058
1059    pub fn set_buffer_to(&mut self, size: usize) {
1060        self.max_buffer = Some(size);
1061    }
1062}