gotham/helpers/http/
mod.rs

1//! Helpers for HTTP request handling and response generation
2
3pub mod header;
4pub mod request;
5pub mod response;
6
7use log::trace;
8use percent_encoding::percent_decode;
9
10/// Represents data that has been successfully percent decoded and is valid UTF-8
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct PercentDecoded {
13    val: String,
14}
15
16impl PercentDecoded {
17    /// Attempt to decode data that has been provided in a perecent encoded format and ensure that
18    /// the result is valid UTF-8.
19    ///
20    /// On success, the decoded data is returned as a `PercentDecoded` value, which allows a
21    /// compile-time check that the decode has occurred in places where it's assumed to have
22    /// occurred.
23    pub(crate) fn new(raw: &str) -> Option<Self> {
24        match percent_decode(raw.as_bytes()).decode_utf8() {
25            Ok(pd) => {
26                trace!(" percent_decode: {}, src: {}", pd, raw);
27                Some(PercentDecoded {
28                    val: pd.into_owned(),
29                })
30            }
31            Err(_) => {
32                trace!(" percent_decode: error, src: {}", raw);
33                None
34            }
35        }
36    }
37}
38
39impl AsRef<str> for PercentDecoded {
40    fn as_ref(&self) -> &str {
41        &self.val
42    }
43}
44
45/// Decode form-urlencoded strings (e.g. query string, or request body with Content-Type:
46/// application/x-www-form-urlencoded
47fn form_url_decode(raw: &str) -> Result<String, std::str::Utf8Error> {
48    match percent_decode(raw.replace('+', " ").as_bytes()).decode_utf8() {
49        Ok(pd) => {
50            trace!(" form_url_decode: {}, src: {}", pd, raw);
51            Ok(pd.into_owned())
52        }
53        Err(e) => {
54            trace!(" form_url_decode: error, src: {}", raw);
55            Err(e)
56        }
57    }
58}
59
60/// Represents data that has been successfully decoded from a form-urlencoded source and is
61/// valid UTF-8
62#[derive(PartialEq, Eq, Hash, Debug)]
63pub struct FormUrlDecoded {
64    val: String,
65}
66
67impl FormUrlDecoded {
68    /// Attempt to decode data that has been provided in www-form-urlencoded format and ensure that
69    /// the result is valid UTF-8.
70    ///
71    /// On success, the decoded data is returned as a `FormUrlDecoded` value, which allows a
72    /// compile-time check that the decode has occurred in places where it's assumed to have
73    /// occurred.
74    pub(crate) fn new(raw: &str) -> Option<Self> {
75        match form_url_decode(raw) {
76            Ok(val) => Some(FormUrlDecoded { val }),
77            Err(_) => None,
78        }
79    }
80}
81
82impl AsRef<str> for FormUrlDecoded {
83    fn as_ref(&self) -> &str {
84        &self.val
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn ensure_valid_percent_decode() {
94        let pd = PercentDecoded::new("%41+%42%2B%63%20%64").unwrap();
95        assert_eq!("A+B+c d", pd.as_ref());
96    }
97
98    #[test]
99    fn ensure_valid_www_form_url_encoded_value() {
100        let f = FormUrlDecoded::new("%41+%42%2B%63%20%64").unwrap();
101        assert_eq!("A B+c d", f.as_ref());
102    }
103}