1use std::sync::Arc;
76
77use rainier_container::Container;
78use rainier_support::{Error, Result};
79
80use crate::pipeline::Middleware;
81
82type Builder = Arc<dyn Fn(&Container) -> Result<Arc<dyn Middleware>> + Send + Sync>;
84
85enum Stage {
87 Ready(Arc<dyn Middleware>),
88 Deferred(&'static str, Builder),
91}
92
93impl Clone for Stage {
94 fn clone(&self) -> Self {
95 match self {
96 Stage::Ready(middleware) => Stage::Ready(Arc::clone(middleware)),
97 Stage::Deferred(name, build) => Stage::Deferred(name, Arc::clone(build)),
98 }
99 }
100}
101
102#[derive(Default, Clone)]
107pub struct MiddlewareStack {
108 stages: Vec<Stage>,
109}
110
111impl MiddlewareStack {
112 pub fn new() -> Self {
114 Self::default()
115 }
116
117 pub fn with(mut self, middleware: impl Middleware) -> Self {
119 self.stages.push(Stage::Ready(Arc::new(middleware)));
120 self
121 }
122
123 pub fn with_arc(mut self, middleware: Arc<dyn Middleware>) -> Self {
128 self.stages.push(Stage::Ready(middleware));
129 self
130 }
131
132 pub fn with_stack(mut self, other: MiddlewareStack) -> Self {
136 self.stages.extend(other.stages);
137 self
138 }
139
140 pub fn deferred<M, F>(mut self, build: F) -> Self
146 where
147 M: Middleware,
148 F: Fn(&Container) -> Result<M> + Send + Sync + 'static,
149 {
150 let name = crate::pipeline::short_type_name(std::any::type_name::<M>());
151 self.stages.push(Stage::Deferred(
152 name,
153 Arc::new(move |container| build(container).map(|m| Arc::new(m) as Arc<dyn Middleware>)),
154 ));
155 self
156 }
157
158 pub fn resolved<S, M, F>(self, build: F) -> Self
171 where
172 S: Send + Sync + 'static,
173 M: Middleware,
174 F: Fn(Arc<S>) -> M + Send + Sync + 'static,
175 {
176 self.deferred(move |container| Ok(build(container.resolve::<S>()?)))
177 }
178
179 pub fn prepend(&mut self, outer: &MiddlewareStack) {
183 let mut combined = outer.stages.clone();
184 combined.append(&mut self.stages);
185 self.stages = combined;
186 }
187
188 pub fn len(&self) -> usize {
190 self.stages.len()
191 }
192
193 pub fn is_empty(&self) -> bool {
195 self.stages.is_empty()
196 }
197
198 pub fn resolve(&self, container: &Container) -> Result<Vec<Arc<dyn Middleware>>> {
202 self.stages
203 .iter()
204 .map(|stage| match stage {
205 Stage::Ready(middleware) => Ok(Arc::clone(middleware)),
206 Stage::Deferred(name, build) => build(container).map_err(|e| {
207 Error::internal(format!("could not build the `{name}` middleware: {e}"))
208 }),
209 })
210 .collect()
211 }
212
213 pub fn labels(&self) -> Vec<&'static str> {
218 self.stages
219 .iter()
220 .map(|stage| match stage {
221 Stage::Ready(middleware) => middleware.name(),
222 Stage::Deferred(name, _) => name,
223 })
224 .collect()
225 }
226}
227
228impl std::fmt::Debug for MiddlewareStack {
229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230 f.debug_list().entries(self.labels()).finish()
231 }
232}
233
234pub trait IntoMiddlewareStack {
250 fn into_middleware_stack(self) -> MiddlewareStack;
252}
253
254impl<M: Middleware> IntoMiddlewareStack for M {
255 fn into_middleware_stack(self) -> MiddlewareStack {
256 MiddlewareStack::new().with(self)
257 }
258}
259
260impl IntoMiddlewareStack for MiddlewareStack {
261 fn into_middleware_stack(self) -> MiddlewareStack {
262 self
263 }
264}
265
266impl IntoMiddlewareStack for Arc<dyn Middleware> {
267 fn into_middleware_stack(self) -> MiddlewareStack {
268 MiddlewareStack::new().with_arc(self)
269 }
270}
271
272impl IntoMiddlewareStack for Vec<Arc<dyn Middleware>> {
273 fn into_middleware_stack(self) -> MiddlewareStack {
274 self.into_iter().fold(MiddlewareStack::new(), MiddlewareStack::with_arc)
275 }
276}
277
278impl<M: Middleware> From<M> for MiddlewareStack {
279 fn from(middleware: M) -> Self {
280 MiddlewareStack::new().with(middleware)
281 }
282}
283
284macro_rules! tuple_stacks {
287 ($( ($($name:ident),+) ),+ $(,)?) => {
288 $(
289 #[allow(non_snake_case, reason = "the idiomatic spelling for a tuple impl")]
290 impl<$($name: Middleware),+> IntoMiddlewareStack for ($($name,)+) {
291 fn into_middleware_stack(self) -> MiddlewareStack {
292 let ($($name,)+) = self;
293 MiddlewareStack::new()$(.with($name))+
294 }
295 }
296 )+
297 };
298}
299
300tuple_stacks! {
301 (A, B),
302 (A, B, C),
303 (A, B, C, D),
304 (A, B, C, D, E),
305 (A, B, C, D, E, F),
306 (A, B, C, D, E, F, G),
307 (A, B, C, D, E, F, G, H),
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313 use crate::pipeline::Next;
314 use rainier_http::{Request, Response};
315
316 macro_rules! tag {
317 ($name:ident) => {
318 struct $name;
319
320 #[async_trait::async_trait]
321 impl Middleware for $name {
322 async fn handle(&self, request: Request, next: Next) -> Response {
323 next.run(request).await
324 }
325 fn name(&self) -> &'static str {
326 stringify!($name)
327 }
328 }
329 };
330 }
331
332 tag!(First);
333 tag!(Second);
334 tag!(Third);
335
336 fn resolved_names(stack: &MiddlewareStack) -> Vec<&'static str> {
337 stack.resolve(&Container::new()).unwrap().iter().map(|m| m.name()).collect()
338 }
339
340 #[test]
341 fn a_stack_keeps_the_order_it_was_built_in() {
342 let stack = MiddlewareStack::new().with(First).with(Second).with(Third);
343 assert_eq!(resolved_names(&stack), vec!["First", "Second", "Third"]);
344 }
345
346 #[test]
347 fn one_middleware_converts_to_a_stack_of_one() {
348 assert_eq!(resolved_names(&First.into_middleware_stack()), vec!["First"]);
349 }
350
351 #[test]
352 fn a_tuple_converts_in_order() {
353 let stack = (First, Second, Third).into_middleware_stack();
354 assert_eq!(resolved_names(&stack), vec!["First", "Second", "Third"]);
355 }
356
357 #[test]
358 fn a_stack_converts_to_itself() {
359 let stack = MiddlewareStack::new().with(First);
360 assert_eq!(resolved_names(&stack.into_middleware_stack()), vec!["First"]);
361 }
362
363 #[test]
364 fn nesting_a_stack_flattens_it_in_place() {
365 let inner = MiddlewareStack::new().with(Second).with(Third);
368 let outer = MiddlewareStack::new().with(First).with_stack(inner);
369
370 assert_eq!(resolved_names(&outer), vec!["First", "Second", "Third"]);
371 }
372
373 #[test]
374 fn prepending_puts_the_group_outside_the_routes_own() {
375 let mut route = MiddlewareStack::new().with(Third);
376 route.prepend(&MiddlewareStack::new().with(First).with(Second));
377
378 assert_eq!(resolved_names(&route), vec!["First", "Second", "Third"]);
379 }
380
381 #[test]
382 fn a_deferred_stage_is_built_at_resolution_not_declaration() {
383 use std::sync::atomic::{AtomicUsize, Ordering};
384 static BUILT: AtomicUsize = AtomicUsize::new(0);
385
386 let stack = MiddlewareStack::new().deferred(|_| {
387 BUILT.fetch_add(1, Ordering::SeqCst);
388 Ok(First)
389 });
390
391 assert_eq!(BUILT.load(Ordering::SeqCst), 0, "declaring must not build");
392
393 assert_eq!(resolved_names(&stack), vec!["First"]);
394 assert_eq!(BUILT.load(Ordering::SeqCst), 1);
395 }
396
397 #[test]
398 fn a_deferred_stage_that_fails_names_its_type() {
399 let stack = MiddlewareStack::new()
402 .deferred(|_| Err::<First, _>(Error::internal("AuthManager is not bound")));
403
404 let err = stack.resolve(&Container::new()).err().expect("resolution should fail");
405 assert!(err.message().contains("`First`"), "{}", err.message());
406 assert!(err.message().contains("AuthManager is not bound"), "{}", err.message());
407 }
408
409 #[test]
410 fn resolved_builds_from_a_binding() {
411 struct Guard(&'static str);
412
413 let container = Container::new();
414 container.instance(Guard("bound"));
415
416 let stack = MiddlewareStack::new().resolved(|guard: Arc<Guard>| {
417 assert_eq!(guard.0, "bound");
418 First
419 });
420
421 let built = stack.resolve(&container).unwrap();
423 assert_eq!(built.iter().map(|m| m.name()).collect::<Vec<_>>(), vec!["First"]);
424 }
425
426 #[test]
427 fn resolved_reports_the_missing_binding_by_type() {
428 struct NeverBound;
431
432 let stack = MiddlewareStack::new().resolved(|_: Arc<NeverBound>| First);
433
434 let err = stack.resolve(&Container::new()).err().expect("should fail");
435 assert!(err.message().contains("`First`"), "{}", err.message());
436 assert!(err.message().contains("NeverBound"), "{}", err.message());
437 }
438
439 #[test]
440 fn a_deferred_stage_labels_itself_before_it_is_built() {
441 let stack = MiddlewareStack::new().with(First).deferred(|_| Ok(Second));
444
445 assert_eq!(stack.labels(), vec!["First", "Second"]);
446 assert_eq!(format!("{stack:?}"), r#"["First", "Second"]"#);
447 }
448
449 #[test]
450 fn a_shared_instance_is_not_cloned_per_route() {
451 let shared: Arc<dyn Middleware> = Arc::new(First);
454
455 let a = MiddlewareStack::new().with_arc(Arc::clone(&shared));
456 let b = MiddlewareStack::new().with_arc(Arc::clone(&shared));
457
458 let container = Container::new();
459 assert!(Arc::ptr_eq(
460 &a.resolve(&container).unwrap()[0],
461 &b.resolve(&container).unwrap()[0]
462 ));
463 }
464}