Skip to main content

salvo_cache/
skipper.rs

1use std::collections::HashSet;
2
3use salvo_core::handler::Skipper;
4use salvo_core::http::Method;
5use salvo_core::{Depot, Request};
6
7/// Skipper for `Method`. You can use it to skip some methods.
8///
9/// If the request method is in the skip list, the request will be skipped.
10#[derive(Default, Clone, Debug)]
11pub struct MethodSkipper {
12    skipped_methods: HashSet<Method>,
13}
14impl MethodSkipper {
15    /// Create a new `MethodSkipper`.
16    #[must_use]
17    pub fn new() -> Self {
18        Self {
19            skipped_methods: HashSet::new(),
20        }
21    }
22    /// Add the [`Method::GET`] method to skipped methods.
23    #[must_use]
24    pub fn skip_get(self, value: bool) -> Self {
25        self.skip_method(Method::GET, value)
26    }
27    /// Add the [`Method::POST`] method to skipped methods.
28    #[must_use]
29    pub fn skip_post(self, value: bool) -> Self {
30        self.skip_method(Method::POST, value)
31    }
32    /// Add the [`Method::PUT`] method to skipped methods.
33    #[must_use]
34    pub fn skip_put(self, value: bool) -> Self {
35        self.skip_method(Method::PUT, value)
36    }
37    /// Add the [`Method::DELETE`] method to skipped methods.
38    #[must_use]
39    pub fn skip_delete(self, value: bool) -> Self {
40        self.skip_method(Method::DELETE, value)
41    }
42    /// Add the [`Method::HEAD`] method to skipped methods.
43    #[must_use]
44    pub fn skip_head(self, value: bool) -> Self {
45        self.skip_method(Method::HEAD, value)
46    }
47    /// Add the [`Method::PATCH`] method to skipped methods.
48    #[must_use]
49    pub fn skip_patch(self, value: bool) -> Self {
50        self.skip_method(Method::PATCH, value)
51    }
52    /// Add the [`Method::OPTIONS`] method to skipped methods.
53    #[must_use]
54    pub fn skip_options(self, value: bool) -> Self {
55        self.skip_method(Method::OPTIONS, value)
56    }
57    /// Add the [`Method::CONNECT`] method to skipped methods.
58    #[must_use]
59    pub fn skip_connect(self, value: bool) -> Self {
60        self.skip_method(Method::CONNECT, value)
61    }
62    /// Add the [`Method::TRACE`] method to skipped methods.
63    #[must_use]
64    pub fn skip_trace(self, value: bool) -> Self {
65        self.skip_method(Method::TRACE, value)
66    }
67    /// Add a [`Method`] to skipped methods.
68    #[must_use]
69    pub fn skip_method(mut self, method: Method, value: bool) -> Self {
70        if value {
71            self.skipped_methods.insert(method);
72        } else {
73            self.skipped_methods.remove(&method);
74        }
75        self
76    }
77    /// Add all methods to skipped methods.
78    #[must_use]
79    pub fn skip_all(mut self) -> Self {
80        self.skipped_methods = [
81            Method::GET,
82            Method::POST,
83            Method::PUT,
84            Method::DELETE,
85            Method::HEAD,
86            Method::PATCH,
87            Method::OPTIONS,
88            Method::CONNECT,
89            Method::TRACE,
90        ]
91        .into_iter()
92        .collect();
93        self
94    }
95}
96impl Skipper for MethodSkipper {
97    fn skipped(&self, req: &mut Request, _depot: &Depot) -> bool {
98        self.skipped_methods.contains(req.method())
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use salvo_core::http::Method;
105
106    use super::*;
107
108    #[test]
109    fn test_method_skipper_new() {
110        let skipper = MethodSkipper::new();
111        assert!(skipper.skipped_methods.is_empty());
112    }
113
114    #[test]
115    fn test_method_skipper_default() {
116        let skipper = MethodSkipper::default();
117        assert!(skipper.skipped_methods.is_empty());
118    }
119
120    #[test]
121    fn test_skip_get() {
122        let skipper = MethodSkipper::new().skip_get(true);
123        assert!(skipper.skipped_methods.contains(&Method::GET));
124
125        let skipper = skipper.skip_get(false);
126        assert!(!skipper.skipped_methods.contains(&Method::GET));
127    }
128
129    #[test]
130    fn test_skip_post() {
131        let skipper = MethodSkipper::new().skip_post(true);
132        assert!(skipper.skipped_methods.contains(&Method::POST));
133
134        let skipper = skipper.skip_post(false);
135        assert!(!skipper.skipped_methods.contains(&Method::POST));
136    }
137
138    #[test]
139    fn test_skip_put() {
140        let skipper = MethodSkipper::new().skip_put(true);
141        assert!(skipper.skipped_methods.contains(&Method::PUT));
142
143        let skipper = skipper.skip_put(false);
144        assert!(!skipper.skipped_methods.contains(&Method::PUT));
145    }
146
147    #[test]
148    fn test_skip_delete() {
149        let skipper = MethodSkipper::new().skip_delete(true);
150        assert!(skipper.skipped_methods.contains(&Method::DELETE));
151
152        let skipper = skipper.skip_delete(false);
153        assert!(!skipper.skipped_methods.contains(&Method::DELETE));
154    }
155
156    #[test]
157    fn test_skip_head() {
158        let skipper = MethodSkipper::new().skip_head(true);
159        assert!(skipper.skipped_methods.contains(&Method::HEAD));
160
161        let skipper = skipper.skip_head(false);
162        assert!(!skipper.skipped_methods.contains(&Method::HEAD));
163    }
164
165    #[test]
166    fn test_skip_patch() {
167        let skipper = MethodSkipper::new().skip_patch(true);
168        assert!(skipper.skipped_methods.contains(&Method::PATCH));
169
170        let skipper = skipper.skip_patch(false);
171        assert!(!skipper.skipped_methods.contains(&Method::PATCH));
172    }
173
174    #[test]
175    fn test_skip_options() {
176        let skipper = MethodSkipper::new().skip_options(true);
177        assert!(skipper.skipped_methods.contains(&Method::OPTIONS));
178
179        let skipper = skipper.skip_options(false);
180        assert!(!skipper.skipped_methods.contains(&Method::OPTIONS));
181    }
182
183    #[test]
184    fn test_skip_connect() {
185        let skipper = MethodSkipper::new().skip_connect(true);
186        assert!(skipper.skipped_methods.contains(&Method::CONNECT));
187
188        let skipper = skipper.skip_connect(false);
189        assert!(!skipper.skipped_methods.contains(&Method::CONNECT));
190    }
191
192    #[test]
193    fn test_skip_trace() {
194        let skipper = MethodSkipper::new().skip_trace(true);
195        assert!(skipper.skipped_methods.contains(&Method::TRACE));
196
197        let skipper = skipper.skip_trace(false);
198        assert!(!skipper.skipped_methods.contains(&Method::TRACE));
199    }
200
201    #[test]
202    fn test_skip_all() {
203        let skipper = MethodSkipper::new().skip_all();
204        assert!(skipper.skipped_methods.contains(&Method::GET));
205        assert!(skipper.skipped_methods.contains(&Method::POST));
206        assert!(skipper.skipped_methods.contains(&Method::PUT));
207        assert!(skipper.skipped_methods.contains(&Method::DELETE));
208        assert!(skipper.skipped_methods.contains(&Method::HEAD));
209        assert!(skipper.skipped_methods.contains(&Method::PATCH));
210        assert!(skipper.skipped_methods.contains(&Method::OPTIONS));
211        assert!(skipper.skipped_methods.contains(&Method::CONNECT));
212        assert!(skipper.skipped_methods.contains(&Method::TRACE));
213        assert_eq!(skipper.skipped_methods.len(), 9);
214    }
215
216    #[test]
217    fn test_skip_method_chain() {
218        let skipper = MethodSkipper::new()
219            .skip_get(true)
220            .skip_post(true)
221            .skip_put(true);
222        assert!(skipper.skipped_methods.contains(&Method::GET));
223        assert!(skipper.skipped_methods.contains(&Method::POST));
224        assert!(skipper.skipped_methods.contains(&Method::PUT));
225        assert_eq!(skipper.skipped_methods.len(), 3);
226    }
227
228    #[test]
229    fn test_skip_all_then_allow_get() {
230        let skipper = MethodSkipper::new().skip_all().skip_get(false);
231        assert!(!skipper.skipped_methods.contains(&Method::GET));
232        assert!(skipper.skipped_methods.contains(&Method::POST));
233        assert_eq!(skipper.skipped_methods.len(), 8);
234    }
235
236    #[test]
237    fn test_method_skipper_debug() {
238        let skipper = MethodSkipper::new().skip_get(true);
239        let debug_str = format!("{:?}", skipper);
240        assert!(debug_str.contains("MethodSkipper"));
241        assert!(debug_str.contains("skipped_methods"));
242    }
243
244    #[test]
245    fn test_method_skipper_clone() {
246        let skipper = MethodSkipper::new().skip_get(true).skip_post(true);
247        let cloned = skipper.clone();
248        assert_eq!(skipper.skipped_methods, cloned.skipped_methods);
249    }
250}