From 318b067a06ecb42f0fba51928675d3b4291c7643 Mon Sep 17 00:00:00 2001 From: Fernando Mendez Date: Sat, 7 Feb 2015 15:50:51 -0400 Subject: [PATCH] feat(headers): Add `If-None-Match` header field Add the HTTP/1.1 `If-None-Match` header field makes the request method conditional on a recipient cache or origin server either not having any current representation of the target resource, when the field-value is "*", or having a selected representation with an entity-tag that does not match any of those listed in the field-value. Closes #238 --- src/header/common/if_none_match.rs | 84 ++++++++++++++++++++++++++++++ src/header/common/mod.rs | 2 + 2 files changed, 86 insertions(+) create mode 100644 src/header/common/if_none_match.rs diff --git a/src/header/common/if_none_match.rs b/src/header/common/if_none_match.rs new file mode 100644 index 0000000000..ef1211d841 --- /dev/null +++ b/src/header/common/if_none_match.rs @@ -0,0 +1,84 @@ +use header::{Header, HeaderFormat, EntityTag}; +use header::parsing::{from_comma_delimited, fmt_comma_delimited, from_one_raw_str}; +use std::fmt::{self}; + +/// The `If-None-Match` header defined by HTTP/1.1. +/// +/// The "If-None-Match" header field makes the request method conditional +/// on a recipient cache or origin server either not having any current +/// representation of the target resource, when the field-value is "*", +/// or having a selected representation with an entity-tag that does not +/// match any of those listed in the field-value. +/// +/// A recipient MUST use the weak comparison function when comparing +/// entity-tags for If-None-Match (Section 2.3.2), since weak entity-tags +/// can be used for cache validation even if there have been changes to +/// the representation data. +/// +/// Spec: https://tools.ietf.org/html/rfc7232#section-3.2 + +/// The `If-None-Match` header field. +#[derive(Clone, PartialEq, Debug)] +pub enum IfNoneMatch { + /// This corresponds to '*'. + Any, + /// The header field names which will influence the response representation. + EntityTags(Vec) +} + +impl Header for IfNoneMatch { + fn header_name() -> &'static str { + "If-None-Match" + } + + fn parse_header(raw: &[Vec]) -> Option { + from_one_raw_str(raw).and_then(|s: String| { + let slice = &s[]; + match slice { + "" => None, + "*" => Some(IfNoneMatch::Any), + _ => from_comma_delimited(raw).map(|vec| IfNoneMatch::EntityTags(vec)), + } + }) + } +} + +impl HeaderFormat for IfNoneMatch { + fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + IfNoneMatch::Any => { write!(fmt, "*") } + IfNoneMatch::EntityTags(ref fields) => { fmt_comma_delimited(fmt, &fields[]) } + } + } +} + +#[cfg(test)] +mod tests { + use super::IfNoneMatch; + use header::Header; + use header::EntityTag; + + #[test] + fn test_if_none_match() { + let mut if_none_match: Option; + + if_none_match = Header::parse_header([b"*".to_vec()].as_slice()); + assert_eq!(if_none_match, Some(IfNoneMatch::Any)); + + if_none_match = Header::parse_header([b"\"foobar\", W/\"weak-etag\"".to_vec()].as_slice()); + let mut entities: Vec = Vec::new(); + let foobar_etag = EntityTag { + weak: false, + tag: "foobar".to_string() + }; + let weak_etag = EntityTag { + weak: true, + tag: "weak-etag".to_string() + }; + entities.push(foobar_etag); + entities.push(weak_etag); + assert_eq!(if_none_match, Some(IfNoneMatch::EntityTags(entities))); + } +} + +bench_header!(bench, IfNoneMatch, { vec![b"W/\"nonemptytag\"".to_vec()] }); diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index bb6ec9a372..f9bbd0fb7c 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -21,6 +21,7 @@ pub use self::etag::Etag; pub use self::expires::Expires; pub use self::host::Host; pub use self::if_modified_since::IfModifiedSince; +pub use self::if_none_match::IfNoneMatch; pub use self::if_unmodified_since::IfUnmodifiedSince; pub use self::last_modified::LastModified; pub use self::location::Location; @@ -158,6 +159,7 @@ mod expires; mod host; mod last_modified; mod if_modified_since; +mod if_none_match; mod if_unmodified_since; mod location; mod pragma;