tower_http/follow_redirect/policy/
and.rs1use super::{Action, Attempt, Policy};
2use http::Request;
3
4#[derive(Clone, Copy, Debug, Default)]
8pub struct And<A, B> {
9 a: A,
10 b: B,
11}
12
13impl<A, B> And<A, B> {
14 pub(crate) fn new<Bd, E>(a: A, b: B) -> Self
15 where
16 A: Policy<Bd, E>,
17 B: Policy<Bd, E>,
18 {
19 And { a, b }
20 }
21}
22
23impl<Bd, E, A, B> Policy<Bd, E> for And<A, B>
24where
25 A: Policy<Bd, E>,
26 B: Policy<Bd, E>,
27{
28 fn redirect(&mut self, attempt: &Attempt<'_>) -> Result<Action, E> {
29 match self.a.redirect(attempt) {
30 Ok(Action::Follow) => self.b.redirect(attempt),
31 a => a,
32 }
33 }
34
35 fn on_request(&mut self, request: &mut Request<Bd>) {
36 self.a.on_request(request);
37 self.b.on_request(request);
38 }
39
40 fn clone_body(&self, body: &Bd) -> Option<Bd> {
41 self.a.clone_body(body).or_else(|| self.b.clone_body(body))
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use http::{Method, Uri};
49
50 struct Taint<P> {
51 policy: P,
52 used: bool,
53 }
54
55 impl<P> Taint<P> {
56 fn new(policy: P) -> Self {
57 Taint {
58 policy,
59 used: false,
60 }
61 }
62 }
63
64 impl<B, E, P> Policy<B, E> for Taint<P>
65 where
66 P: Policy<B, E>,
67 {
68 fn redirect(&mut self, attempt: &Attempt<'_>) -> Result<Action, E> {
69 self.used = true;
70 self.policy.redirect(attempt)
71 }
72 }
73
74 #[test]
75 fn redirect() {
76 let attempt = Attempt {
77 status: Default::default(),
78 method: &Method::GET,
79 location: &Uri::from_static("*"),
80 previous_method: &Method::GET,
81 previous: &Uri::from_static("*"),
82 };
83
84 let mut a = Taint::new(Action::Follow);
85 let mut b = Taint::new(Action::Follow);
86 let mut policy = And::new::<(), ()>(&mut a, &mut b);
87 assert!(Policy::<(), ()>::redirect(&mut policy, &attempt)
88 .unwrap()
89 .is_follow());
90 assert!(a.used);
91 assert!(b.used);
92
93 let mut a = Taint::new(Action::Stop);
94 let mut b = Taint::new(Action::Follow);
95 let mut policy = And::new::<(), ()>(&mut a, &mut b);
96 assert!(Policy::<(), ()>::redirect(&mut policy, &attempt)
97 .unwrap()
98 .is_stop());
99 assert!(a.used);
100 assert!(!b.used); let mut a = Taint::new(Action::Follow);
103 let mut b = Taint::new(Action::Stop);
104 let mut policy = And::new::<(), ()>(&mut a, &mut b);
105 assert!(Policy::<(), ()>::redirect(&mut policy, &attempt)
106 .unwrap()
107 .is_stop());
108 assert!(a.used);
109 assert!(b.used);
110
111 let mut a = Taint::new(Action::Stop);
112 let mut b = Taint::new(Action::Stop);
113 let mut policy = And::new::<(), ()>(&mut a, &mut b);
114 assert!(Policy::<(), ()>::redirect(&mut policy, &attempt)
115 .unwrap()
116 .is_stop());
117 assert!(a.used);
118 assert!(!b.used);
119 }
120}