use std::{
convert::Infallible,
task::{Context, Poll},
};
use futures::{future::BoxFuture, FutureExt};
use http::{Request, Response};
use http_api_problem::ApiError;
use hyper::Body;
use manas_http::service::BoxHttpResponseFuture;
use tower::{Service, ServiceExt};
pub mod common;
pub mod delete;
pub mod get;
pub mod head;
pub mod post;
pub mod put_or_patch;
#[derive(Debug, Clone)]
pub struct MethodService<BaseMethodSvc, Marshaller> {
pub base_method_svc: BaseMethodSvc,
pub marshaller: Marshaller,
}
impl<BaseMethodSvc, Marshaller> Service<Request<Body>> for MethodService<BaseMethodSvc, Marshaller>
where
BaseMethodSvc: BaseMethodService,
Marshaller: BaseResponseMarshaller<BaseMethodSvc::BaseResponse>,
{
type Response = Response<Body>;
type Error = Infallible;
type Future = BoxHttpResponseFuture<Body>;
#[inline]
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
#[inline]
fn call(&mut self, req: Request<Body>) -> Self::Future {
let marshaller = self.marshaller.clone();
Box::pin(
self.base_method_svc
.clone()
.oneshot(req)
.then(move |base_result| marshaller.oneshot(base_result)),
)
}
}
pub trait BaseMethodService:
Service<
Request<Body>,
Response = Self::BaseResponse,
Error = ApiError,
Future = BoxFuture<'static, Result<Self::BaseResponse, ApiError>>,
> + Clone
+ Send
+ 'static
{
type BaseResponse: Send + 'static;
}
impl<BR, S> BaseMethodService for S
where
S: Service<
Request<Body>,
Response = BR,
Error = ApiError,
Future = BoxFuture<'static, Result<BR, ApiError>>,
> + Clone
+ Send
+ 'static,
BR: Send + 'static,
{
type BaseResponse = BR;
}
pub trait BaseResponseMarshaller<R>:
Service<
Result<R, ApiError>,
Response = Response<Body>,
Error = Infallible,
Future = BoxHttpResponseFuture<Body>,
> + Clone
+ Send
+ 'static
{
}
impl<BR, S> BaseResponseMarshaller<BR> for S where
S: Service<
Result<BR, ApiError>,
Response = Response<Body>,
Error = Infallible,
Future = BoxHttpResponseFuture<Body>,
> + Clone
+ Send
+ 'static
{
}