server/request.rs
1//! # use server::request::{ [RequestObject], [handle_connection] }
2//!
3//! A library that hanldes requests made to the web-server.
4
5use std::{fs, net::TcpStream};
6use std::io::prelude::*;
7use super::process::CliArgs;
8
9#[derive(Debug)]
10/// The requests made to the web-server are represented in the data structure `RequestObject`
11/// The only supported request method on the server is `GET`
12pub struct RequestObject {
13 /// This represents the request method of the request received by the server
14 pub method: String,
15
16 /// This represents the route of the asset/file requested by the client side.
17 pub route: String,
18}
19
20impl RequestObject {
21 /// Returns a struct with a request method and request route.
22 ///
23 /// # Args
24 ///
25 /// * `request` - This is the request in a string format containing necessary request information.
26 ///
27 /// # Example
28 ///
29 /// ```
30 /// use server::request::RequestObject;
31 /// let req_obj: Option<RequestObject> = RequestObject::new(&String::from("GET / Content-Length: 0\r\n\r\n"));
32 ///
33 /// match req_obj {
34 /// Some(obj) => {
35 /// assert!(obj.method == "GET");
36 /// assert!(obj.route == "/");
37 /// }
38 /// None => {}
39 /// }
40 ///
41 /// ```
42 ///
43 /// # Panics
44 ///
45 /// - Panics if the request methos is not a `GET` method
46 /// - Panics if the route does not start with `/`.
47 ///
48 pub fn new(request: &String) -> Option<RequestObject> {
49 let allowed_methods = ["GET"];
50 let req_args: Vec<&str> = request.split(" ").collect();
51 let method = req_args[0];
52 let route = req_args[1];
53
54 assert!(allowed_methods.contains(&method), "Invalid request method");
55 assert!(route.starts_with("/"), "Invalid request route");
56
57 Some(RequestObject {
58 method: String::from(method),
59 route: String::from(route)
60 })
61 }
62}
63
64/// Function that handles a request stream.
65/// The request is processed based on the method and route.
66/// The route determines the file path for a `GET` request.
67///
68/// Args
69///
70/// * `stream` - A TcpStream type which basically is a stream of bytes that represents the client request.
71///
72pub fn handle_connection(mut stream: TcpStream) {
73 let mut buffer = [0; 1024];
74 stream.read(&mut buffer).unwrap();
75
76 let str_buffer = String::from_utf8(buffer.clone().to_vec()).unwrap();
77 let request_obj = RequestObject::new(&str_buffer);
78
79 match &request_obj {
80 Some(req) => {
81 if req.method == "GET" {
82 let route = req.route.as_str();
83 let content: String;
84 match route {
85 value => {
86 let mut file_path = value;
87 if (!value.contains(".") && !value.contains(".html")) || value == "/index.html" {
88 file_path = "/index.html"
89 }
90 let file_content = fs::read_to_string(String::from(CliArgs::get().dir_path) + file_path);
91
92 match file_content {
93 Ok(data) => {
94 content = data.clone()
95 }
96 Err(_) => {
97 content = fs::read_to_string("assets/404.html").unwrap();
98 }
99 }
100 }
101 }
102
103 let response = format!(
104 "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
105 content.len(),
106 content,
107 );
108 stream.write(response.as_bytes()).unwrap();
109 stream.flush().unwrap();
110 }
111 }
112 None => {}
113 }
114}