Initial start of the route handling for DAM assets.

This commit is contained in:
calcu1on 2025-01-05 11:26:21 -05:00
parent d1ac420503
commit 3c66a6b6bc
4 changed files with 146 additions and 85 deletions

View File

@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
base64 = "0.22.1"
rand = "0.8"
sqlite = "0.36.1"

103
src/connection.rs Normal file
View File

@ -0,0 +1,103 @@
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<String> = 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>) -> 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}")
}

View File

@ -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<String> = 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>) -> 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
}

38
src/router.rs Normal file
View File

@ -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<String, String> {
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()
}