Middleware

Trait Middleware 

Source
pub trait Middleware: Send {
    type Error: HttpError;

    // Required method
    fn handle<E: Endpoint>(
        &mut self,
        request: &mut Request,
        next: E,
    ) -> impl Future<Output = Result<Response, MiddlewareError<E::Error, Self::Error>>> + Send;
}
Expand description

Trait for implementing middleware that can process HTTP requests and responses.

Middleware sits between the initial request and the final endpoint, allowing you to implement cross-cutting concerns like authentication, logging, rate limiting, compression, and other request/response transformations.

Middleware operates in a chain where each middleware can:

  • Inspect and modify the incoming request
  • Decide whether to call the next middleware/endpoint in the chain
  • Inspect and modify the outgoing response
  • Handle errors and implement fallback behavior

§Implementation Pattern

A typical middleware implementation follows this pattern:

  1. Pre-process the request (logging, validation, etc.)
  2. Call next.respond(request).await to continue the chain
  3. Post-process the response (add headers, transform body, etc.)
  4. Return the final response

§Examples

§Request Logging Middleware

use http_kit::{Request, Response, Result, Middleware, Endpoint, Body, Error};
use http_kit::middleware::MiddlewareError;

struct LoggingMiddleware;

impl Middleware for LoggingMiddleware {
    type Error = Error;
    async fn handle<E: Endpoint>(&mut self, request: &mut Request, mut next: E) -> Result<Response, MiddlewareError<E::Error, Self::Error>> {
        println!("Incoming: {} {}", request.method(), request.uri());

        let response = next.respond(request).await.map_err(MiddlewareError::Endpoint)?;

        println!("Outgoing: {}", response.status());
        Ok(response)
    }
}

§Authentication Middleware

use http_kit::{Request, Response, Result, Middleware, Endpoint, StatusCode, Body, Error};
use http_kit::middleware::MiddlewareError;

struct AuthMiddleware {
    required_token: String,
}

impl Middleware for AuthMiddleware {
    type Error = Error;
    async fn handle<E: Endpoint>(&mut self, request: &mut Request, mut next: E) -> Result<Response, MiddlewareError<E::Error, Self::Error>> {
        if let Some(auth_header) = request.headers().get(http::header::AUTHORIZATION) {
            if auth_header.as_bytes() == self.required_token.as_bytes() {
                return next.respond(request).await.map_err(MiddlewareError::Endpoint);
            }
        }

        Ok(Response::new(Body::from_bytes("Authentication required")))
    }
}

§Response Header Middleware

use http_kit::{Request, Response, Result, Middleware, Endpoint, Body, Error};
use http_kit::middleware::MiddlewareError;

struct HeaderMiddleware;

impl Middleware for HeaderMiddleware {
    type Error = Error;
    async fn handle<E: Endpoint>(&mut self, request: &mut Request, mut next: E) -> Result<Response, MiddlewareError<E::Error, Self::Error>> {
        let mut response = next.respond(request).await.map_err(MiddlewareError::Endpoint)?;

        response.headers_mut().insert(
            http::header::SERVER,
            http::HeaderValue::from_static("http-kit/1.0")
        );

        Ok(response)
    }
}

Required Associated Types§

Source

type Error: HttpError

The error type that this middleware can produce.

Required Methods§

Source

fn handle<E: Endpoint>( &mut self, request: &mut Request, next: E, ) -> impl Future<Output = Result<Response, MiddlewareError<E::Error, Self::Error>>> + Send

Processes a request through the middleware chain.

This method receives the current request and a next parameter representing the next step in the processing chain (either another middleware or the final endpoint). The middleware can:

  • Modify the request before passing it to next
  • Decide whether to call next at all (for auth, rate limiting, etc.)
  • Transform the response returned by next
  • Handle errors and provide fallback responses
§Arguments
  • request - Mutable reference to the HTTP request being processed
  • next - The next step in the processing chain (middleware or endpoint)
§Returns

Returns a Result<Response> which can either be:

  • Ok(response) - A successful HTTP response
  • Err(error) - An error with an associated HTTP status code
§Examples
use http_kit::{Request, Response, Result, Middleware, Endpoint, Body, Error};
use http_kit::middleware::MiddlewareError;

struct TimingMiddleware;

impl Middleware for TimingMiddleware {
    type Error = Error;
    async fn handle<E: Endpoint>(&mut self, request: &mut Request, mut next: E) -> Result<Response, MiddlewareError<E::Error, Self::Error>> {
        let start = std::time::Instant::now();

        // Call the next middleware or endpoint
        let response = next.respond(request).await.map_err(MiddlewareError::Endpoint)?;

        let duration = start.elapsed();
        println!("Request processed in {:?}", duration);

        Ok(response)
    }
}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Middleware for ()

No-op middleware implementation for the unit type.

This implementation allows () to be used as a middleware that does nothing but pass the request through to the next handler. This is useful for:

  • Default values in generic contexts
  • Conditional middleware application
  • Testing scenarios where middleware is optional
Source§

type Error = Infallible

Source§

async fn handle<E: Endpoint>( &mut self, request: &mut Request, next: E, ) -> Result<Response, MiddlewareError<E::Error, Self::Error>>

Source§

impl<M: Middleware> Middleware for &mut M

Source§

type Error = <M as Middleware>::Error

Source§

async fn handle<E: Endpoint>( &mut self, request: &mut Request, next: E, ) -> Result<Response, MiddlewareError<E::Error, Self::Error>>

Source§

impl<M: Middleware> Middleware for Box<M>

Source§

type Error = <M as Middleware>::Error

Source§

async fn handle<E: Endpoint>( &mut self, request: &mut Request, next: E, ) -> Result<Response, MiddlewareError<E::Error, Self::Error>>

Implementors§