use std::net::{TcpStream, TcpListener}; use std::io::prelude::*; // use std::fs; // use std::thread; // use std::time::Duration; // use std::str; use std::path::Path; use webserv::{ThreadPool, Response, Route}; extern crate regex; use regex::Regex; fn main() { let listener = TcpListener::bind("127.0.0.1:26382").unwrap(); let pool = ThreadPool::new(4); for stream in listener.incoming() { let stream = stream.unwrap(); pool.execute(|| { handle_connection(stream); }); } println!("Shutting down."); } fn handle_connection(mut stream: TcpStream) { let mut buffer = [0; 512]; stream.read(&mut buffer).unwrap(); let mut r = Response::new("",""); let bf = &String::from_utf8_lossy(&buffer[..]); // let get = b"GET / HTTP/1.1\r\n"; // let sleep = b"GET /sleep HTTP/1.1\r\n"; if buffer.starts_with(b"GET") { let hdr = Regex::new(r"GET /([^ ]*) HTTP/1.1").unwrap(); let caps = hdr.captures(&bf); match caps { Some(cap) => { let c = cap.get(1).unwrap().as_str(); route(&c, &mut r); }, None => { println!("This wasn't even a well-formed header"); r.set_header("HTTP/1.1 404 NOT FOUND\r\n\r\n"); r.add_file_contents("404.html"); } } } else { println!("It didn't start with GET!"); r.set_header("HTTP/1.1 404 NOT FOUND\r\n\r\n"); r.add_file_contents("404.html"); } // println!("Sending {}: {}", r.header, r.path); let response = format!("{}{}", r.get_header(), r.get_content()); stream.write(response.as_bytes()).unwrap(); stream.flush().unwrap(); // println!("Request: {}", String::from_utf8_lossy(&buffer[..])); } fn route(c: &str, mut r: &mut Response) { let mut routes = vec![]; routes.push(Route::new("v1/hi", api_hi)); routes.push(Route::new("v1/bye", api_bye)); // println!("Asked to fetch {}", c); //assert!(Path::new(c).exists()); if c == "" { println!("Asked to send root!"); r.set_header("HTTP/1.1 200 OK\r\n\r\n"); r.add_file_contents("index.html"); } else if c.starts_with("api/") { let apipath = c.replace("api/",""); let apipath = apipath.as_str(); let mut iter_routes = routes.into_iter(); let valid_route = iter_routes.find(|x| x.get_path() == apipath); match valid_route { Some(rt) => { (rt.get_action())(&apipath, &mut r); }, None => { api_none(&c, &mut r); } } } else if Path::new(c).exists() { route_basic(&c, &mut r); } else { println!("Asked to send {} and I could not find it", &c); r.set_header("HTTP/1.1 404 NOT FOUND\r\n\r\n"); r.add_file_contents("404.html"); } } fn route_basic(c: &&str, r: &mut Response) { if Path::new(c).is_dir() { let mut cs = c.to_string(); if cs.chars().last().unwrap().to_string() != "/" { cs.push_str("/"); } cs.push_str("index.html"); if Path::new(&cs).exists() { println!("Asked to send {}", &cs); r.set_header("HTTP/1.1 200 OK\r\n\r\n"); r.add_file_contents(&cs); } else { println!("Asked to send {} and I couldn't find it", &cs); r.set_header("HTTP/1.1 404 NOT FOUND\r\n\r\n"); r.add_file_contents("404.html"); } } else { println!("Asked to send {}", &c); r.set_header("HTTP/1.1 200 OK\r\n\r\n"); r.add_file_contents(&c); } } fn api_none(_c: &&str, r: &mut Response) { r.set_header("HTTP/1.1 404 NOT FOUND\r\n\r\n"); r.set_content("There is currently no API endpoint at that address."); } fn api_hi(_c: &&str, r: &mut Response) { r.set_header("HTTP/1.1 200 OK\r\n\r\n"); r.set_content("Hello there!"); } fn api_bye(_c: &&str, r: &mut Response) { r.set_header("HTTP/1.1 200 OK\r\n\r\n"); r.set_content("Leaving so soon?"); }