rust-express 0.1.1

An ExpressJS inspired rust crate that handles http request in a similar way to ExpressJS. Created entirely out of bordom, you can pull and expand it as you like!
Documentation
use std::{collections::HashMap, io::ErrorKind};

use crate::utils::request::Request;
use crate::utils::router::Router;
use base64::prelude::*;
use mime_guess::from_path;
use serde_json::{json, Value};
use std::fs;


#[allow(dead_code)]
pub struct Response {
    pub content_type: String,
    pub content_length: usize,
    pub status_text: String,
    pub status: i64,
    pub body: Value,
    pub raw: String,
    pub cookies: HashMap<String, String>,
    pub is_file: bool,
}

#[allow(dead_code)]
impl Response {
    pub fn new() -> Self {
        Self {
            content_length: 0,
            content_type: "text/plain".to_owned(),
            status_text: "OK".to_owned(),
            status: 200,
            body: json!(format!("")),
            raw: format!("HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\n"),
            cookies: HashMap::new(),
            is_file: false,
        }
    }

    pub fn text(&self, body: &str, status: i64) -> Response {
        Response {
            content_length: body.len(),
            content_type: "text/plain".to_owned(),
            status_text: "OK".to_owned(),
            status,
            body: json!(body),
            raw: format!(
                "HTTP/1.1 {}\r\nContent-Type: text/plain\r\n\r\n{}",
                status,
                body
            ),
            cookies: self.cookies.to_owned(),
            is_file: false,
        }
    }

    pub fn json(&self, body: Value, status: i64) -> Response {
        Response {
            content_length: body.to_string().len(),
            content_type: "application/json".to_owned(),
            status_text: "OK".to_owned(),
            status,
            body: body.to_owned(),
            raw: format!(
                "HTTP/1.1 {}\r\nContent-Type: application/json\r\n\r\n{}",
                status,
                serde_json::to_string(&body.to_owned()).unwrap()
            ),
            cookies: self.cookies.to_owned(),
            is_file: false,
        }
    }

    pub fn error(&self, body: &str, status: i64) -> Response {
        Response {
            status,
            body: json!(body),
            status_text: "Internal Server Error".to_owned(),
            content_length: body.len(),
            content_type: "text/plain".to_owned(),
            raw: format!(
                "HTTP/1.1 {} Internal Server Error\r\nContent-Type: text/plain\r\n\r\n{}",
                status,
                body
            ),
            cookies: self.cookies.to_owned(),
            is_file: false,
        }
    }


    pub fn send_file(&self, path: &str, status: i64) -> Response {
        let filename = path.split("/").last().unwrap();
        let file_type = from_path(path).first_or_octet_stream().to_string();
        let mut file_content = String::new();

        match fs::read_to_string(path) {
            Ok(content) => file_content = content,
            Err(err) => {
                if err.kind() == ErrorKind::InvalidData {
                    let file_bytes = fs::read(path).expect("Error while reading file bytes");
                    file_content = BASE64_STANDARD.encode(file_bytes)
                } else {
                    eprint!("Error while reading file! {}", err.to_string())
                }
            }
        }

        Response {
            content_length: file_content.len(),
            content_type: file_type.to_owned(),
            status_text: "OK".to_owned(),
            status,
            body: json!(format!("{filename}:{file_content}")),
            raw: format!(
                "HTTP/1.1 {}\r\nContent-Type: {}\r\n\r\n{}",
                status, file_type, self.body
            ),
            cookies: self.cookies.to_owned(),
            is_file: true,
        }
    }

    pub fn render(&self, path: &str, status: i64) -> Response {
        let file_content = fs::read_to_string(path).expect("Error while reading html content");
        Response {
            content_length: file_content.len(),
            content_type: "text/html".to_owned(),
            status_text: "OK".to_owned(),
            status,
            body: json!(file_content),
            raw: format!(
                "HTTP/1.1 {} OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\n\r\n{}",
                status,
                file_content.len(),
                file_content
            ),
            cookies: self.cookies.to_owned(),
            is_file: false,
        }
    }

}

pub async fn handle_response(
    stream: &mut tokio::net::TcpStream,
    request: &Request,
    router: &Router,
) {
    router.handle_request(stream, request).await;
}