use axum::{extract::Request, response::Response};
use future::{AsyncResponseFuture, ResponseFuture};
use futures_util::StreamExt;
pub use layer::{AsyncFilterExLayer, FilterExLayer};
pub use predicate::{AsyncPredicate, Predicate};
use std::{
marker::PhantomData,
task::{Context, Poll},
};
use tower::Service;
mod future;
mod layer;
mod predicate;
#[derive(Debug)]
pub struct FilterEx<T, U> {
inner: T,
predicate: U,
}
impl<T: Clone, U: Clone> Clone for FilterEx<T, U> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
predicate: self.predicate.clone(),
}
}
}
impl<T, U: Clone> FilterEx<T, U> {
pub fn new(inner: T, predicate: U) -> Self {
Self { inner, predicate }
}
pub fn layer(predicate: U) -> FilterExLayer<U> {
FilterExLayer::new(predicate)
}
pub fn check<R>(&mut self, request: R) -> Result<U::Request, U::Response>
where
U: Predicate<R>,
{
self.predicate.check(request)
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T, U> Service<Request> for FilterEx<T, U>
where
T: Service<U::Request, Response = Response>,
U: Predicate<Request, Response = Response>,
{
type Response = T::Response;
type Error = T::Error;
type Future = ResponseFuture<T::Future>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request) -> Self::Future {
match self.predicate.check(req) {
Ok(req) => ResponseFuture::Future {
future: self.inner.call(req),
},
Err(response) => ResponseFuture::Error {
response: Some(response),
},
}
}
}
#[derive(Debug)]
pub struct AsyncFilterEx<T, U, R>
where
U: AsyncPredicate<R>,
{
inner: T,
predicate: U,
_r: PhantomData<R>,
}
impl<T: Clone, U: Clone, R> Clone for AsyncFilterEx<T, U, R>
where
U: AsyncPredicate<R>,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
predicate: self.predicate.clone(),
_r: PhantomData,
}
}
}
impl<T, U, R> AsyncFilterEx<T, U, R>
where
U: AsyncPredicate<R>,
{
pub fn new(inner: T, predicate: U) -> Self {
Self {
inner,
predicate,
_r: PhantomData,
}
}
pub fn layer(predicate: U) -> AsyncFilterExLayer<U, R> {
AsyncFilterExLayer::new(predicate)
}
pub async fn check(&mut self, request: R) -> Result<U::Request, U::Response>
where
U: AsyncPredicate<R>,
{
self.predicate.check(request).await
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T, U> Service<Request> for AsyncFilterEx<T, U, Request>
where
T: Service<U::Request, Response = Response> + Clone,
U: AsyncPredicate<Request, Response = Response>,
{
type Response = T::Response;
type Error = T::Error;
type Future = AsyncResponseFuture<U, T, Request>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request) -> Self::Future {
use std::mem;
let inner = self.inner.clone();
let inner = mem::replace(&mut self.inner, inner);
let check = self.predicate.check(req);
AsyncResponseFuture::new(check, inner)
}
}
pub async fn drain_body(request: Request) {
let mut data_stream = request.into_body().into_data_stream();
while let Some(_) = data_stream.next().await {}
}