use std::{collections::HashMap, fs::{self, File}};
use mime_guess::{MimeGuess};
use crate::{HttpRequest, HttpServer, HttpStatusStruct};
pub fn break_request_uri(req: &HttpRequest) -> (String, HashMap<String, String>) {
let uri = req.uri();
let parts: Vec<&str> = uri.split('?').collect();
let mut params = HashMap::<String, String>::new();
let path = String::from(if let Some(path) = parts.get(0) { path } else { "/" });
if parts.len() >= 2 {
let pairs: Vec<&str> = parts[1].split('&').collect();
for pair in pairs {
let key_val: Vec<&str> = pair.split('=').collect();
params.insert(String::from(key_val[0]), String::from(if let Some(val) = key_val.get(1) { val } else { "" }));
}
}
(path, params)
}
pub trait MoreDetailsRequest {
fn path(&self) -> String;
fn params(&self) -> HashMap<String, String>;
}
impl MoreDetailsRequest for HttpRequest {
fn path(&self) -> String {
break_request_uri(&self).0
}
fn params(&self) -> HashMap<String, String> {
break_request_uri(&self).1
}
}
pub trait ServeStatic {
fn serve_static(&mut self, root_dir: Option<String>);
}
impl ServeStatic for HttpServer {
fn serve_static(&mut self, root_dir: Option<String>) {
let roor_dir = root_dir.unwrap_or(String::from("public"));
self.insert_handler(move |req, mut res| {
let path = req.path();
let file_path = format!("{}{}", &roor_dir, &path);
if let Ok(file) = File::open(&file_path) {
if let Ok(metadata) = file.metadata() {
if metadata.is_file() {
let data = fs::read(&file_path).unwrap_or(Vec::new());
let guess = MimeGuess::from_path(&file_path);
res.set_status(HttpStatusStruct(200, "OK"));
res.insert_header(String::from("Content-Type"), guess.first_or(mime_guess::mime::TEXT_PLAIN).to_string());
res.bytes(data);
}
}
}
Ok((req, res))
});
}
}