use crate::{BoxedError, DefaultFuture, Error, FromRequest, NoContext};
use futures::{future::FutureResult, Future, IntoFuture};
use hyper::{
service::{MakeService, Service},
Body, Method, Request, Response,
};
use std::any::Any;
use std::fmt;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::Arc;
pub struct AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
handler: Arc<H>,
context: R::Context,
}
impl<H, R, F> AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest<Context = NoContext>,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
pub fn new(handler: H) -> Self {
Self::with_context(handler, NoContext)
}
}
impl<H, R, F> AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
pub fn with_context(handler: H, context: R::Context) -> Self {
Self {
handler: Arc::new(handler),
context,
}
}
}
impl<H, R, F> Clone for AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
context: self.context.clone(),
}
}
}
impl<C, H, R, F> MakeService<C> for AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
type ReqBody = Body;
type ResBody = Body;
type Error = BoxedError;
type Service = Self;
type Future = FutureResult<Self, BoxedError>;
type MakeError = BoxedError;
fn make_service(&mut self, _ctx: C) -> Self::Future {
Ok(self.clone()).into_future()
}
}
impl<H, R, F> Service for AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
type ReqBody = Body;
type ResBody = Body;
type Error = BoxedError;
type Future = DefaultFuture<Response<Body>, BoxedError>;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let is_head = req.method() == Method::HEAD;
let handler = self.handler.clone();
let (parts, body) = req.into_parts();
let req = Arc::new(Request::from_parts(parts, ()));
let fut = R::from_request_and_body(&req, body, self.context.clone())
.and_then(move |r| handler(r, req))
.map(move |response| {
if is_head {
response.map(|_| Body::empty())
} else {
response
}
})
.or_else(|err| {
if let Some(our_error) = err.downcast_ref::<Error>() {
Ok(our_error.response().map(|()| Body::empty()))
} else {
Err(err)
}
});
Box::new(fut)
}
}
impl<H, R, F> fmt::Debug for AsyncService<H, R, F>
where
H: Fn(R, Arc<Request<()>>) -> F + Send + Sync + 'static,
R: FromRequest,
R::Context: Clone + fmt::Debug,
R::Future: 'static,
F: Future<Item = Response<Body>, Error = BoxedError> + Send + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[derive(Debug)]
struct HandlerRef {
strong_count: usize,
weak_count: usize,
}
f.debug_struct("AsyncService")
.field(
"handler",
&HandlerRef {
strong_count: Arc::strong_count(&self.handler),
weak_count: Arc::weak_count(&self.handler),
},
)
.field("context", &self.context)
.finish()
}
}
pub struct SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone,
{
handler: Arc<H>,
context: R::Context,
}
impl<H, R> SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest<Context = NoContext> + Send + 'static,
{
pub fn new(handler: H) -> Self {
Self::with_context(handler, NoContext)
}
}
impl<H, R> SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone,
{
pub fn with_context(handler: H, context: R::Context) -> Self {
Self {
handler: Arc::new(handler),
context,
}
}
}
impl<H, R> Clone for SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
context: self.context.clone(),
}
}
}
impl<C, H, R> MakeService<C> for SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone,
{
type ReqBody = Body;
type ResBody = Body;
type Error = BoxedError;
type Service = Self;
type Future = FutureResult<Self, BoxedError>;
type MakeError = BoxedError;
fn make_service(&mut self, _ctx: C) -> Self::Future {
Ok(self.clone()).into_future()
}
}
impl<H, R> Service for SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone,
{
type ReqBody = Body;
type ResBody = Body;
type Error = BoxedError;
type Future = DefaultFuture<Response<Body>, BoxedError>;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let is_head = req.method() == Method::HEAD;
let handler = self.handler.clone();
let (parts, body) = req.into_parts();
let req = Arc::new(Request::from_parts(parts, ()));
let fut = R::from_request_and_body(&req, body, self.context.clone())
.and_then(move |route| {
crate::blocking(move || Ok(handler(route, req)))
})
.map(move |response| {
if is_head {
response.map(|_| Body::empty())
} else {
response
}
})
.or_else(|err| {
if let Some(our_error) = err.downcast_ref::<Error>() {
Ok(our_error.response().map(|()| Body::empty()))
} else {
Err(err)
}
});
Box::new(fut)
}
}
impl<H, R> fmt::Debug for SyncService<H, R>
where
H: Fn(R, Arc<Request<()>>) -> Response<Body> + Send + Sync + 'static,
R: FromRequest + Send + 'static,
R::Context: Clone + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[derive(Debug)]
struct HandlerRef {
strong_count: usize,
weak_count: usize,
}
f.debug_struct("SyncService")
.field(
"handler",
&HandlerRef {
strong_count: Arc::strong_count(&self.handler),
weak_count: Arc::weak_count(&self.handler),
},
)
.field("context", &self.context)
.finish()
}
}
pub trait ServiceExt: Service + Sized {
fn catch_unwind<H, R>(self, handler: H) -> CatchUnwind<Self, R, H>
where
Self: Service<ResBody = Body, Error = BoxedError> + Sync,
Self::Future: Send,
H: Fn(Box<dyn Any + Send>) -> R + Send + Sync + 'static,
R: IntoFuture<Item = Response<Body>, Error = BoxedError>,
R::Future: Send + 'static;
fn make_service_by_cloning(self) -> MakeServiceByCloning<Self>
where
Self: Clone;
}
impl<T: Service> ServiceExt for T {
fn catch_unwind<H, R>(self, handler: H) -> CatchUnwind<Self, R, H>
where
Self: Service<ResBody = Body, Error = BoxedError> + Sync,
Self::Future: Send,
H: Fn(Box<dyn Any + Send>) -> R + Send + Sync + 'static,
R: IntoFuture<Item = Response<Body>, Error = BoxedError>,
R::Future: Send + 'static,
{
CatchUnwind {
inner: self,
handler: Arc::new(handler),
}
}
fn make_service_by_cloning(self) -> MakeServiceByCloning<Self>
where
Self: Clone,
{
MakeServiceByCloning { service: self }
}
}
#[derive(Debug)]
pub struct CatchUnwind<S, R, H>
where
S: Service<ResBody = Body, Error = BoxedError> + Sync,
S::Future: Send + 'static,
R: IntoFuture<Item = Response<Body>, Error = BoxedError>,
R::Future: Send + 'static,
H: Fn(Box<dyn Any + Send>) -> R + Send + Sync + 'static,
{
inner: S,
handler: Arc<H>,
}
impl<S, R, H> Service for CatchUnwind<S, R, H>
where
S: Service<ResBody = Body, Error = BoxedError> + Sync,
S::Future: Send + 'static,
R: IntoFuture<Item = Response<Body>, Error = BoxedError>,
R::Future: Send + 'static,
H: Fn(Box<dyn Any + Send>) -> R + Send + Sync + 'static,
{
type ReqBody = S::ReqBody;
type ResBody = Body;
type Error = BoxedError;
type Future = DefaultFuture<Response<Body>, BoxedError>;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let handler = self.handler.clone();
let inner_future = match catch_unwind(AssertUnwindSafe(move || self.inner.call(req))) {
Ok(future) => future,
Err(panic_payload) => return Box::new(handler(panic_payload).into_future()),
};
Box::new(AssertUnwindSafe(inner_future)
.catch_unwind()
.then(move |panic_result| -> Box<dyn Future<Item=Response<Body>, Error = BoxedError>
+ Send> {
match panic_result {
Ok(result) => Box::new(result.into_future()),
Err(panic_payload) => Box::new(handler(panic_payload).into_future()),
}
}),
)
}
}
impl<S, R, H> Clone for CatchUnwind<S, R, H>
where
S: Service<ResBody = Body, Error = BoxedError> + Clone + Sync,
S::Future: Send + 'static,
R: IntoFuture<Item = Response<Body>, Error = BoxedError>,
R::Future: Send + 'static,
H: Fn(Box<dyn Any + Send>) -> R + Send + Sync + 'static,
{
fn clone(&self) -> Self {
CatchUnwind {
inner: self.inner.clone(),
handler: self.handler.clone(),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct MakeServiceByCloning<S: Service + Clone> {
service: S,
}
impl<Ctx, S: Service + Clone> MakeService<Ctx> for MakeServiceByCloning<S> {
type ReqBody = S::ReqBody;
type ResBody = S::ResBody;
type Error = S::Error;
type Service = S;
type Future = FutureResult<S, Self::MakeError>;
type MakeError = BoxedError;
fn make_service(&mut self, _ctx: Ctx) -> Self::Future {
Ok(self.service.clone()).into_future()
}
}