From 4156bc42fae04732ff39adc9baff45e98fe32f8b Mon Sep 17 00:00:00 2001 From: holly sparkles Date: Wed, 4 Oct 2023 10:50:17 +0200 Subject: [PATCH] refactor!: remove lazy_static dep, use rustfmt on data module --- Cargo.toml | 2 -- src/data.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------- src/main.rs | 71 ++++++++++++++++++++++++++++++++++------------------------------------- 3 files changed, 94 insertions(+), 100 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cb79530..5cdf648 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,7 @@ edition = "2021" [dependencies] async-std = { version = "1.12.0", features = ["attributes"] } -envy = "0.4.2" jealousy = { version = "0.1.5", features = ["derive"] } -lazy_static = "1.4.0" serde = { version = "1.0.188", features = ["derive"] } serde_yaml = "0.9.25" tide = "0.16.0" diff --git a/src/data.rs b/src/data.rs index 345d07d..2447ca3 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,82 +1,81 @@ -use std::path::Path; - use serde::Deserialize; +use std::str::FromStr; use tide::log; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] pub struct LicenseDatabase { pub licenses: Vec, } pub trait Queryable { - fn get_licenses(self: &Self, chunk_size: usize) -> Option; - fn get_detailed_licenses(self: &Self) -> Option; - fn get_license(self: &Self, id: &str) -> Option; + fn get_licenses(self: &Self, chunk_size: usize) -> Option; + fn get_detailed_licenses(self: &Self) -> Option; + fn get_license(self: &Self, id: &str) -> Option; } impl Queryable for LicenseDatabase { - fn get_licenses(self: &Self, chunk_size: usize) -> Option { - let result = self - .licenses - .iter() - .map(|license| license.id.clone()) - .collect::>() - .chunks(chunk_size) - .map(|chunk| chunk.join(", ")) - .collect::>() - .join("\n"); - - if result.is_empty() { - log::warn!("License database not found!"); - None - } - else { - Some(result) - } - } - - fn get_detailed_licenses(self: &Self) -> Option { - const PADDING: usize = 20; + fn get_licenses(self: &Self, chunk_size: usize) -> Option { + let result = self + .licenses + .iter() + .map(|license| license.id.clone()) + .collect::>() + .chunks(chunk_size) + .map(|chunk| chunk.join(", ")) + .collect::>() + .join("\n"); - let result: String = self - .licenses - .iter() - .map(|license| { - format!( - "{:padding$}{}", - license.id, - license.description, - padding = PADDING - ) - }) - .collect::>() - .join("\n"); + if result.is_empty() { + log::warn!("License database not found!"); + None + } else { + Some(result) + } + } - if result.is_empty() { - log::warn!("License database not found!"); - None - } - else { - Some(result) - } - } + fn get_detailed_licenses(self: &Self) -> Option { + const PADDING: usize = 20; - fn get_license(self: &Self, id: &str) -> Option { - let query: Option = self - .licenses - .iter() - .map(|license| license.clone()) - .find(|license| license.id.eq(id)); - - query - } + let result: String = self + .licenses + .iter() + .map(|license| { + format!( + "{:padding$}{}", + license.id, + license.description, + padding = PADDING + ) + }) + .collect::>() + .join("\n"); + + if result.is_empty() { + log::warn!("License database not found!"); + None + } else { + Some(result) + } + } + + fn get_license(self: &Self, id: &str) -> Option { + let query: Option = self + .licenses + .iter() + .map(|license| license.clone()) + .find(|license| license.id.eq(id)); + + query + } } impl LicenseDatabase { - pub fn load_file(file: &Path) -> LicenseDatabase { - let file_contents = std::fs::read_to_string(file).unwrap(); + pub fn load(file: String) -> LicenseDatabase { + // TODO: error handling and use log::info when done + // not sure if i should validate the unwrap since main won't start if there is an error... + let db_path: std::path::PathBuf = std::path::PathBuf::from_str(file.as_str()).unwrap(); + let file_contents = std::fs::read_to_string(db_path.as_path()).unwrap(); let database: LicenseDatabase = serde_yaml::from_str(&file_contents).unwrap(); - database } } diff --git a/src/main.rs b/src/main.rs index 6fd0f5e..fa6b0c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,29 +5,26 @@ use async_std::{ use data::LicenseDatabase; use jealousy::FromEnv; use serde::Deserialize; -use std::{net::Ipv4Addr, str::FromStr}; +use std::net::Ipv4Addr; use tide::{http::mime, log, Response, Result, Server, StatusCode}; -use crate::data::{License, Queryable}; +use crate::data::Queryable; mod data; -#[macro_use] -extern crate lazy_static; - -#[derive(Debug, Deserialize, FromEnv)] +#[derive(Debug, Deserialize, FromEnv, Clone)] #[from_env(prefix = "LICENSE_API")] -struct Config { - #[serde(default = "Config::default_base_url")] +struct ServerConfig { + #[serde(default = "ServerConfig::default_base_url")] base_url: String, database: String, - #[serde(default = "Config::default_server_ip")] + #[serde(default = "ServerConfig::default_server_ip")] server_ip: Ipv4Addr, // TODO: IPv6 support - #[serde(default = "Config::default_server_port")] + #[serde(default = "ServerConfig::default_server_port")] server_port: u16, } -impl Config { +impl ServerConfig { fn default_base_url() -> String { String::from("/") } @@ -41,16 +38,10 @@ impl Config { } } -lazy_static! { - #[derive (Debug)] - static ref DATABASE: LicenseDatabase = { - // TODO: error handling and use log::info when done - // not sure if i should validate the unwrap since main won't start if there is an error... - let config = Config::from_env().unwrap(); - let db_path: std::path::PathBuf = std::path::PathBuf::from_str(&config.database).unwrap(); - let database: LicenseDatabase = LicenseDatabase::load_file(db_path.as_path()); - database - }; +#[derive(Debug, Clone)] +struct RunningConfig { + config: ServerConfig, + database: LicenseDatabase, } const ERROR_LICENSE_NOT_FOUND: &str = @@ -60,11 +51,17 @@ const ERROR_LICENSE_NOT_FOUND: &str = async fn main() -> Result<()> { log::start(); - match Config::from_env() { + match ServerConfig::from_env() { Ok(config) => { - let mut app = tide::new(); + // TODO: fix the borrow issue here + let run_config = RunningConfig { + config: config.clone(), + database: LicenseDatabase::load(config.database.clone()), + }; - create_routes(&mut app, &config); + let mut app = tide::with_state(run_config); + + create_routes(&mut app); app.listen(format!("{}:{}", config.server_ip, config.server_port)) .await?; @@ -75,8 +72,10 @@ async fn main() -> Result<()> { Ok(()) } -fn create_routes(server: &mut Server<()>, config: &Config) { - let mut base_route = server.at(&config.base_url); +fn create_routes(server: &mut Server) { + // TODO: figure out how to not need clone + let url = server.clone().state().config.base_url.clone(); + let mut base_route = server.at(&url); base_route.get(get_welcome_message); base_route.at(":license").get(get_requested_license); @@ -99,7 +98,7 @@ fn build_response(status: StatusCode, data: String) -> Response { response } -async fn get_welcome_message(req: tide::Request<()>) -> tide::Result { +async fn get_welcome_message(req: tide::Request) -> tide::Result { log::info!("{:?}", req); Ok(build_response( @@ -108,11 +107,11 @@ async fn get_welcome_message(req: tide::Request<()>) -> tide::Result { )) } -async fn get_license_list(req: tide::Request<()>) -> tide::Result { +async fn get_license_list(req: tide::Request) -> tide::Result { log::info!("{:?}", req); - // TODO: env var this - match DATABASE.get_licenses(5) { + // TODO: env var the chunks + match req.state().database.get_licenses(5) { Some(licenses) => Ok(build_response(StatusCode::Ok, format!("{}", licenses))), None => Ok(build_response( StatusCode::NotFound, @@ -121,10 +120,10 @@ async fn get_license_list(req: tide::Request<()>) -> tide::Result { } } -async fn get_detailed_license_list(req: tide::Request<()>) -> tide::Result { +async fn get_detailed_license_list(req: tide::Request) -> tide::Result { log::info!("{:?}", req); - match DATABASE.get_detailed_licenses() { + match req.state().database.get_detailed_licenses() { Some(licenses) => Ok(build_response(StatusCode::Ok, format!("{}", licenses))), None => Ok(build_response( StatusCode::NotFound, @@ -133,19 +132,17 @@ async fn get_detailed_license_list(req: tide::Request<()>) -> tide::Result) -> tide::Result { +async fn get_requested_license(req: tide::Request) -> tide::Result { log::info!("{:?}", req); - let config = Config::from_env().unwrap(); - // remove prefix from requested route // TODO: make this better let request = req.url().path().strip_prefix("/").unwrap_or(""); - let response = match DATABASE.get_license(request) { + let response = match req.state().database.get_license(request) { Some(license) => { // is there a better way to do this? - let source_dir = PathBuf::from(&config.database); + let source_dir = PathBuf::from(req.state().config.database.clone()); let source_dir = source_dir.parent().unwrap_or(Path::new("")); let mut license_file_path = PathBuf::from(source_dir); -- libgit2 1.7.2