From ab0cfcf09a51d7f633c4d6f9df51c4ebe35652b4 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sun, 12 Aug 2018 23:58:52 -0700 Subject: [PATCH] i might need to change the entire thing tomorrow but im done for now --- src/handler.rs | 5 -- src/handlers/git.rs | 20 +++++++ src/handlers/mod.rs | 12 ++++ src/handlers/script.rs | 18 ++++++ src/hook.rs | 4 +- src/lib.rs | 121 ++++++++++++++++++++++------------------- 6 files changed, 118 insertions(+), 62 deletions(-) delete mode 100644 src/handler.rs create mode 100644 src/handlers/git.rs create mode 100644 src/handlers/mod.rs create mode 100644 src/handlers/script.rs diff --git a/src/handler.rs b/src/handler.rs deleted file mode 100644 index a4c35f4..0000000 --- a/src/handler.rs +++ /dev/null @@ -1,5 +0,0 @@ -use hyper::{Body, Request, Response}; - -pub trait Handler: Send + Sync { - fn handle(&self, payload: &Request) -> Option>; -} diff --git a/src/handlers/git.rs b/src/handlers/git.rs new file mode 100644 index 0000000..ac58d5a --- /dev/null +++ b/src/handlers/git.rs @@ -0,0 +1,20 @@ +use toml::Value; +use failure::Error; +use hyper::{Body, Request, Response, Method}; + +use handlers::Handler; + +pub struct GithubHandler {} + +impl GithubHandler { + pub fn new() -> Self { + GithubHandler {} + } +} + +impl Handler for GithubHandler { + fn handle(&self, req: &Request) -> Result, Error> { + if req.method() != Method::POST { bail!("Github webhooks should use the POST method.") } + Ok(Response::new(Body::from("Lol"))) + } +} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs new file mode 100644 index 0000000..baa22d5 --- /dev/null +++ b/src/handlers/mod.rs @@ -0,0 +1,12 @@ +mod git; +mod script; + +use failure::Error; +use hyper::{Body, Request, Response}; + +pub use self::git::*; +pub use self::script::*; + +pub trait Handler: Send + Sync { + fn handle(&self, &Request) -> Result, Error>; +} diff --git a/src/handlers/script.rs b/src/handlers/script.rs new file mode 100644 index 0000000..d8be4d6 --- /dev/null +++ b/src/handlers/script.rs @@ -0,0 +1,18 @@ +use failure::Error; +use hyper::{Body, Request, Response}; + +use handlers::Handler; + +pub struct ScriptHandler {} + +impl ScriptHandler { + pub fn new() -> Self { + ScriptHandler {} + } +} + +impl Handler for ScriptHandler { + fn handle(&self, req: &Request) -> Result, Error> { + Ok(Response::new(Body::from("Lol"))) + } +} diff --git a/src/hook.rs b/src/hook.rs index 58048ca..47b7529 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -16,7 +16,7 @@ impl Hook { .to_owned(); Ok(Hook { handler_type }) } - pub fn handle(&self, payload: &Request) -> Option> { - None + pub fn handle(&self, payload: &Request) -> Result, Error> { + Ok(Response::new(Body::from("lol"))) } } diff --git a/src/lib.rs b/src/lib.rs index 4c610bd..942be97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate failure; extern crate hyper; #[macro_use] @@ -7,7 +8,7 @@ extern crate regex; extern crate toml; extern crate walkdir; -mod handler; +mod handlers; mod hook; use std::collections::HashMap; @@ -27,13 +28,14 @@ use regex::Regex; use toml::Value; use walkdir::WalkDir; -use handler::*; +use handlers::*; use hook::*; +const URIPATTERN_STR: &str = r"/webhook/(?P[A-Za-z._][A-Za-z0-9._]*)"; + lazy_static! { - static ref URIPATTERN: Regex = - Regex::new(r"/webhook/(?P[A-Za-z_][A-Za-z0-9_]*)").unwrap(); - static ref HANDLERS: HashMap> = HashMap::new(); + static ref URIPATTERN: Regex = Regex::new(URIPATTERN_STR).unwrap(); + static ref HANDLERS: Mutex>> = Mutex::new(HashMap::new()); static ref HOOKS: Mutex> = Mutex::new(HashMap::new()); } @@ -50,27 +52,28 @@ const NOTFOUND: &str = r#" "#; -fn service_fn(req: Request) -> Option> { - let captures = match URIPATTERN.captures(req.uri().path()) { - Some(value) => value, - None => return None, - }; - let name = match captures.name("name") { - Some(name) => name.as_str(), - None => return None, - }; +fn service_fn(req: &Request) -> Result, Error> { + let captures = URIPATTERN + .captures(req.uri().path()) + .ok_or(err_msg("Did not match url pattern"))?; + let name = captures + .name("name") + .ok_or(err_msg("Missing name"))? + .as_str(); let hooks = HOOKS.lock().unwrap(); - let handler = match hooks.get(name) { - Some(handler) => handler, - None => return None, - }; + let handler = hooks + .get(name) + .ok_or(err_msg(format!("Hook '{}' doesn't exist", name)))?; handler.handle(&req) } fn service_fn_wrapper(req: Request) -> Response { - match service_fn(req) { - Some(response) => response, - None => Response::new(Body::from(NOTFOUND)), + match service_fn(&req) { + Ok(response) => response, + Err(err) => { + eprintln!("Got error from '{}': {}", req.uri().path(), err); + Response::new(Body::from(NOTFOUND)) + } } } @@ -80,41 +83,49 @@ where { println!("Reloading config..."); // hold on to the lock while config is being reloaded - let mut hooks = HOOKS.lock().unwrap(); - hooks.clear(); - let hooks_dir = { - let mut p = root.as_ref().to_path_buf(); - p.push("hooks"); - p - }; - if hooks_dir.exists() { - for entry in WalkDir::new(hooks_dir) { - let path = match entry.as_ref().map(|e| e.path()) { - Ok(path) => path, - _ => continue, - }; - if !path.is_file() { - continue; - } - match (|path: &Path| -> Result<(), Error> { - let filename = path - .file_name() - .ok_or(err_msg("what the fuck bro"))? - .to_str() - .ok_or(err_msg("???"))? - .to_owned(); - let mut file = File::open(path)?; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; + { + let mut handlers = HANDLERS.lock().unwrap(); + handlers.clear(); + handlers.insert("github".to_owned(), Box::new(handlers::GithubHandler::new())); + } + { + let mut hooks = HOOKS.lock().unwrap(); + hooks.clear(); + let hooks_dir = { + let mut p = root.as_ref().to_path_buf(); + p.push("hooks"); + p + }; + if hooks_dir.exists() { + for entry in WalkDir::new(hooks_dir) { + let path = match entry.as_ref().map(|e| e.path()) { + Ok(path) => path, + _ => continue, + }; + if !path.is_file() { + continue; + } + match (|path: &Path| -> Result<(), Error> { + let filename = path + .file_name() + .ok_or(err_msg("what the fuck bro"))? + .to_str() + .ok_or(err_msg("???"))? + .to_owned(); + let mut file = File::open(path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; - let config = contents.parse::()?; - let hook = Hook::from(&config)?; - hooks.insert(filename, hook); - Ok(()) - })(path) - { - Ok(_) => (), - Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err), + let config = contents.parse::()?; + let hook = Hook::from(&config)?; + println!("Added hook '{}'", filename); + hooks.insert(filename, hook); + Ok(()) + })(path) + { + Ok(_) => (), + Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err), + } } } }