pub mod header;
pub mod method;
mod predicate;
pub use header::Header;
pub use predicate::*;
use std::fmt::Debug;
use crate::request::Request;
use crate::{BoxFuture, Continue, Error, Middleware, Next};
pub type Content<T, U> = (
Header<header::Contains<Or<(header::Media<header::CaseSensitive>, U)>>>,
When<Not<method::IsSafe>, (Header<T>, Header<Wildcard>)>,
);
pub struct Filter<T, U> {
predicate: T,
middleware: U,
}
pub struct FlatMap<T, U> {
predicate: T,
middleware: U,
}
pub fn filter<T, U>(predicate: T, middleware: U) -> Filter<T, U> {
Filter {
predicate,
middleware,
}
}
pub fn flat_map<T, U>(predicate: T, middleware: U) -> FlatMap<T, U> {
FlatMap {
predicate,
middleware,
}
}
pub fn guard<T>(predicate: T) -> FlatMap<T, Continue> {
flat_map(predicate, Continue)
}
pub fn header<K, V>(key: K, value: V) -> Header<V>
where
K: TryInto<http::HeaderName>,
K::Error: Debug,
{
Header {
value,
key: key.try_into().expect("invalid header name."),
}
}
pub fn content<T, U>(accepts: T, provides: U) -> Content<T, U> {
(
header::accept(provides),
when(
method::is_mutation(),
(header::content_type(accepts), header::content_length()),
),
)
}
impl<T, U, App> Middleware<App> for FlatMap<T, U>
where
T: Predicate<Request<App>> + Send + Sync,
for<'a> T::Error<'a>: Into<Error>,
U: Middleware<App>,
{
fn call(&self, request: Request<App>, next: Next<App>) -> BoxFuture {
match self.predicate.cmp(&request) {
Ok(_) => self.middleware.call(request, next),
Err(error) => {
let error = error.into();
Box::pin(async { Err(error) })
}
}
}
}
impl<T, U, App> Middleware<App> for Filter<T, U>
where
T: Predicate<Request<App>> + Send + Sync,
U: Middleware<App>,
{
fn call(&self, request: Request<App>, next: Next<App>) -> BoxFuture {
if self.predicate.cmp(&request).is_ok() {
self.middleware.call(request, next)
} else {
next.call(request)
}
}
}