use crate::common::ExtensionsModifier;
use crate::{common::ErrorHandler, handler::Args, request::RequestContext};
use super::*;
#[derive(Clone)]
pub struct ErrorHandlerLayer<ErrH>(ErrH);
impl<ErrH> ErrorHandlerLayer<ErrH>
where
ErrH: ErrorHandler + Clone,
{
pub fn new(error_handler: ErrH) -> Self {
Self(error_handler)
}
}
impl<H, ErrH> Layer<H> for ErrorHandlerLayer<ErrH>
where
ErrH: ErrorHandler + Clone,
{
type Handler = ResponseResultHandler<H, ErrH>;
fn wrap(&self, handler: H) -> Self::Handler {
ResponseResultHandler::new(handler, self.0.clone())
}
}
#[derive(Clone)]
pub struct RequestExtensionsModifierLayer<ExtM>(ExtM);
impl<ExtM> RequestExtensionsModifierLayer<ExtM>
where
ExtM: ExtensionsModifier + Clone,
{
pub fn new(extensions_modifier: ExtM) -> Self {
Self(extensions_modifier)
}
}
impl<H, ExtM> Layer<H> for RequestExtensionsModifierLayer<ExtM>
where
ExtM: ExtensionsModifier + Clone,
{
type Handler = RequestExtensionsModifier<H, ExtM>;
fn wrap(&self, handler: H) -> Self::Handler {
RequestExtensionsModifier::new(handler, self.0.clone())
}
}
#[derive(Clone)]
pub struct RedirectionLayer<U: AsRef<str>> {
status_code: StatusCode,
prefix: bool,
uri: U,
}
impl<U: AsRef<str>> RedirectionLayer<U> {
pub fn for_permanent_redirection_to(uri: U) -> Self {
Self {
status_code: StatusCode::PERMANENT_REDIRECT,
prefix: false,
uri,
}
}
pub fn for_permanent_redirection_to_prefix(uri: U) -> Self {
Self {
status_code: StatusCode::PERMANENT_REDIRECT,
prefix: true,
uri,
}
}
pub fn for_temporary_redirection_to(uri: U) -> Self {
Self {
status_code: StatusCode::TEMPORARY_REDIRECT,
prefix: false,
uri,
}
}
pub fn for_temporary_redirection_to_prefix(uri: U) -> Self {
Self {
status_code: StatusCode::TEMPORARY_REDIRECT,
prefix: true,
uri,
}
}
pub fn for_redirection_to_see(uri: U) -> Self {
Self {
status_code: StatusCode::SEE_OTHER,
prefix: false,
uri,
}
}
pub fn for_redirection_to_see_prefix(uri: U) -> Self {
Self {
status_code: StatusCode::SEE_OTHER,
prefix: true,
uri,
}
}
}
impl<H, U> Layer<H> for RedirectionLayer<U>
where
U: AsRef<str> + Clone,
{
type Handler = Redirector;
fn wrap(&self, _handler: H) -> Self::Handler {
Redirector::new(self.prefix, self.uri.clone())
}
}
mod private {
use std::future::ready;
use crate::response::Redirect;
use super::*;
#[derive(Clone)]
pub struct ResponseResultHandler<H, ErrH> {
inner: H,
error_handler: ErrH,
}
impl<H, ErrH> ResponseResultHandler<H, ErrH> {
pub(crate) fn new(inner: H, error_handler: ErrH) -> Self {
Self {
inner,
error_handler,
}
}
}
impl<H, B, Ext, ErrH> Handler<B, Ext> for ResponseResultHandler<H, ErrH>
where
H: Handler<
B,
Ext,
Response = Response,
Error = BoxedErrorResponse,
Future = BoxedFuture<Result<Response, BoxedErrorResponse>>,
>,
Ext: Clone,
ErrH: ErrorHandler + Clone + Send + 'static,
{
type Response = Response;
type Error = BoxedErrorResponse;
type Future = BoxedFuture<Result<Self::Response, Self::Error>>;
#[inline]
fn handle(&self, request_context: RequestContext<B>, args: Args<'_, Ext>) -> Self::Future {
let future = self.inner.handle(request_context, args);
let mut error_handler_clone = self.error_handler.clone();
Box::pin(async move {
match future.await {
Ok(response) => Ok(response),
Err(error) => error_handler_clone.handle_error(error).await,
}
})
}
}
#[derive(Clone)]
pub struct RequestExtensionsModifier<H, ExtM> {
inner_handler: H,
extensions_modifier: ExtM,
}
impl<H, ExtM> RequestExtensionsModifier<H, ExtM> {
pub(super) fn new(handler: H, extensions_modifier: ExtM) -> Self {
Self {
inner_handler: handler,
extensions_modifier,
}
}
}
impl<H, B, HExt, ExtM> Handler<B, HExt> for RequestExtensionsModifier<H, ExtM>
where
H: Handler<B, HExt>,
HExt: Clone,
ExtM: ExtensionsModifier + Clone,
{
type Response = H::Response;
type Error = H::Error;
type Future = H::Future;
#[inline(always)]
fn handle(&self, mut request_context: RequestContext<B>, args: Args<'_, HExt>) -> Self::Future {
self
.extensions_modifier
.modify_extensions(request_context.request_mut().extensions_mut());
self.inner_handler.handle(request_context, args)
}
}
#[derive(Clone)]
pub struct Redirector {
prefix: bool,
uri: Box<str>,
}
impl Redirector {
pub(crate) fn new<U: AsRef<str>>(prefix: bool, uri: U) -> Self {
let uri = uri.as_ref();
let uri = if prefix {
uri.strip_suffix('/').unwrap_or(uri)
} else {
uri
};
Self {
prefix,
uri: uri.into(),
}
}
}
impl<B, Ext: Clone> Handler<B, Ext> for Redirector {
type Response = Response;
type Error = BoxedErrorResponse;
type Future = BoxedFuture<Result<Self::Response, Self::Error>>;
#[inline]
fn handle(&self, request_context: RequestContext<B>, _args: Args<'_, Ext>) -> Self::Future {
let redirect = if self.prefix {
let uri = format!("{}{}", self.uri.as_ref(), request_context.uri_ref().path());
Redirect::permanently_to(uri)
} else {
Redirect::permanently_to(self.uri.as_ref())
};
Box::pin(ready(Ok(redirect.into_response())))
}
}
#[derive(Clone)]
pub struct LayerFn<Func>(pub(crate) Func);
impl<Func, InH, OutH> Layer<InH> for LayerFn<Func>
where
Func: Fn(InH) -> OutH,
{
type Handler = OutH;
fn wrap(&self, handler: InH) -> Self::Handler {
self.0(handler)
}
}
}
use http::StatusCode;
pub(crate) use private::LayerFn;
pub(crate) use private::Redirector;
pub(crate) use private::RequestExtensionsModifier;
pub(crate) use private::ResponseResultHandler;