rusty_server/
lib.rs

1pub mod thread_pool {
2    use std::sync::mpsc;
3    use std::sync::Arc;
4    use std::sync::Mutex;
5    use std::thread;
6    type Job = Box<dyn FnOnce() + Send + 'static>;
7
8    enum ThreadState {
9        Doing(Job),
10        Terminate,
11    }
12    pub struct Worker {
13        id: usize,
14        thread: Option<thread::JoinHandle<()>>,
15    }
16
17    impl Worker {
18        fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<ThreadState>>>) -> Worker {
19            let thread = thread::spawn(move || loop {
20                let state = receiver.lock().unwrap().recv().unwrap();
21                match state {
22                    ThreadState::Doing(job) => {
23                        println!("Worder {}, got a job; executing.", id);
24                        job();
25                    }
26                    ThreadState::Terminate => {
27                        println!("Worker {} was told to terminate.", id);
28                        break;
29                    }
30                }
31            });
32            Worker {
33                id,
34                thread: Some(thread),
35            }
36        }
37    }
38    pub struct ThreadPool {
39        workers: Vec<Worker>,
40        sender: mpsc::Sender<ThreadState>,
41    }
42
43    impl ThreadPool {
44        pub fn new(size: usize) -> ThreadPool {
45            assert!(size > 0);
46
47            let (sender, receiver) = mpsc::channel();
48            let receiver = Arc::new(Mutex::new(receiver));
49            let mut workers = Vec::with_capacity(size);
50            for id in 0..size {
51                workers.push(Worker::new(id, Arc::clone(&receiver)));
52            }
53            ThreadPool { workers, sender }
54        }
55        pub fn execute<F>(&self, f: F)
56        where
57            F: FnOnce() + Send + 'static,
58        {
59            let job = Box::new(f);
60            self.sender.send(ThreadState::Doing(job)).unwrap();
61        }
62    }
63    impl Drop for ThreadPool {
64        fn drop(&mut self) {
65            for _ in &self.workers {
66                self.sender.send(ThreadState::Terminate).unwrap();
67            }
68            for worker in &mut self.workers {
69                println!("shutting down worker {}", worker.id);
70                if let Some(thread) = worker.thread.take() {
71                    thread.join().unwrap();
72                }
73            }
74        }
75    }
76}
77
78pub mod server {
79    use crate::thread_pool;
80    use std::collections::HashMap;
81    use std::fs;
82    use std::io::prelude::*;
83    use std::net::TcpListener;
84    use std::net::TcpStream;
85    #[derive(Clone)]
86    pub struct Server {
87        pub req_hash: HashMap<String, String>,
88        pub port: String 
89    }
90    impl Server {
91        pub fn new() -> Server   {
92            Server {
93                req_hash: HashMap::new(),
94                port: "8080".to_string(),
95            }
96        }
97        pub fn get(&mut self, path: &str, serve: &str) {
98            self.req_hash
99                .insert(format!("GET {} HTTP/1.1\r\n", path), serve.to_string());
100        }
101
102        fn check_req(&mut self, buffer: [u8; 1024]) -> (String, String) {
103            let buffer = String::from_utf8_lossy(&buffer[..]);
104            for req in self.req_hash.keys() {
105                if buffer.starts_with(req) {
106                    return (
107                        "HTTP/1.1 200 OK".to_string(),
108                        match self.req_hash.get(&req.clone()) {
109                            Some(addr) => addr.to_string(),
110                            None => {
111                                // handle error
112                                panic!("error while handleing {}", req);
113                            }
114                        },
115                    );
116                }
117            }
118            (
119                "HTTP/1.1 404 NOT FOUND".to_string(),
120                "public/404.html".to_string(),
121            )
122        }
123
124        fn handle_connection(&mut self, mut stream: TcpStream) {
125            let mut buffer = [0; 1024];
126            stream.read(&mut buffer).unwrap();
127            let (status_line, mut content) = self.check_req(buffer.clone());
128            if content.starts_with("public") {
129                content = fs::read_to_string(content).unwrap();
130            }
131
132            let responce = format!(
133                "{}\r\nContent-Lenght: {}\r\n\r\n{}",
134                status_line,
135                content.len(),
136                content
137            );
138            stream.write(responce.as_bytes()).unwrap();
139            stream.flush().unwrap();
140        }
141        pub fn bind(&mut self, port: &str) {
142            self.port = port.to_string();
143        }
144        pub fn start(&self) {
145            let listener = TcpListener::bind(String::from("127.0.0.1:") + &self.port).unwrap();
146            let pool = thread_pool::ThreadPool::new(4);
147            for stream in listener.incoming() {
148                let stream = stream.unwrap();
149                let mut inst = self.clone();
150                pool.execute(move || {
151                    inst.handle_connection(stream);
152                });
153            }
154            println!("Shutting the server down");
155        }
156    }
157}