tower_request_guard/
content_type.rs1fn extract_media_type(content_type: &str) -> &str {
4 content_type
5 .split(';')
6 .next()
7 .unwrap_or(content_type)
8 .trim()
9}
10
11pub fn matches_content_type(content_type: &str, allowed: &[String]) -> bool {
14 let media_type = extract_media_type(content_type);
15 allowed.iter().any(|a| a.eq_ignore_ascii_case(media_type))
16}
17
18#[cfg(test)]
19mod tests {
20 use super::*;
21
22 #[test]
23 fn exact_match() {
24 let allowed = vec!["application/json".to_string()];
25 assert!(matches_content_type("application/json", &allowed));
26 }
27
28 #[test]
29 fn matches_ignoring_params() {
30 let allowed = vec!["application/json".to_string()];
31 assert!(matches_content_type(
32 "application/json; charset=utf-8",
33 &allowed
34 ));
35 }
36
37 #[test]
38 fn matches_case_insensitive() {
39 let allowed = vec!["application/json".to_string()];
40 assert!(matches_content_type("Application/JSON", &allowed));
41 }
42
43 #[test]
44 fn rejects_non_matching() {
45 let allowed = vec!["application/json".to_string()];
46 assert!(!matches_content_type("text/xml", &allowed));
47 }
48
49 #[test]
50 fn multiple_allowed() {
51 let allowed = vec![
52 "application/json".to_string(),
53 "multipart/form-data".to_string(),
54 ];
55 assert!(matches_content_type(
56 "multipart/form-data; boundary=abc",
57 &allowed
58 ));
59 assert!(!matches_content_type("text/plain", &allowed));
60 }
61
62 #[test]
63 fn empty_allowed_rejects_all() {
64 let allowed: Vec<String> = vec![];
65 assert!(!matches_content_type("application/json", &allowed));
66 }
67}