summaryrefslogtreecommitdiff
path: root/src/script.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/script.rs94
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))
+ }
+
+}