Skip to main content

tower_request_guard/
content_type.rs

1/// Extracts the media type from a Content-Type header value,
2/// stripping parameters like charset and boundary.
3fn extract_media_type(content_type: &str) -> &str {
4    content_type
5        .split(';')
6        .next()
7        .unwrap_or(content_type)
8        .trim()
9}
10
11/// Check if a Content-Type value matches any of the allowed types.
12/// Comparison is case-insensitive and ignores parameters.
13pub 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}