diff --git a/examples/github.rs b/examples/github.rs index 21c10e9..d0c1119 100644 --- a/examples/github.rs +++ b/examples/github.rs @@ -54,8 +54,7 @@ fn main() -> Result<(), Error> { let secret = GenericArray::from_iter(config.secret.bytes()); let mut mac = Hmac::::new(&secret); mac.input(payload.body.as_bytes()); - let signature = mac - .result() + let signature = mac.result() .code() .into_iter() .map(|b| format!("{:02x}", b)) diff --git a/src/hook.rs b/src/hook.rs index 0844f68..f1676a8 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -31,8 +31,7 @@ impl Hook { where P: AsRef, { - let filename = path - .as_ref() + let filename = path.as_ref() .file_name() .ok_or(err_msg("what the fuck bro"))? .to_str() diff --git a/src/lib.rs b/src/lib.rs index 20d29bd..f080ece 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,8 @@ #[macro_use] extern crate failure; -extern crate hyper; extern crate futures; +extern crate hyper; extern crate serde; #[macro_use] extern crate serde_json; @@ -17,6 +17,7 @@ extern crate walkdir; pub mod config; pub mod handler; pub mod hook; +pub mod service; use std::collections::HashMap; use std::net::SocketAddrV4; @@ -28,8 +29,8 @@ use std::time::Duration; use failure::{err_msg, Error}; use hyper::rt::Future; -use hyper::service::service_fn_ok; -use hyper::{Body, Request, Response, Server, StatusCode}; +use hyper::service::service_fn; +use hyper::Server; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use regex::Regex; use walkdir::WalkDir; @@ -37,68 +38,19 @@ use walkdir::WalkDir; pub use config::Config; pub use handler::*; use hook::*; +use service::*; const URIPATTERN_STR: &str = r"/webhook/(?P[A-Za-z._][A-Za-z0-9._]*)"; lazy_static! { static ref URIPATTERN: Regex = Regex::new(URIPATTERN_STR).unwrap(); - static ref HANDLERS: Mutex>> = Mutex::new(HashMap::new()); + // static ref HANDLERS: Mutex>> = Mutex::new(HashMap::new()); static ref PROGRAMS: Mutex> = Mutex::new(HashMap::new()); static ref HOOKS: Mutex> = Mutex::new(HashMap::new()); } const NOTFOUND: &str = "

Looks like you took a wrong turn!

There's nothing to see here.

"; -fn service_fn(req: Request) -> Result, Error> { - let path = req.uri().path().to_owned(); - let captures = URIPATTERN - .captures(path.as_ref()) - .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 hook = hooks - .get(name) - .ok_or(err_msg(format!("Hook '{}' doesn't exist", name)))?; - - let req_obj = { - let headers = req - .headers() - .clone() - .into_iter() - .filter_map(|(k, v)| { - let key = k.unwrap().as_str().to_owned(); - v.to_str().map(|value| (key, value.to_owned())).ok() - }).collect::>(); - let method = req.method().as_str().to_owned(); - // probably not idiomatically the best way to do it - // i was just trying to get something working - let body = "wip".to_owned(); - json!({ - "body": body, - "headers": headers, - "method": method, - }) - }; - hook.iter() - .fold(Ok(req_obj), |prev, handler| { - prev.and_then(|val| handler.run(val)) - }).map(|_| Response::new(Body::from("success"))) -} - -fn service_fn_wrapper(req: Request) -> Response { - let uri = req.uri().path().to_owned(); - service_fn(req).unwrap_or_else(|err| { - eprintln!("Error from '{}': {}", uri, err); - Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::from(NOTFOUND)) - .unwrap() - }) -} - fn load_config

(root: P) where P: AsRef, @@ -123,8 +75,7 @@ where if !path.is_file() { continue; } - match path - .file_name() + match path.file_name() .and_then(|s| s.to_str()) .ok_or(err_msg("???")) .map(|s| { @@ -197,7 +148,7 @@ pub fn run(config: &Config) -> Result<(), Error> { let addr: SocketAddrV4 = SocketAddrV4::from_str(config.bind.as_ref())?; let server = Server::bind(&addr.into()) - .serve(|| service_fn_ok(service_fn_wrapper)) + .serve(|| service_fn(dip_service)) .map_err(|e| eprintln!("server error: {}", e)); println!("Listening on {:?}", addr); hyper::rt::run(server); diff --git a/src/service.rs b/src/service.rs new file mode 100644 index 0000000..b81011b --- /dev/null +++ b/src/service.rs @@ -0,0 +1,60 @@ +use std::collections::HashMap; + +use failure::{err_msg, Error}; +use futures::{future, Future}; +use hyper::{Body, Request, Response, StatusCode}; + +use {HOOKS, NOTFOUND, URIPATTERN}; + +fn service_fn(req: Request) -> Result, Error> { + let path = req.uri().path().to_owned(); + let captures = URIPATTERN + .captures(path.as_ref()) + .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 hook = hooks + .get(name) + .ok_or(err_msg(format!("Hook '{}' doesn't exist", name)))?; + + let req_obj = { + let headers = req.headers() + .clone() + .into_iter() + .filter_map(|(k, v)| { + let key = k.unwrap().as_str().to_owned(); + v.to_str().map(|value| (key, value.to_owned())).ok() + }) + .collect::>(); + let method = req.method().as_str().to_owned(); + // probably not idiomatically the best way to do it + // i was just trying to get something working + let body = "wip".to_owned(); + json!({ + "body": body, + "headers": headers, + "method": method, + }) + }; + hook.iter() + .fold(Ok(req_obj), |prev, handler| { + prev.and_then(|val| handler.run(val)) + }) + .map(|_| Response::new(Body::from("success"))) +} + +pub fn dip_service( + req: Request, +) -> Box, Error = String> + Send> { + let uri = req.uri().path().to_owned(); + Box::new(future::ok(service_fn(req).unwrap_or_else(|err| { + eprintln!("Error from '{}': {}", uri, err); + Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::from(NOTFOUND)) + .unwrap() + }))) +}