tower_http

Module validate_request

source
Expand description

Middleware that validates requests.

§Example

use tower_http::validate_request::ValidateRequestHeaderLayer;
use http::{Request, Response, StatusCode, header::ACCEPT};
use http_body_util::Full;
use bytes::Bytes;
use tower::{Service, ServiceExt, ServiceBuilder, service_fn, BoxError};

async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, BoxError> {
    Ok(Response::new(Full::default()))
}

let mut service = ServiceBuilder::new()
    // Require the `Accept` header to be `application/json`, `*/*` or `application/*`
    .layer(ValidateRequestHeaderLayer::accept("application/json"))
    .service_fn(handle);

// Requests with the correct value are allowed through
let request = Request::builder()
    .header(ACCEPT, "application/json")
    .body(Full::default())
    .unwrap();

let response = service
    .ready()
    .await?
    .call(request)
    .await?;

assert_eq!(StatusCode::OK, response.status());

// Requests with an invalid value get a `406 Not Acceptable` response
let request = Request::builder()
    .header(ACCEPT, "text/strings")
    .body(Full::default())
    .unwrap();

let response = service
    .ready()
    .await?
    .call(request)
    .await?;

assert_eq!(StatusCode::NOT_ACCEPTABLE, response.status());

Custom validation can be made by implementing ValidateRequest:

use tower_http::validate_request::{ValidateRequestHeaderLayer, ValidateRequest};
use http::{Request, Response, StatusCode, header::ACCEPT};
use http_body_util::Full;
use tower::{Service, ServiceExt, ServiceBuilder, service_fn, BoxError};
use bytes::Bytes;

#[derive(Clone, Copy)]
pub struct MyHeader { /* ...  */ }

impl<B> ValidateRequest<B> for MyHeader {
    type ResponseBody = Full<Bytes>;

    fn validate(
        &mut self,
        request: &mut Request<B>,
    ) -> Result<(), Response<Self::ResponseBody>> {
        // validate the request...
    }
}

async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, BoxError> {
    Ok(Response::new(Full::default()))
}


let service = ServiceBuilder::new()
    // Validate requests using `MyHeader`
    .layer(ValidateRequestHeaderLayer::custom(MyHeader { /* ... */ }))
    .service_fn(handle);

Or using a closure:

use tower_http::validate_request::{ValidateRequestHeaderLayer, ValidateRequest};
use http::{Request, Response, StatusCode, header::ACCEPT};
use bytes::Bytes;
use http_body_util::Full;
use tower::{Service, ServiceExt, ServiceBuilder, service_fn, BoxError};

async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, BoxError> {
    // ...
}

let service = ServiceBuilder::new()
    .layer(ValidateRequestHeaderLayer::custom(|request: &mut Request<Full<Bytes>>| {
        // Validate the request
    }))
    .service_fn(handle);

Structs§

Traits§