actix_web/guard/
acceptable.rs1use super::{Guard, GuardContext};
2use crate::http::header::Accept;
3
4#[derive(Debug, Clone)]
20pub struct Acceptable {
21    mime: mime::Mime,
22
23    match_star_star: bool,
27}
28
29impl Acceptable {
30    pub fn new(mime: mime::Mime) -> Self {
32        Self {
33            mime,
34            match_star_star: false,
35        }
36    }
37
38    pub fn match_star_star(mut self) -> Self {
40        self.match_star_star = true;
41        self
42    }
43}
44
45impl Guard for Acceptable {
46    fn check(&self, ctx: &GuardContext<'_>) -> bool {
47        let accept = match ctx.header::<Accept>() {
48            Some(hdr) => hdr,
49            None => return false,
50        };
51
52        let target_type = self.mime.type_();
53        let target_subtype = self.mime.subtype();
54
55        for mime in accept.0.into_iter().map(|q| q.item) {
56            return match (mime.type_(), mime.subtype()) {
57                (typ, subtype) if typ == target_type && subtype == target_subtype => true,
58                (typ, mime::STAR) if typ == target_type => true,
59                (mime::STAR, mime::STAR) if self.match_star_star => true,
60                _ => continue,
61            };
62        }
63
64        false
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::{http::header, test::TestRequest};
72
73    #[test]
74    fn test_acceptable() {
75        let req = TestRequest::default().to_srv_request();
76        assert!(!Acceptable::new(mime::APPLICATION_JSON).check(&req.guard_ctx()));
77
78        let req = TestRequest::default()
79            .insert_header((header::ACCEPT, "application/json"))
80            .to_srv_request();
81        assert!(Acceptable::new(mime::APPLICATION_JSON).check(&req.guard_ctx()));
82
83        let req = TestRequest::default()
84            .insert_header((header::ACCEPT, "text/html, application/json"))
85            .to_srv_request();
86        assert!(Acceptable::new(mime::APPLICATION_JSON).check(&req.guard_ctx()));
87    }
88
89    #[test]
90    fn test_acceptable_star() {
91        let req = TestRequest::default()
92            .insert_header((header::ACCEPT, "text/html, */*;q=0.8"))
93            .to_srv_request();
94
95        assert!(Acceptable::new(mime::APPLICATION_JSON)
96            .match_star_star()
97            .check(&req.guard_ctx()));
98    }
99}