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