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),
+ }
}
}
}