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};