diff options
Diffstat (limited to 'src/script.rs')
-rw-r--r-- | src/script.rs | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/script.rs b/src/script.rs new file mode 100644 index 0000000..369fbf8 --- /dev/null +++ b/src/script.rs @@ -0,0 +1,94 @@ +use std::{env, collections::HashMap, fs::read_to_string, process::Command, result::Result, error::Error}; + +use crate::http::{response::Response, method::Method}; + +pub struct Script { + path: String +} + +impl Script { + fn new(path: String) -> Self { + Self { path } + } + + pub fn run(&self, body: Option<&String>) -> Result<Response, std::io::Error> { + let mut res = Response::new(); + + let mut command = Command::new(&self.path); + if let Some(body) = body { + command.args([body]); + } + + let output = match command.output() { + Ok(output) => output, + Err(err) => return Err(err) + }; + + let status = output.status.code().unwrap_or(500) as u16; + + let response = String::from_utf8_lossy(&output.stdout).into_owned(); + let mut lines = response.split('\n').into_iter(); + + res.headers.serialize(&mut lines); + + let body: String = lines.collect::<Vec<&str>>().join("\n"); + if body.len() > 0 { + res.body = Some(body); + } + + res.status = status; + + Ok(res) + } +} + +pub struct Config { + map: HashMap<String, Script> +} + +impl Config { + + fn key(method: &Method, route: &str) -> String { + format!("{}:{}", method.deserialize(), route) + } + + pub fn load() -> Result<Self, Box<dyn Error>> { + + let config_path = env::var("CONFIG_PATH").unwrap_or_else(|_| String::from("config")); + let config = read_to_string(&config_path)?; + + let mut map = HashMap::new(); + let lines = config.split("\n").into_iter(); + + for (i, line) in lines.enumerate() { + let mut parts = line.split_whitespace(); + + let Some(method_str) = parts.next() else { continue }; + let method = Method::serialize(&method_str) + .ok_or(format!("config line {i} has invalid http method: {method_str}"))?; + + let route = parts.next() + .ok_or(format!("config line {i} missing http route"))?; + + let script = parts.next() + .ok_or(format!{"config line {i} missing script path"})?; + + let key = Self::key(&method, route); + let value = Script::new(script.to_owned()); + + println!("adding script {script} for {} {route}", method.deserialize()); + map.insert(key, value); + } + + if map.len() < 1 { + return Err("cannot run server, config is empty".into()) + } + + Ok(Self { map }) + } + + pub fn get(&self, method: &Method, route: &str) -> Option<&Script> { + self.map.get(&Self::key(method, route)) + } + +} |