dip/src/service.rs
2018-09-01 14:56:58 -05:00

84 lines
2.7 KiB
Rust

use std::collections::HashMap;
use futures::{future, Future, Stream};
use hyper::{Body, Error, Request, Response, StatusCode};
use mktemp::Temp;
use {HOOKS, URIPATTERN};
pub(crate) fn dip_service(
req: Request<Body>,
) -> Box<Future<Item = Response<Body>, Error = Error> + Send> {
let path = req.uri().path().to_owned();
let captures = match URIPATTERN.captures(path.as_ref()) {
Some(value) => value,
None => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("not found"))
.unwrap(),
))
}
};
let name = match captures.name("name") {
Some(value) => value.as_str().to_owned(),
None => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("not found"))
.unwrap(),
))
}
};
// TODO: filter by method as well
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::<HashMap<_, _>>();
let method = req.method().as_str().to_owned();
// spawn job
Box::new(req.into_body().concat2().map(move |body| {
let body = String::from_utf8(body.to_vec()).unwrap();
let req_obj = json!({
"body": body,
"headers": headers,
"method": method,
});
let hooks = HOOKS.lock().unwrap();
{
let mut temp_dir = Temp::new_dir().unwrap();
let temp_path = temp_dir.to_path_buf();
assert!(temp_path.exists());
let hook = match hooks.get(&name) {
Some(hook) => hook,
None => {
temp_dir.release();
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("not found"))
.unwrap_or_else(|_| Response::new(Body::from("not found")));
}
};
let (code, msg) = match hook.handle(req_obj, temp_path) {
Ok(msg) => (StatusCode::ACCEPTED, msg),
Err(msg) => (StatusCode::BAD_REQUEST, msg),
};
temp_dir.release();
Response::builder()
.status(code)
.body(Body::from(msg))
.unwrap_or_else(|err| Response::new(Body::from(format!("{}", err))))
}
}))
}