use std::marker::PhantomData;
use crate::error::Failure;
use crate::service::{Ctx, Middleware, Service, ServiceFactory};
use crate::web::{AppState, WebError, WebRequest, WebResponse, WebResponseError};
#[derive(Debug, Clone)]
pub struct WebStack<St, Inner, Outer> {
inner: Inner,
outer: Outer,
err: PhantomData<St>,
}
impl<St, Inner, Outer> WebStack<St, Inner, Outer> {
pub fn new(inner: Inner, outer: Outer) -> Self {
WebStack {
inner,
outer,
err: PhantomData,
}
}
}
impl<S, St, Inner, Outer> Middleware<S, St> for WebStack<St, Inner, Outer>
where
St: AppState,
Inner: Middleware<S, St>,
Outer: Middleware<Inner::Service, St>,
{
type Service = WebMiddleware<Outer::Service, St>;
fn create(&self, st: &St, service: S) -> Self::Service {
WebMiddleware {
svc: self.outer.create(st, self.inner.create(st, service)),
err: PhantomData,
}
}
}
#[derive(Debug)]
pub struct WebMiddleware<S, St> {
svc: S,
err: PhantomData<St>,
}
impl<S, St> Clone for WebMiddleware<S, St>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
svc: self.svc.clone(),
err: PhantomData,
}
}
}
impl<S, St, In> Service<St, WebRequest<In>> for WebMiddleware<S, St>
where
S: Service<St, WebRequest<In>, Res = WebResponse>,
S::Error: WebResponseError<St, St::Error>,
St: AppState,
{
type Res = WebResponse;
type Error = WebError<St, St::Error>;
#[inline]
async fn call(
&self,
req: WebRequest<In>,
ctx: Ctx<'_, Self, St>,
) -> Result<Self::Res, Self::Error> {
ctx.call(&self.svc, req).await.map_err(WebError::from_err)
}
crate::forward_ready!(St, svc, WebError::from_err);
crate::forward_shutdown!(St, svc);
}
#[derive(derive_more::Debug)]
#[debug("Filter")]
pub struct Filter<St, In>(PhantomData<(St, In)>);
impl<St, In> Filter<St, In> {
pub(super) fn new() -> Self {
Filter(PhantomData)
}
}
impl<St: AppState, In> ServiceFactory<St, WebRequest<In>> for Filter<St, In> {
type Res = WebRequest<In>;
type Error = WebError<St, St::Error>;
type Service = Filter<St, In>;
type InitError = Failure;
async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
Ok(Filter(PhantomData))
}
}
impl<St: AppState, In> Service<St, WebRequest<In>> for Filter<St, In> {
type Res = WebRequest<In>;
type Error = WebError<St, St::Error>;
async fn call(
&self,
req: WebRequest<In>,
_: Ctx<'_, Self, St>,
) -> Result<Self::Res, Self::Error> {
Ok(req)
}
}