i might need to change the entire thing tomorrow but im done for now

This commit is contained in:
Michael Zhang 2018-08-12 23:58:52 -07:00
parent 8042d2d19a
commit ab0cfcf09a
No known key found for this signature in database
GPG key ID: A1B65B603268116B
6 changed files with 118 additions and 62 deletions

View file

@ -1,5 +0,0 @@
use hyper::{Body, Request, Response};
pub trait Handler: Send + Sync {
fn handle(&self, payload: &Request<Body>) -> Option<Response<Body>>;
}

20
src/handlers/git.rs Normal file
View file

@ -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<Body>) -> Result<Response<Body>, Error> {
if req.method() != Method::POST { bail!("Github webhooks should use the POST method.") }
Ok(Response::new(Body::from("Lol")))
}
}

12
src/handlers/mod.rs Normal file
View file

@ -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<Body>) -> Result<Response<Body>, Error>;
}

18
src/handlers/script.rs Normal file
View file

@ -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<Body>) -> Result<Response<Body>, Error> {
Ok(Response::new(Body::from("Lol")))
}
}

View file

@ -16,7 +16,7 @@ impl Hook {
.to_owned(); .to_owned();
Ok(Hook { handler_type }) Ok(Hook { handler_type })
} }
pub fn handle(&self, payload: &Request<Body>) -> Option<Response<Body>> { pub fn handle(&self, payload: &Request<Body>) -> Result<Response<Body>, Error> {
None Ok(Response::new(Body::from("lol")))
} }
} }

View file

@ -1,3 +1,4 @@
#[macro_use]
extern crate failure; extern crate failure;
extern crate hyper; extern crate hyper;
#[macro_use] #[macro_use]
@ -7,7 +8,7 @@ extern crate regex;
extern crate toml; extern crate toml;
extern crate walkdir; extern crate walkdir;
mod handler; mod handlers;
mod hook; mod hook;
use std::collections::HashMap; use std::collections::HashMap;
@ -27,13 +28,14 @@ use regex::Regex;
use toml::Value; use toml::Value;
use walkdir::WalkDir; use walkdir::WalkDir;
use handler::*; use handlers::*;
use hook::*; use hook::*;
const URIPATTERN_STR: &str = r"/webhook/(?P<name>[A-Za-z._][A-Za-z0-9._]*)";
lazy_static! { lazy_static! {
static ref URIPATTERN: Regex = static ref URIPATTERN: Regex = Regex::new(URIPATTERN_STR).unwrap();
Regex::new(r"/webhook/(?P<name>[A-Za-z_][A-Za-z0-9_]*)").unwrap(); static ref HANDLERS: Mutex<HashMap<String, Box<Handler>>> = Mutex::new(HashMap::new());
static ref HANDLERS: HashMap<String, Box<Handler>> = HashMap::new();
static ref HOOKS: Mutex<HashMap<String, Hook>> = Mutex::new(HashMap::new()); static ref HOOKS: Mutex<HashMap<String, Hook>> = Mutex::new(HashMap::new());
} }
@ -50,27 +52,28 @@ const NOTFOUND: &str = r#"<html>
</body> </body>
</html>"#; </html>"#;
fn service_fn(req: Request<Body>) -> Option<Response<Body>> { fn service_fn(req: &Request<Body>) -> Result<Response<Body>, Error> {
let captures = match URIPATTERN.captures(req.uri().path()) { let captures = URIPATTERN
Some(value) => value, .captures(req.uri().path())
None => return None, .ok_or(err_msg("Did not match url pattern"))?;
}; let name = captures
let name = match captures.name("name") { .name("name")
Some(name) => name.as_str(), .ok_or(err_msg("Missing name"))?
None => return None, .as_str();
};
let hooks = HOOKS.lock().unwrap(); let hooks = HOOKS.lock().unwrap();
let handler = match hooks.get(name) { let handler = hooks
Some(handler) => handler, .get(name)
None => return None, .ok_or(err_msg(format!("Hook '{}' doesn't exist", name)))?;
};
handler.handle(&req) handler.handle(&req)
} }
fn service_fn_wrapper(req: Request<Body>) -> Response<Body> { fn service_fn_wrapper(req: Request<Body>) -> Response<Body> {
match service_fn(req) { match service_fn(&req) {
Some(response) => response, Ok(response) => response,
None => Response::new(Body::from(NOTFOUND)), Err(err) => {
eprintln!("Got error from '{}': {}", req.uri().path(), err);
Response::new(Body::from(NOTFOUND))
}
} }
} }
@ -80,41 +83,49 @@ where
{ {
println!("Reloading config..."); println!("Reloading config...");
// hold on to the lock while config is being reloaded // hold on to the lock while config is being reloaded
let mut hooks = HOOKS.lock().unwrap(); {
hooks.clear(); let mut handlers = HANDLERS.lock().unwrap();
let hooks_dir = { handlers.clear();
let mut p = root.as_ref().to_path_buf(); handlers.insert("github".to_owned(), Box::new(handlers::GithubHandler::new()));
p.push("hooks"); }
p {
}; let mut hooks = HOOKS.lock().unwrap();
if hooks_dir.exists() { hooks.clear();
for entry in WalkDir::new(hooks_dir) { let hooks_dir = {
let path = match entry.as_ref().map(|e| e.path()) { let mut p = root.as_ref().to_path_buf();
Ok(path) => path, p.push("hooks");
_ => continue, p
}; };
if !path.is_file() { if hooks_dir.exists() {
continue; for entry in WalkDir::new(hooks_dir) {
} let path = match entry.as_ref().map(|e| e.path()) {
match (|path: &Path| -> Result<(), Error> { Ok(path) => path,
let filename = path _ => continue,
.file_name() };
.ok_or(err_msg("what the fuck bro"))? if !path.is_file() {
.to_str() continue;
.ok_or(err_msg("???"))? }
.to_owned(); match (|path: &Path| -> Result<(), Error> {
let mut file = File::open(path)?; let filename = path
let mut contents = String::new(); .file_name()
file.read_to_string(&mut contents)?; .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::<Value>()?; let config = contents.parse::<Value>()?;
let hook = Hook::from(&config)?; let hook = Hook::from(&config)?;
hooks.insert(filename, hook); println!("Added hook '{}'", filename);
Ok(()) hooks.insert(filename, hook);
})(path) Ok(())
{ })(path)
Ok(_) => (), {
Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err), Ok(_) => (),
Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err),
}
} }
} }
} }