Available on crate feature
validate-request only.Expand description
Middleware that validates requests.
§Example
Validation of the Accept header can be made by using ValidateRequestHeaderLayer::accept():
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());Validation of a custom header can be made by using ValidateRequestHeaderLayer::has_header_value():
use tower_http::validate_request::ValidateRequestHeaderLayer;
use http::{Request, Response, StatusCode};
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 a `X-Custom-Header` header to have the value `random-value-1234567890` or reject with a `403 Forbidden` response
.layer(ValidateRequestHeaderLayer::has_header_value(
"x-custom-header",
"random-value-1234567890",
).expect("invalid validate header"))
.service_fn(handle);
// Requests with the correct value are allowed through
let request = Request::builder()
.header("x-custom-header", "random-value-1234567890")
.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 `403 Forbidden` response
let request = Request::builder()
.header("x-custom-header", "wrong-value")
.body(Full::default())
.unwrap();
let response = service
.ready()
.await?
.call(request)
.await?;
assert_eq!(StatusCode::FORBIDDEN, response.status());To require only that a header is present, use ValidateRequestHeaderLayer::custom():
use tower_http::validate_request::ValidateRequestHeaderLayer;
use http::{Request, Response, StatusCode};
use http_body_util::Full;
use bytes::Bytes;
use tower::{ServiceBuilder, service_fn, BoxError};
async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, BoxError> {
Ok(Response::new(Full::default()))
}
let service = ServiceBuilder::new()
.layer(ValidateRequestHeaderLayer::custom(|req: &mut Request<Full<Bytes>>| {
if req.headers().contains_key("x-custom-header") {
Ok(())
} else {
let mut res = Response::new(Full::<Bytes>::default());
*res.status_mut() = StatusCode::FORBIDDEN;
Err(res)
}
}))
.service_fn(handle);To serve a custom response when validation fails, also use ValidateRequestHeaderLayer::custom():
use tower_http::validate_request::ValidateRequestHeaderLayer;
use http::{Request, Response, StatusCode};
use http_body_util::Full;
use bytes::Bytes;
use tower::{ServiceBuilder, service_fn, BoxError};
async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, BoxError> {
Ok(Response::new(Full::default()))
}
let service = ServiceBuilder::new()
.layer(ValidateRequestHeaderLayer::custom(|req: &mut Request<Full<Bytes>>| {
match req.headers().get("x-custom-header").map(|v| v.as_bytes()) {
Some(b"random-value-1234567890") => Ok(()),
_ => Err(Response::builder()
.status(StatusCode::FORBIDDEN)
.body(Full::<Bytes>::default())
.unwrap()),
}
}))
.service_fn(handle);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);Structs§
- Accept
Header - Type that performs validation of the Accept header.
- Required
Header Value - Type that rejects requests if a header is not present or does not have an expected value.
- Response
Future - Response future for
ValidateRequestHeader. - Validate
Request Header - Middleware that validates requests.
- Validate
Request Header Layer - Layer that applies
ValidateRequestHeaderwhich validates all requests.
Traits§
- Validate
Request - Trait for validating requests.