140 lines
3.5 KiB
Rust
140 lines
3.5 KiB
Rust
extern crate file_matcher;
|
|
|
|
use file_matcher::FileNamed;
|
|
use hello::{
|
|
ThreadPool,
|
|
};
|
|
use std::{
|
|
fs,
|
|
io::{prelude::*, BufReader},
|
|
net::{TcpListener, TcpStream},
|
|
collections::HashMap,
|
|
path::Path,
|
|
};
|
|
use config::Config;
|
|
|
|
|
|
fn main() {
|
|
//building config
|
|
let cfg = Config::builder()
|
|
.add_source(config::File::with_name("websrv_conf"))
|
|
.build()
|
|
.unwrap();
|
|
|
|
let cfg = cfg.try_deserialize::<HashMap<String, String>>().expect("Could not deserialize configuration");
|
|
println!("Starting with configuration: ");
|
|
for conf in &cfg {
|
|
println!("{:?}", conf);
|
|
}
|
|
|
|
let nbr_of_threads: usize = cfg
|
|
.get("threads")
|
|
.expect("Threads not found in config")
|
|
.parse()
|
|
.unwrap();
|
|
|
|
let default_bind_addr = String::from("0.0.0.0:7878");
|
|
let bind_addr = cfg
|
|
.get("bind_addr")
|
|
.unwrap_or(&default_bind_addr)
|
|
.to_string();
|
|
|
|
let default_webpage = String::from("index.html");
|
|
let webpage = cfg
|
|
.get("webpage")
|
|
.unwrap_or(&default_webpage)
|
|
.to_string();
|
|
|
|
let listener = TcpListener::bind(bind_addr).unwrap();
|
|
|
|
let pool = ThreadPool::new(nbr_of_threads);
|
|
|
|
for stream in listener.incoming() {
|
|
let stream = stream.unwrap();
|
|
let webp = webpage.clone();
|
|
|
|
pool.execute(move || {
|
|
handle_connection(stream, webp);
|
|
});
|
|
}
|
|
|
|
println!("Shutting down.");
|
|
}
|
|
|
|
fn search_page(page: &String) -> Option<String> {
|
|
if page == "/" {
|
|
match FileNamed::regex(r"index\.htm.*").within("./html").find() {
|
|
Ok(f) => {
|
|
return Some(fs::read_to_string(f).unwrap());
|
|
},
|
|
Err(_) => return None,
|
|
};
|
|
} else {
|
|
match FileNamed::regex(format!(r"{}\.htm.*", page)).within("./html").find() {
|
|
Ok(f) => {
|
|
let fpath = format!("./html/{:?}", f);
|
|
return Some(fs::read_to_string(f).unwrap());
|
|
},
|
|
Err(_) => return None,
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
///Analyze the request and answer it
|
|
///Returns the complete answer
|
|
fn analyze_request_line(line: Vec<&str>) -> String {
|
|
let req = String::from(line[0]);
|
|
let mut page = String::from(line[1]);
|
|
let proto = String::from(line[2]);
|
|
let mut ret_code = "404 NOT FOUND";
|
|
|
|
//Removing the leading / from the page if need be
|
|
if &page != "/" {
|
|
page.remove(0);
|
|
}
|
|
|
|
let content = match search_page(&page) {
|
|
Some(c) => {
|
|
*&mut ret_code = "200 OK";
|
|
c
|
|
},
|
|
None => {
|
|
fs::read_to_string("./html/err_pages/404.html").unwrap_or(String::from("404 not found"))
|
|
},
|
|
};
|
|
|
|
let length = content.len();
|
|
let returned_line = format!(
|
|
"{proto} {ret_code}\r\nContent-Length: {length}\r\n\r\n{content}"
|
|
);
|
|
return returned_line;
|
|
|
|
|
|
}
|
|
|
|
fn handle_connection(mut stream: TcpStream, webpage: String) {
|
|
let buf_reader = BufReader::new(&mut stream);
|
|
//for i in buf_reader.lines() {
|
|
// println!("{:?}", i);
|
|
//}
|
|
let mut req_lines = buf_reader.lines();
|
|
let mut request = match req_lines.next() {
|
|
Some(c) => c,
|
|
None => Ok(String::from("RIEN")),
|
|
};
|
|
let request = request.unwrap();
|
|
println!("!!{:?}", request);
|
|
//Some(Ok("GET /crabe HTTP/1.1"))
|
|
|
|
|
|
if &request != "RIEN" {
|
|
let request_analyze: Vec<&str> = request.split_whitespace().collect();
|
|
let ret_line = analyze_request_line(request_analyze);
|
|
|
|
stream.write_all(ret_line.as_bytes()).unwrap();
|
|
}
|
|
}
|
|
|
|
|