1use std::collections::HashSet;
2
3use salvo_core::handler::Skipper;
4use salvo_core::http::Method;
5use salvo_core::{Depot, Request};
6
7#[derive(Default, Clone, Debug)]
11pub struct MethodSkipper {
12 skipped_methods: HashSet<Method>,
13}
14impl MethodSkipper {
15 #[must_use]
17 pub fn new() -> Self {
18 Self {
19 skipped_methods: HashSet::new(),
20 }
21 }
22 #[must_use]
24 pub fn skip_get(self, value: bool) -> Self {
25 self.skip_method(Method::GET, value)
26 }
27 #[must_use]
29 pub fn skip_post(self, value: bool) -> Self {
30 self.skip_method(Method::POST, value)
31 }
32 #[must_use]
34 pub fn skip_put(self, value: bool) -> Self {
35 self.skip_method(Method::PUT, value)
36 }
37 #[must_use]
39 pub fn skip_query(self, value: bool) -> Self {
40 self.skip_method(Method::QUERY, value)
41 }
42 #[must_use]
44 pub fn skip_delete(self, value: bool) -> Self {
45 self.skip_method(Method::DELETE, value)
46 }
47 #[must_use]
49 pub fn skip_head(self, value: bool) -> Self {
50 self.skip_method(Method::HEAD, value)
51 }
52 #[must_use]
54 pub fn skip_patch(self, value: bool) -> Self {
55 self.skip_method(Method::PATCH, value)
56 }
57 #[must_use]
59 pub fn skip_options(self, value: bool) -> Self {
60 self.skip_method(Method::OPTIONS, value)
61 }
62 #[must_use]
64 pub fn skip_connect(self, value: bool) -> Self {
65 self.skip_method(Method::CONNECT, value)
66 }
67 #[must_use]
69 pub fn skip_trace(self, value: bool) -> Self {
70 self.skip_method(Method::TRACE, value)
71 }
72 #[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 #[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}