rama_http/layer/validate_request/mod.rs
1//! Middleware that validates requests.
2//!
3//! # Example
4//!
5//! ```
6//! use rama_http::layer::validate_request::ValidateRequestHeaderLayer;
7//! use rama_http::{Body, Request, Response, StatusCode, header::ACCEPT};
8//! use rama_core::service::service_fn;
9//! use rama_core::{Context, Service, Layer};
10//! use rama_core::error::BoxError;
11//!
12//! async fn handle(request: Request) -> Result<Response, BoxError> {
13//! Ok(Response::new(Body::empty()))
14//! }
15//!
16//! # #[tokio::main]
17//! # async fn main() -> Result<(), BoxError> {
18//! let mut service = (
19//! // Require the `Accept` header to be `application/json`, `*/*` or `application/*`
20//! ValidateRequestHeaderLayer::accept("application/json"),
21//! ).layer(service_fn(handle));
22//!
23//! // Requests with the correct value are allowed through
24//! let request = Request::builder()
25//! .header(ACCEPT, "application/json")
26//! .body(Body::empty())
27//! .unwrap();
28//!
29//! let response = service
30//! .serve(Context::default(), request)
31//! .await?;
32//!
33//! assert_eq!(StatusCode::OK, response.status());
34//!
35//! // Requests with an invalid value get a `406 Not Acceptable` response
36//! let request = Request::builder()
37//! .header(ACCEPT, "text/strings")
38//! .body(Body::empty())
39//! .unwrap();
40//!
41//! let response = service
42//! .serve(Context::default(), request)
43//! .await?;
44//!
45//! assert_eq!(StatusCode::NOT_ACCEPTABLE, response.status());
46//! # Ok(())
47//! # }
48//! ```
49//!
50//! Custom validation can be made by implementing [`ValidateRequest`]:
51//!
52//! ```
53//! use rama_http::layer::validate_request::{ValidateRequestHeaderLayer, ValidateRequest};
54//! use rama_http::{Body, Request, Response, StatusCode, header::ACCEPT};
55//! use rama_core::service::service_fn;
56//! use rama_core::{Context, Service, Layer};
57//! use rama_core::error::BoxError;
58//!
59//! #[derive(Clone, Copy)]
60//! pub struct MyHeader { /* ... */ }
61//!
62//! impl<S, B> ValidateRequest<S, B> for MyHeader
63//! where
64//! S: Clone + Send + Sync + 'static,
65//! B: Send + 'static,
66//! {
67//! type ResponseBody = Body;
68//!
69//! async fn validate(
70//! &self,
71//! ctx: Context<S>,
72//! req: Request<B>,
73//! ) -> Result<(Context<S>, Request<B>), Response<Self::ResponseBody>> {
74//! // validate the request...
75//! # Ok::<_, Response>((ctx, req))
76//! }
77//! }
78//!
79//! async fn handle(request: Request) -> Result<Response, BoxError> {
80//! # Ok(Response::builder().body(Body::empty()).unwrap())
81//! // ...
82//! }
83//!
84//!
85//! # #[tokio::main]
86//! # async fn main() -> Result<(), BoxError> {
87//! let service = (
88//! // Validate requests using `MyHeader`
89//! ValidateRequestHeaderLayer::custom(MyHeader { /* ... */ }),
90//! ).layer(service_fn(handle));
91//!
92//! # let request = Request::builder()
93//! # .body(Body::empty())
94//! # .unwrap();
95//!
96//! let response = service
97//! .serve(Context::default(), request)
98//! .await?;
99//!
100//! # Ok(())
101//! # }
102//! ```
103//!
104//! Or using a closure:
105//!
106//! ```
107//! use bytes::Bytes;
108//! use rama_http::{Body, Request, Response, StatusCode, header::ACCEPT};
109//! use rama_http::layer::validate_request::{ValidateRequestHeaderLayer, ValidateRequest};
110//! use rama_core::service::service_fn;
111//! use rama_core::{Context, Service, Layer};
112//! use rama_core::error::BoxError;
113//!
114//! async fn handle(request: Request) -> Result<Response, BoxError> {
115//! # Ok(Response::builder().body(Body::empty()).unwrap())
116//! // ...
117//! }
118//!
119//! # #[tokio::main]
120//! # async fn main() -> Result<(), BoxError> {
121//! let service = (
122//! ValidateRequestHeaderLayer::custom_fn(|request: Request| async move {
123//! // Validate the request
124//! # Ok::<_, Response>(request)
125//! }),
126//! ).layer(service_fn(handle));
127//!
128//! # let request = Request::builder()
129//! # .body(Body::empty())
130//! # .unwrap();
131//!
132//! let response = service
133//! .serve(Context::default(), request)
134//! .await?;
135//!
136//! # Ok(())
137//! # }
138//! ```
139
140mod accept_header;
141mod validate;
142mod validate_fn;
143mod validate_request_header;
144
145#[doc(inline)]
146pub use accept_header::AcceptHeader;
147#[doc(inline)]
148pub use validate::ValidateRequest;
149#[doc(inline)]
150pub use validate_fn::{BoxValidateRequestFn, ValidateRequestFn};
151#[doc(inline)]
152pub use validate_request_header::{ValidateRequestHeader, ValidateRequestHeaderLayer};