use std::{ fs, io::{prelude::*, BufReader}, net::TcpStream, }; use crate::router; #[allow(dead_code)] struct IncomingRequest { req_type: String, path: String } #[allow(unused_assignments)] pub fn handle_connection(mut stream: TcpStream) { // Create a new buffer reader with the stream data. let buf_reader = BufReader::new(&stream); // Store each line in a vector. let http_request: Vec<_> = buf_reader .lines() .map(|result| result.unwrap()) .take_while(|line| !line.is_empty()) .collect(); // Get the first line of the stream which contains request data. let request_line: String = http_request.first().expect("Not a string").to_string(); // Split the request data on spaces into a vector. let req_vec: Vec<&str> = request_line.split(" ").collect(); let inc_request = IncomingRequest { req_type: req_vec[0].to_string(), path: req_vec[1].to_string(), }; // Retrieve the api key from the request. let api_key: String = get_api_key(http_request); let mut response = String::new(); // If not a GET request, or missing API key, throw 404. if inc_request.req_type != "GET" || api_key.is_empty() { response = return_response("404"); } else { // Get allowed api key from text file. let mut keyfile: Vec = fs::read_to_string("./keys.txt").into_iter().collect(); // Get the first item, for now. @todo make this more dynamic. keyfile[0].pop().expect("Keyfile not found").to_string(); if api_key == keyfile[0] { // Here we need to look up the route by path. if inc_request.path.is_empty() { response = return_response("404"); } else { response = return_response(&inc_request.path); } // response = return_response("200"); } else { response = return_response("404"); } } stream.write_all(response.as_bytes()).unwrap(); } fn get_api_key(headers: Vec) -> String { let mut api_key = String::new(); for header in headers { // split header, strip whitespace, check if exists. let split_header: Vec<&str> = header.split(":").collect(); let header_key: String = split_header.first().expect("Nothing here").to_string(); if header_key == "x-api-key" { api_key = split_header[1].to_string(); } } api_key } fn return_response(path_or_code: &str) -> String { let status_line: String; let contents: String; match path_or_code { "404" => { status_line = "HTTP/1.1 404 Not Found".to_string(); contents = fs::read_to_string("./public/404.json").unwrap(); }, "200" => { status_line = "HTTP/1.1 200 OK".to_string(); contents = fs::read_to_string("./public/200.json").unwrap(); }, &_ => { // Need to get the proper response based on the given path. let has_route = router::route_exists(path_or_code); if has_route { status_line = "HTTP/1.1 200 OK".to_string(); contents = router::get_route_data(path_or_code); } else { status_line = "HTTP/1.1 404 Not Found".to_string(); contents = fs::read_to_string("./public/404.json").unwrap(); } } } let length = contents.len(); format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}") }