use std::sync::Arc;
use proto::{HyperRequest, HyperResponse};
use futures::Future;
use prelude::*;
pub struct Writium {
ns: Arc<Namespace>,
}
impl Writium {
pub fn new() -> Writium {
Writium {
ns: Arc::new(Namespace::new(&[])),
}
}
pub fn route(&self, req: HyperRequest)
-> Box<Future<Item=HyperResponse, Error=::hyper::Error>> {
let (method, uri, _version, headers, body) = req.deconstruct();
use futures::Stream;
let ns = self.ns.clone();
let f_res = body
.concat2()
.map(move |body| {
let mut req = Request::new(method);
req.set_headers(headers);
req.set_body(body.to_vec());
req.set_uri(&uri);
match ns.route(&mut req) {
Ok(res) => res.into(),
Err(err) => {
let mut log = Vec::<String>::new();
if err.status().is_server_error() {
log.push(format!("Unexpected error occured: {}", err));
let mut err: &::std::error::Error = &err;
loop {
if let Some(cause) = err.cause() {
log.push(format!("\tBy: {}", cause));
err = cause;
} else {
break
}
}
warn!("{}", log.join("\n"));
} else if err.status().is_client_error() {
warn!("Bad request induced an error: {}", err);
}
err.into()
},
}
});
Box::new(f_res)
}
pub fn bind<A: Api + 'static>(&mut self, api: A) {
Arc::make_mut(&mut self.ns).bind(api)
}
}