1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! # rainier-middleware
//!
//! Middleware as values: the [`Middleware`] contract, the [`Pipeline`] that
//! runs a chain of it, and the [`MiddlewareStack`] a route or a group attaches.
//!
//! ```
//! use rainier_http::{Request, Response, StatusCode};
//! use rainier_middleware::{Middleware, Next, Pipeline};
//!
//! struct RequireApiKey;
//!
//! #[async_trait::async_trait]
//! impl Middleware for RequireApiKey {
//! async fn handle(&self, request: Request, next: Next) -> Response {
//! match request.header("x-api-key") {
//! Some("secret") => next.run(request).await,
//! _ => Response::new(StatusCode::UNAUTHORIZED),
//! }
//! }
//! }
//!
//! # #[tokio::main] async fn main() {
//! let pipeline = Pipeline::new()
//! .through(RequireApiKey)
//! .then(|_: Request| async { Response::text("secrets") });
//!
//! let denied = pipeline.run(Request::builder().build()).await;
//! assert_eq!(denied.status(), StatusCode::UNAUTHORIZED);
//!
//! let allowed = pipeline.run(Request::builder().header("x-api-key", "secret").build()).await;
//! assert_eq!(allowed.status(), StatusCode::OK);
//! # }
//! ```
//!
//! ## No names anywhere
//!
//! A route attaches `.middleware(Authenticate::new(auth))`, not
//! `.middleware("auth")`. A name-keyed kernel needs the string because a
//! dynamic language has nowhere to put the type; Rust does not, and the
//! indirection costs more than it saves —
//! a misspelled alias is a route that runs unguarded, and only an integration
//! test notices.
//!
//! The router still does not depend on `rainier-auth` or `rainier-session`. It
//! only ever sees `dyn Middleware`, which is defined here; the **application**
//! names the concrete type, because the application is the crate that knows it.
//!
//! | The name-based equivalent | Rainier |
//! |---|---|
//! | a route-middleware alias map | nothing — attach the value |
//! | a named group in a map | a function returning a [`MiddlewareStack`] |
//! | the global list | [`MiddlewareRegistry::global`] |
//! | a throttle spelled as a string | `ThrottleRequests::per_minute(60)` |
//! | excluding middleware by name | `.without_middleware::<Authenticate<User>>()` |
//!
//! The one thing a name genuinely bought — middleware that cannot be built
//! until the container is populated — is [`MiddlewareStack::deferred`], which
//! runs a closure when the router compiles.
pub use ;
pub use Compress;
pub use MethodOverride;
pub use ;
pub use ;
pub use ;
pub use MiddlewareRegistry;
pub use ;
pub use Timeout;
// Re-exported so middleware implementors get the attribute macro without
// adding the dependency themselves.
pub use async_trait;