use crate::service::Service;
pub struct WebContext;
impl<S, E> Service<Result<S, E>> for WebContext {
type Response = service::WebContextService<S>;
type Error = E;
async fn call(&self, res: Result<S, E>) -> Result<Self::Response, Self::Error> {
res.map(|service| service::WebContextService { service })
}
}
mod service {
use core::{cell::RefCell, convert::Infallible};
use xitca_http::util::middleware::context::Context;
use crate::{
body::{Either, ResponseBody},
context::WebContext,
http::{WebRequest, WebResponse},
service::{Service, ready::ReadyService},
};
pub struct WebContextService<S> {
pub(super) service: S,
}
type EitherResBody<B> = Either<B, ResponseBody>;
impl<'c, S, C, ResB, SE> Service<Context<'c, WebRequest, C>> for WebContextService<S>
where
S: for<'r> Service<WebContext<'r, C>, Response = WebResponse<ResB>, Error = SE>,
SE: for<'r> Service<WebContext<'r, C>, Response = WebResponse, Error = Infallible>,
{
type Response = WebResponse<EitherResBody<ResB>>;
type Error = Infallible;
async fn call(&self, ctx: Context<'c, WebRequest, C>) -> Result<Self::Response, Self::Error> {
let (req, state) = ctx.into_parts();
let (parts, ext) = req.into_parts();
let (ext, body) = ext.replace_body(());
let mut req = WebRequest::from_parts(parts, ext);
let mut body = RefCell::new(body);
let mut ctx = WebContext::new(&mut req, &mut body, state);
match self.service.call(ctx.reborrow()).await {
Ok(res) => Ok(res.map(Either::left)),
Err(e) => e.call(ctx).await.map(|res| res.map(Either::right)),
}
}
}
impl<S> ReadyService for WebContextService<S>
where
S: ReadyService,
{
type Ready = S::Ready;
#[inline]
async fn ready(&self) -> Self::Ready {
self.service.ready().await
}
}
}