hyper_sync/header/common/
warning.rs

1use std::fmt;
2use std::str::{FromStr};
3
4use header::{Header, HttpDate, Raw};
5use header::parsing::from_one_raw_str;
6
7/// `Warning` header, defined in [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.5)
8///
9/// The `Warning` header field can be be used to carry additional information
10/// about the status or transformation of a message that might not be reflected
11/// in the status code. This header is sometimes used as backwards
12/// compatible way to notify of a deprecated API.
13///
14/// # ABNF
15///
16/// ```text
17/// Warning       = 1#warning-value
18/// warning-value = warn-code SP warn-agent SP warn-text
19///                                       [ SP warn-date ]
20/// warn-code  = 3DIGIT
21/// warn-agent = ( uri-host [ ":" port ] ) / pseudonym
22///                 ; the name or pseudonym of the server adding
23///                 ; the Warning header field, for use in debugging
24///                 ; a single "-" is recommended when agent unknown
25/// warn-text  = quoted-string
26/// warn-date  = DQUOTE HTTP-date DQUOTE
27/// ```
28///
29/// # Example values
30///
31/// * `Warning: 112 - "network down" "Sat, 25 Aug 2012 23:34:45 GMT"`
32/// * `Warning: 299 - "Deprecated API " "Tue, 15 Nov 1994 08:12:31 GMT"`
33/// * `Warning: 299 api.hyper.rs:8080 "Deprecated API : use newapi.hyper.rs instead."`
34/// * `Warning: 299 api.hyper.rs:8080 "Deprecated API : use newapi.hyper.rs instead." "Tue, 15 Nov 1994 08:12:31 GMT"`
35///
36/// # Examples
37///
38/// ```
39/// use hyper_sync::header::{Headers, Warning};
40///
41/// let mut headers = Headers::new();
42/// headers.set(
43///     Warning{
44///         code: 299,
45///         agent: "api.hyper.rs".to_owned(),
46///         text: "Deprecated".to_owned(),
47///         date: None
48///     }
49/// );
50/// ```
51///
52/// ```
53/// use hyper_sync::header::{Headers, HttpDate, Warning};
54///
55/// let mut headers = Headers::new();
56/// headers.set(
57///     Warning{
58///         code: 299,
59///         agent: "api.hyper.rs".to_owned(),
60///         text: "Deprecated".to_owned(),
61///         date: "Tue, 15 Nov 1994 08:12:31 GMT".parse::<HttpDate>().ok()
62///     }
63/// );
64/// ```
65///
66/// ```
67/// use std::time::SystemTime;
68/// use hyper_sync::header::{Headers, Warning};
69///
70/// let mut headers = Headers::new();
71/// headers.set(
72///     Warning{
73///         code: 199,
74///         agent: "api.hyper.rs".to_owned(),
75///         text: "Deprecated".to_owned(),
76///         date: Some(SystemTime::now().into())
77///     }
78/// );
79/// ```
80#[derive(PartialEq, Clone, Debug)]
81pub struct Warning {
82    /// The 3 digit warn code.
83    pub code: u16,
84    /// The name or pseudonym of the server adding this header.
85    pub agent: String,
86    /// The warning message describing the error.
87    pub text: String,
88    /// An optional warning date.
89    pub date: Option<HttpDate>
90}
91
92impl Header for Warning {
93    fn header_name() -> &'static str {
94        static NAME: &'static str = "Warning";
95        NAME
96    }
97
98    fn parse_header(raw: &Raw) -> ::Result<Warning> {
99        from_one_raw_str(raw)
100    }
101
102    fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
103        f.fmt_line(self)
104    }
105}
106
107impl fmt::Display for Warning {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        match self.date {
110            Some(date) => write!(f, "{:03} {} \"{}\" \"{}\"", self.code, self.agent, self.text, date),
111            None => write!(f, "{:03} {} \"{}\"", self.code, self.agent, self.text)
112        }
113    }
114}
115
116impl FromStr for Warning {
117    type Err = ::Error;
118
119    fn from_str(s: &str) -> ::Result<Warning> {
120        let mut warning_split = s.split_whitespace();
121        let code = match warning_split.next() {
122            Some(c) => match c.parse::<u16>() {
123                Ok(c) => c,
124                Err(..) => return Err(::Error::Header)
125            },
126            None => return Err(::Error::Header)
127        };
128        let agent = match warning_split.next() {
129            Some(a) => a.to_string(),
130            None => return Err(::Error::Header)
131        };
132
133        let mut warning_split = s.split('"').skip(1);
134        let text = match warning_split.next() {
135            Some(t) => t.to_string(),
136            None => return Err(::Error::Header)
137        };
138        let date = match warning_split.skip(1).next() {
139            Some(d) => d.parse::<HttpDate>().ok(),
140            None => None // Optional
141        };
142
143        Ok(Warning {
144            code: code,
145            agent: agent,
146            text: text,
147            date: date
148        })
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::Warning;
155    use header::{Header, HttpDate};
156
157    #[test]
158    fn test_parsing() {
159        let warning = Header::parse_header(&vec![b"112 - \"network down\" \"Sat, 25 Aug 2012 23:34:45 GMT\"".to_vec()].into());
160        assert_eq!(warning.ok(), Some(Warning {
161            code: 112,
162            agent: "-".to_owned(),
163            text: "network down".to_owned(),
164            date: "Sat, 25 Aug 2012 23:34:45 GMT".parse::<HttpDate>().ok()
165        }));
166
167        let warning = Header::parse_header(&vec![b"299 api.hyper.rs:8080 \"Deprecated API : use newapi.hyper.rs instead.\"".to_vec()].into());
168        assert_eq!(warning.ok(), Some(Warning {
169            code: 299,
170            agent: "api.hyper.rs:8080".to_owned(),
171            text: "Deprecated API : use newapi.hyper.rs instead.".to_owned(),
172            date: None
173        }));
174
175        let warning = Header::parse_header(&vec![b"299 api.hyper.rs:8080 \"Deprecated API : use newapi.hyper.rs instead.\" \"Tue, 15 Nov 1994 08:12:31 GMT\"".to_vec()].into());
176        assert_eq!(warning.ok(), Some(Warning {
177            code: 299,
178            agent: "api.hyper.rs:8080".to_owned(),
179            text: "Deprecated API : use newapi.hyper.rs instead.".to_owned(),
180            date: "Tue, 15 Nov 1994 08:12:31 GMT".parse::<HttpDate>().ok()
181        }));
182    }
183}