1use std::{convert::TryFrom, fs, io::Read, net::TcpListener};
2
3use crate::http::{Method, ParseError, Request, Response, StatusCode};
4
5const BUFFER_SIZE: usize = 16 * 1024;
6
7#[derive(Debug)]
8pub struct Server {
9 pub port: u16,
10 pub public_path: String,
11}
12
13impl Default for Server {
14 fn default() -> Self {
15 Server {
16 port: 8080,
17 public_path: String::from("./"),
18 }
19 }
20}
21
22impl Server {
23 fn read_file(&self, file_path: &str) -> Option<String> {
24 let path = format!("{}/{}", self.public_path, file_path);
25 fs::read_to_string(path).ok()
26 }
27
28 fn handle_request(&mut self, request: &Request) -> Response {
31 match request.method() {
32 Method::GET => match request.path() {
33 "/" => Response::new(StatusCode::Ok, self.read_file("index.html")),
34 path => match self.read_file(path) {
35 Some(contents) => Response::new(StatusCode::Ok, Some(contents)),
36 None => Response::new(StatusCode::NotFound, None),
37 },
38 },
39 _ => Response::new(
40 StatusCode::NotFound,
41 Some(String::from(
42 "Could not find a index.html file in this dir...",
43 )),
44 ),
45 }
46 }
47
48 fn handle_bad_request(&mut self, err: &ParseError) -> Response {
49 println!("Failed to parse a request: {}", err);
50 Response::new(
51 StatusCode::BadRequest,
52 Some("Nothing to see here...".to_string()),
53 )
54 }
55}
56
57impl Server {
58 pub fn new(port: u16, public_path: String) -> Self {
59 Server { port, public_path }
60 }
61
62 pub fn run(mut self) {
63 let address = format!("127.0.0.1:{}", self.port);
64 println!("Server running on http://{}", &address);
65 let listener = TcpListener::bind(address).expect("Error binding TcpListener");
66
67 loop {
68 match listener.accept() {
69 Ok((mut stream, _)) => {
70 let mut buffer = [0; BUFFER_SIZE];
71 match stream.read(&mut buffer) {
72 Ok(_) => {
73 let response = match Request::try_from(&buffer[..]) {
74 Ok(request) => self.handle_request(&request),
75 Err(err) => self.handle_bad_request(&err),
76 };
77
78 if let Err(err) = response.send(&mut stream) {
79 println!("Failed to send response, {}", err);
80 }
81 }
82 Err(err) => println!("Failed to read from connection: {}", err),
83 }
84 }
85 Err(err) => println!("Failed to establish a connection: {}", err),
86 }
87 }
88 }
89}