use super::{Request, Response};
use hyper::{
self,
header::{HeaderValue, SERVER},
rt::Future,
service::Service,
Body,
Error,
};
use proto::{ArcHandler, ArcService};
use std::{mem, net::SocketAddr, panic::AssertUnwindSafe};
pub(crate) struct RootService {
pub(crate) remote_ip: Option<SocketAddr>,
pub(crate) service: ArcHandler,
}
impl Service for RootService {
type ReqBody = Body;
type ResBody = Body;
type Error = Error;
type Future = Box<Future<Item = hyper::Response<Body>, Error = Self::Error> + Send>;
fn call(&mut self, req: hyper::Request<Self::ReqBody>) -> Self::Future {
let mut request: Request = req.into();
request.remote = mem::replace(&mut self.remote_ip, None);
let res = Response::new();
let responseFuture = AssertUnwindSafe(self.service.call(request, res)).catch_unwind();
let responseFuture = responseFuture.then(|result| {
match result {
Ok(response) => {
match response {
Ok(mut res) | Err(mut res) => {
res.headers_mut().insert(
SERVER,
HeaderValue::from_static(concat!(
"Arc-Reactor/{}",
env!("CARGO_PKG_VERSION")
)),
);
Ok(res.into())
}
}
}
Err(err) => {
error!("Service pannicked {:?}", err);
let res = hyper::Response::builder()
.status(500)
.body(Body::empty())
.unwrap();
Ok(res)
}
}
});
return Box::new(responseFuture);
}
}