Skip to content

Commit 318b067

Browse files
committed
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
1 parent f836ee8 commit 318b067

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/header/common/if_none_match.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use header::{Header, HeaderFormat, EntityTag};
2+
use header::parsing::{from_comma_delimited, fmt_comma_delimited, from_one_raw_str};
3+
use std::fmt::{self};
4+
5+
/// The `If-None-Match` header defined by HTTP/1.1.
6+
///
7+
/// The "If-None-Match" header field makes the request method conditional
8+
/// on a recipient cache or origin server either not having any current
9+
/// representation of the target resource, when the field-value is "*",
10+
/// or having a selected representation with an entity-tag that does not
11+
/// match any of those listed in the field-value.
12+
///
13+
/// A recipient MUST use the weak comparison function when comparing
14+
/// entity-tags for If-None-Match (Section 2.3.2), since weak entity-tags
15+
/// can be used for cache validation even if there have been changes to
16+
/// the representation data.
17+
///
18+
/// Spec: https://tools.ietf.org/html/rfc7232#section-3.2
19+
20+
/// The `If-None-Match` header field.
21+
#[derive(Clone, PartialEq, Debug)]
22+
pub enum IfNoneMatch {
23+
/// This corresponds to '*'.
24+
Any,
25+
/// The header field names which will influence the response representation.
26+
EntityTags(Vec<EntityTag>)
27+
}
28+
29+
impl Header for IfNoneMatch {
30+
fn header_name() -> &'static str {
31+
"If-None-Match"
32+
}
33+
34+
fn parse_header(raw: &[Vec<u8>]) -> Option<IfNoneMatch> {
35+
from_one_raw_str(raw).and_then(|s: String| {
36+
let slice = &s[];
37+
match slice {
38+
"" => None,
39+
"*" => Some(IfNoneMatch::Any),
40+
_ => from_comma_delimited(raw).map(|vec| IfNoneMatch::EntityTags(vec)),
41+
}
42+
})
43+
}
44+
}
45+
46+
impl HeaderFormat for IfNoneMatch {
47+
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
48+
match *self {
49+
IfNoneMatch::Any => { write!(fmt, "*") }
50+
IfNoneMatch::EntityTags(ref fields) => { fmt_comma_delimited(fmt, &fields[]) }
51+
}
52+
}
53+
}
54+
55+
#[cfg(test)]
56+
mod tests {
57+
use super::IfNoneMatch;
58+
use header::Header;
59+
use header::EntityTag;
60+
61+
#[test]
62+
fn test_if_none_match() {
63+
let mut if_none_match: Option<IfNoneMatch>;
64+
65+
if_none_match = Header::parse_header([b"*".to_vec()].as_slice());
66+
assert_eq!(if_none_match, Some(IfNoneMatch::Any));
67+
68+
if_none_match = Header::parse_header([b"\"foobar\", W/\"weak-etag\"".to_vec()].as_slice());
69+
let mut entities: Vec<EntityTag> = Vec::new();
70+
let foobar_etag = EntityTag {
71+
weak: false,
72+
tag: "foobar".to_string()
73+
};
74+
let weak_etag = EntityTag {
75+
weak: true,
76+
tag: "weak-etag".to_string()
77+
};
78+
entities.push(foobar_etag);
79+
entities.push(weak_etag);
80+
assert_eq!(if_none_match, Some(IfNoneMatch::EntityTags(entities)));
81+
}
82+
}
83+
84+
bench_header!(bench, IfNoneMatch, { vec![b"W/\"nonemptytag\"".to_vec()] });

src/header/common/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub use self::etag::Etag;
2121
pub use self::expires::Expires;
2222
pub use self::host::Host;
2323
pub use self::if_modified_since::IfModifiedSince;
24+
pub use self::if_none_match::IfNoneMatch;
2425
pub use self::if_unmodified_since::IfUnmodifiedSince;
2526
pub use self::last_modified::LastModified;
2627
pub use self::location::Location;
@@ -158,6 +159,7 @@ mod expires;
158159
mod host;
159160
mod last_modified;
160161
mod if_modified_since;
162+
mod if_none_match;
161163
mod if_unmodified_since;
162164
mod location;
163165
mod pragma;

0 commit comments

Comments
 (0)