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_delete(self, value: bool) -> Self {
40 self.skip_method(Method::DELETE, value)
41 }
42 #[must_use]
44 pub fn skip_head(self, value: bool) -> Self {
45 self.skip_method(Method::HEAD, value)
46 }
47 #[must_use]
49 pub fn skip_patch(self, value: bool) -> Self {
50 self.skip_method(Method::PATCH, value)
51 }
52 #[must_use]
54 pub fn skip_options(self, value: bool) -> Self {
55 self.skip_method(Method::OPTIONS, value)
56 }
57 #[must_use]
59 pub fn skip_connect(self, value: bool) -> Self {
60 self.skip_method(Method::CONNECT, value)
61 }
62 #[must_use]
64 pub fn skip_trace(self, value: bool) -> Self {
65 self.skip_method(Method::TRACE, value)
66 }
67 #[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 #[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}