Merge pull request #910 from smithsps/feat-warning-header
feat(headers): add Warning header
This commit is contained in:
@@ -58,6 +58,7 @@ pub use self::transfer_encoding::TransferEncoding;
|
|||||||
pub use self::upgrade::{Upgrade, Protocol, ProtocolName};
|
pub use self::upgrade::{Upgrade, Protocol, ProtocolName};
|
||||||
pub use self::user_agent::UserAgent;
|
pub use self::user_agent::UserAgent;
|
||||||
pub use self::vary::Vary;
|
pub use self::vary::Vary;
|
||||||
|
pub use self::warning::Warning;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@@ -420,3 +421,4 @@ mod transfer_encoding;
|
|||||||
mod upgrade;
|
mod upgrade;
|
||||||
mod user_agent;
|
mod user_agent;
|
||||||
mod vary;
|
mod vary;
|
||||||
|
mod warning;
|
||||||
174
src/header/common/warning.rs
Normal file
174
src/header/common/warning.rs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
use std::fmt;
|
||||||
|
use std::str::{FromStr};
|
||||||
|
use header::{Header, HttpDate, Raw};
|
||||||
|
use header::parsing::from_one_raw_str;
|
||||||
|
|
||||||
|
/// `Warning` header, defined in [RFC7234](https://tools.ietf.org/html/rfc7234#section-5.5)
|
||||||
|
///
|
||||||
|
/// The `Warning` header field can be be used to carry additional information
|
||||||
|
/// about the status or transformation of a message that might not be reflected
|
||||||
|
/// in the status code. This header is sometimes used as backwards
|
||||||
|
/// compatible way to notify of a deprecated API.
|
||||||
|
///
|
||||||
|
/// # ABNF
|
||||||
|
/// ```plain
|
||||||
|
/// Warning = 1#warning-value
|
||||||
|
/// warning-value = warn-code SP warn-agent SP warn-text
|
||||||
|
/// [ SP warn-date ]
|
||||||
|
/// warn-code = 3DIGIT
|
||||||
|
/// warn-agent = ( uri-host [ ":" port ] ) / pseudonym
|
||||||
|
/// ; the name or pseudonym of the server adding
|
||||||
|
/// ; the Warning header field, for use in debugging
|
||||||
|
/// ; a single "-" is recommended when agent unknown
|
||||||
|
/// warn-text = quoted-string
|
||||||
|
/// warn-date = DQUOTE HTTP-date DQUOTE
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Example values
|
||||||
|
/// * `Warning: 112 - "network down" "Sat, 25 Aug 2012 23:34:45 GMT"`
|
||||||
|
/// * `Warning: 299 - "Deprecated API " "Tue, 15 Nov 1994 08:12:31 GMT"`
|
||||||
|
/// * `Warning: 299 api.hyper.rs:8080 "Deprecated API : use newapi.hyper.rs instead."`
|
||||||
|
/// * `Warning: 299 api.hyper.rs:8080 "Deprecated API : use newapi.hyper.rs instead." "Tue, 15 Nov 1994 08:12:31 GMT"`
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use hyper::header::{Headers, Warning};
|
||||||
|
///
|
||||||
|
/// let mut headers = Headers::new();
|
||||||
|
/// headers.set(
|
||||||
|
/// Warning{
|
||||||
|
/// code: 299,
|
||||||
|
/// agent: "api.hyper.rs".to_owned(),
|
||||||
|
/// text: "Deprecated".to_owned(),
|
||||||
|
/// date: None
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
/// ```
|
||||||
|
/// use hyper::header::{Headers, HttpDate, Warning};
|
||||||
|
///
|
||||||
|
/// let mut headers = Headers::new();
|
||||||
|
/// headers.set(
|
||||||
|
/// Warning{
|
||||||
|
/// code: 299,
|
||||||
|
/// agent: "api.hyper.rs".to_owned(),
|
||||||
|
/// text: "Deprecated".to_owned(),
|
||||||
|
/// date: "Tue, 15 Nov 1994 08:12:31 GMT".parse::<HttpDate>().ok()
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
/// ```
|
||||||
|
/// # extern crate hyper;
|
||||||
|
/// # extern crate time;
|
||||||
|
/// # fn main() {
|
||||||
|
/// use hyper::header::{Headers, HttpDate, Warning};
|
||||||
|
///
|
||||||
|
/// let mut headers = Headers::new();
|
||||||
|
/// headers.set(
|
||||||
|
/// Warning{
|
||||||
|
/// code: 199,
|
||||||
|
/// agent: "api.hyper.rs".to_owned(),
|
||||||
|
/// text: "Deprecated".to_owned(),
|
||||||
|
/// date: Some(HttpDate(time::now()))
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
pub struct Warning {
|
||||||
|
/// The 3 digit warn code.
|
||||||
|
pub code: u16,
|
||||||
|
/// The name or pseudonym of the server adding this header.
|
||||||
|
pub agent: String,
|
||||||
|
/// The warning message describing the error.
|
||||||
|
pub text: String,
|
||||||
|
/// An optional warning date.
|
||||||
|
pub date: Option<HttpDate>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Header for Warning {
|
||||||
|
fn header_name() -> &'static str {
|
||||||
|
static NAME: &'static str = "Warning";
|
||||||
|
NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_header(raw: &Raw) -> ::Result<Warning> {
|
||||||
|
from_one_raw_str(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self.date {
|
||||||
|
Some(date) => write!(f, "{:03} {} \"{}\" \"{}\"", self.code, self.agent, self.text, date),
|
||||||
|
None => write!(f, "{:03} {} \"{}\"", self.code, self.agent, self.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Warning {
|
||||||
|
type Err = ::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> ::Result<Warning> {
|
||||||
|
let mut warning_split = s.split_whitespace();
|
||||||
|
let code = match warning_split.next() {
|
||||||
|
Some(c) => match c.parse::<u16>() {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(..) => return Err(::Error::Header)
|
||||||
|
},
|
||||||
|
None => return Err(::Error::Header)
|
||||||
|
};
|
||||||
|
let agent = match warning_split.next() {
|
||||||
|
Some(a) => a.to_string(),
|
||||||
|
None => return Err(::Error::Header)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut warning_split = s.split('"').skip(1);
|
||||||
|
let text = match warning_split.next() {
|
||||||
|
Some(t) => t.to_string(),
|
||||||
|
None => return Err(::Error::Header)
|
||||||
|
};
|
||||||
|
let date = match warning_split.skip(1).next() {
|
||||||
|
Some(d) => d.parse::<HttpDate>().ok(),
|
||||||
|
None => None // Optional
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Warning {
|
||||||
|
code: code,
|
||||||
|
agent: agent,
|
||||||
|
text: text,
|
||||||
|
date: date
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::Warning;
|
||||||
|
use header::{Header, HttpDate};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parsing() {
|
||||||
|
let warning = Header::parse_header(&vec![b"112 - \"network down\" \"Sat, 25 Aug 2012 23:34:45 GMT\"".to_vec()].into());
|
||||||
|
assert_eq!(warning.ok(), Some(Warning {
|
||||||
|
code: 112,
|
||||||
|
agent: "-".to_owned(),
|
||||||
|
text: "network down".to_owned(),
|
||||||
|
date: "Sat, 25 Aug 2012 23:34:45 GMT".parse::<HttpDate>().ok()
|
||||||
|
}));
|
||||||
|
|
||||||
|
let warning = Header::parse_header(&vec![b"299 api.hyper.rs:8080 \"Deprecated API : use newapi.hyper.rs instead.\"".to_vec()].into());
|
||||||
|
assert_eq!(warning.ok(), Some(Warning {
|
||||||
|
code: 299,
|
||||||
|
agent: "api.hyper.rs:8080".to_owned(),
|
||||||
|
text: "Deprecated API : use newapi.hyper.rs instead.".to_owned(),
|
||||||
|
date: None
|
||||||
|
}));
|
||||||
|
|
||||||
|
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());
|
||||||
|
assert_eq!(warning.ok(), Some(Warning {
|
||||||
|
code: 299,
|
||||||
|
agent: "api.hyper.rs:8080".to_owned(),
|
||||||
|
text: "Deprecated API : use newapi.hyper.rs instead.".to_owned(),
|
||||||
|
date: "Tue, 15 Nov 1994 08:12:31 GMT".parse::<HttpDate>().ok()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user