gotham/router/route/matcher/
access_control_request_method.rs1use crate::router::non_match::RouteNonMatch;
4use crate::router::route::matcher::RouteMatcher;
5use crate::state::{FromState, State};
6use hyper::header::{HeaderMap, ACCESS_CONTROL_REQUEST_METHOD};
7use hyper::{Method, StatusCode};
8
9#[derive(Clone, Debug)]
35pub struct AccessControlRequestMethodMatcher {
36 method: Method,
37}
38
39impl AccessControlRequestMethodMatcher {
40 pub fn new(method: Method) -> Self {
45 Self { method }
46 }
47}
48
49impl RouteMatcher for AccessControlRequestMethodMatcher {
50 fn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {
51 match HeaderMap::borrow_from(state)
54 .get(ACCESS_CONTROL_REQUEST_METHOD)
55 .and_then(|value| value.to_str().ok())
56 .and_then(|str| str.to_ascii_uppercase().parse::<Method>().ok())
57 {
58 Some(m) if m == self.method => Ok(()),
59 _ => Err(RouteNonMatch::new(StatusCode::NOT_FOUND)),
60 }
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::*;
67
68 fn with_state<F>(accept: Option<&str>, block: F)
69 where
70 F: FnOnce(&mut State),
71 {
72 State::with_new(|state| {
73 let mut headers = HeaderMap::new();
74 if let Some(acc) = accept {
75 headers.insert(ACCESS_CONTROL_REQUEST_METHOD, acc.parse().unwrap());
76 }
77 state.put(headers);
78 block(state);
79 });
80 }
81
82 #[test]
83 fn no_acrm_header() {
84 let matcher = AccessControlRequestMethodMatcher::new(Method::PUT);
85 with_state(None, |state| assert!(matcher.is_match(state).is_err()));
86 }
87
88 #[test]
89 fn correct_acrm_header() {
90 let matcher = AccessControlRequestMethodMatcher::new(Method::PUT);
91 with_state(Some("PUT"), |state| {
92 assert!(matcher.is_match(state).is_ok())
93 });
94 with_state(Some("put"), |state| {
95 assert!(matcher.is_match(state).is_ok())
96 });
97 }
98
99 #[test]
100 fn incorrect_acrm_header() {
101 let matcher = AccessControlRequestMethodMatcher::new(Method::PUT);
102 with_state(Some("DELETE"), |state| {
103 assert!(matcher.is_match(state).is_err())
104 });
105 }
106}