envoy_http/
middleware.rs

1//! Middleware types.
2
3use std::fmt::Debug;
4use std::sync::Arc;
5
6use crate::endpoint::DynEndpoint;
7use async_trait::async_trait;
8use std::future::Future;
9
10/// Middleware that wraps around the remaining middleware chain.
11#[async_trait]
12pub trait Middleware: Send + Sync {
13    /// Asynchronously handle the request, and return a response.
14    async fn handle(&self, ctx: &mut crate::Context, next: Next) -> crate::Result;
15
16    /// Set the middleware's name. By default it uses the type signature.
17    fn name(&self) -> &str {
18        std::any::type_name::<Self>()
19    }
20}
21
22impl Debug for dyn Middleware {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        write!(
25            f,
26            "dyn Middleware<{:?}>",
27            std::any::type_name::<Self>(),
28        )
29    }
30}
31
32#[async_trait::async_trait]
33impl<F> Middleware for F
34where
35    F: for<'arg1> Fn1<&'arg1 mut crate::Context, Next> + Sync + Send,
36    for<'arg1> <F as Fn1<&'arg1 mut crate::Context, Next>>::Output: Future<Output = crate::Result> + Send,
37{
38    async fn handle(&self, ctx: &mut crate::Context, next: Next) -> crate::Result {
39        self(ctx, next).await
40    }
41}
42
43trait Fn1<Arg1, Arg2>: Fn(Arg1, Arg2) -> <Self as Fn1<Arg1, Arg2>>::Output {
44    type Output;
45}
46impl<F: Fn(Arg1, Arg2) -> O, Arg1, Arg2, O> Fn1<Arg1, Arg2> for F {
47    type Output = O;
48}
49
50/// The remainder of a middleware chain, including the endpoint.
51#[derive(Debug)]
52pub struct Next {
53    endpoint: Arc<DynEndpoint>,
54    middleware: Arc<Vec<Arc<dyn Middleware>>>,
55    current_index: usize,
56}
57
58impl Next {
59    /// Create a new Next instance.
60    pub fn new(
61        endpoint: Arc<DynEndpoint>,
62        middleware: Arc<Vec<Arc<dyn Middleware>>>,
63    ) -> Next {
64        Next {
65            endpoint,
66            middleware,
67            current_index: 0,
68        }
69    }
70
71    /// Asynchronously execute the remaining middleware chain.
72    pub async fn run(mut self, ctx: &mut crate::Context) -> crate::Result {
73        let current_index = self.current_index; // get a copy of the current index
74        self.current_index += 1; // increment the index for the next call
75
76        match self.middleware.get(current_index) {
77            // if there is a next middleware
78            Some(current) => current.clone().handle(ctx, self).await,
79            // if there is no next middleware, execute the endpoint
80            None => self.endpoint.call(ctx).await,
81        }
82    }
83}