diff --git a/Cargo.toml b/Cargo.toml
index e173c71..e9407fa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
base64 = "0.22.1"
rand = "0.8"
+sqlite = "0.36.1"
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..d42bc82
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,15 @@
+
+
+
+ Page Not Found
+
+
+
+ Page cannot be found
+ Sorry, this page cannot be found.
+
+
diff --git a/src/connection.rs b/src/connection.rs
new file mode 100644
index 0000000..93d41a0
--- /dev/null
+++ b/src/connection.rs
@@ -0,0 +1,117 @@
+use std::{
+ fs,
+ io::{prelude::*, BufReader},
+ net::TcpStream,
+};
+
+use crate::router;
+
+#[allow(dead_code)]
+struct IncomingRequest {
+ req_type: String,
+ path: String
+ // headers: Vec
+}
+
+#[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();
+ println!("{:?}", http_request);
+ 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_header(http_request, "x-api-key");
+ 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 get_header(headers: Vec, needle: &str) -> String {
+ let mut value = String::new();
+ for header in headers {
+ let split_header: Vec<&str> = header.split(":").collect();
+ let header_key: String = split_header.first().expect("Nothing here").to_string();
+ if header_key == needle {
+ value = split_header[1].to_string();
+ }
+ }
+ value
+}
+
+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.html").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.html").unwrap();
+ }
+ }
+ }
+
+ let length = contents.len();
+ format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}")
+}
diff --git a/src/main.rs b/src/main.rs
index 909405f..987cf2e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,7 @@
-use std::{
- fs,
- io::{prelude::*, BufReader},
- net::{TcpListener, TcpStream},
-};
+use std::net::TcpListener;
-#[allow(dead_code)]
-struct IncomingRequest {
- req_type: String,
- path: String
-}
+pub mod connection;
+mod router;
// Listen on port and return response.
fn main() {
@@ -21,81 +14,7 @@ fn main() {
for stream in listener.incoming() {
let stream = stream.unwrap();
- handle_connection(stream);
+ connection::handle_connection(stream);
}
}
-#[allow(unused_assignments)]
-fn handle_connection(mut stream: TcpStream) {
- let buf_reader = BufReader::new(&stream);
- let http_request: Vec<_> = buf_reader
- .lines()
- .map(|result| result.unwrap())
- .take_while(|line| !line.is_empty())
- .collect();
-
- let request_line: String = http_request.first().expect("Not a string").to_string();
- 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(),
- };
- 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 {
- let mut keyfile: Vec = fs::read_to_string("./keys.txt").into_iter().collect();
- keyfile[0].pop().expect("Not a string").to_string();
- if api_key == keyfile[0] {
- response = return_response("200");
- } else {
- response = return_response("404");
- }
- }
- stream.write_all(response.as_bytes()).unwrap();
-}
-
-// get the apy key from the headers.
-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
-}
-
-#[allow(unused_assignments)]
-fn return_response(code: &str) -> String {
- let mut response = String::new();
- match code {
- "404" => {
- let status_line = "HTTP/1.1 404 Not Found";
- let contents = fs::read_to_string("./public/404.json").unwrap();
- let length = contents.len();
-
- response =
- format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
- },
- "200" => {
- let status_line = "HTTP/1.1 200 OK";
- let contents = fs::read_to_string("./public/200.json").unwrap();
- let length = contents.len();
-
- response =
- format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
- },
- &_ => todo!()
- }
-
- response
-}
diff --git a/src/router.rs b/src/router.rs
new file mode 100644
index 0000000..028bc39
--- /dev/null
+++ b/src/router.rs
@@ -0,0 +1,38 @@
+use std::collections::HashMap;
+
+pub fn get_route_data(route: &str) -> String {
+ let route_data: String;
+ match route {
+ "/fetch" => {
+ route_data = fetch_asset();
+ }
+ &_ => todo!(),
+ }
+ route_data
+}
+
+pub fn route_exists(route: &str) -> bool {
+ let existing_routes = get_routes();
+ if existing_routes.contains_key(route) {
+ true
+ }
+ else {
+ false
+ }
+}
+
+fn get_routes() -> HashMap {
+ let mut routes = HashMap::new();
+ routes.insert("/fetch".to_string(), "fetch_asset".to_string());
+ routes
+}
+
+fn fetch_asset() -> String {
+ let asset = r#"{
+ "title": "this is a title",
+ "id": 2,
+ "url": "https://www.espn.com
+ }"#;
+
+ asset.to_string()
+}