Skip to content

Commit e712464

Browse files
committed
accept-encoding smoke test
1 parent 0935725 commit e712464

File tree

2 files changed

+72
-14
lines changed

2 files changed

+72
-14
lines changed

src/content/accept_encoding.rs

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1+
//! Client header advertising available compression algorithms.
2+
13
use crate::content::EncodingProposal;
24
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, ACCEPT_ENCODING};
35

4-
use std::fmt::{self, Debug};
6+
use std::fmt::{self, Debug, Write};
57
use std::option;
68
use std::slice;
79

8-
/// An Accept-Encoding header.
10+
/// Client header advertising available compression algorithms.
911
pub struct AcceptEncoding {
12+
wildcard: bool,
1013
entries: Vec<EncodingProposal>,
1114
}
1215

1316
impl AcceptEncoding {
1417
/// Create a new instance of `AcceptEncoding`.
1518
pub fn new() -> Self {
16-
Self { entries: vec![] }
19+
Self {
20+
entries: vec![],
21+
wildcard: false,
22+
}
1723
}
1824

1925
/// Create an instance of `AcceptEncoding` from a `Headers` instance.
@@ -24,8 +30,20 @@ impl AcceptEncoding {
2430
None => return Ok(None),
2531
};
2632

33+
let mut wildcard = false;
34+
2735
for value in headers {
2836
for part in value.as_str().trim().split(',') {
37+
let part = part.trim();
38+
39+
// Handle empty strings, and wildcard directives.
40+
if part.is_empty() {
41+
continue;
42+
} else if part == "*" {
43+
wildcard = true;
44+
continue;
45+
}
46+
2947
// Try and parse a directive from a str. If the directive is
3048
// unkown we skip it.
3149
if let Some(entry) = EncodingProposal::from_str(part)? {
@@ -34,12 +52,22 @@ impl AcceptEncoding {
3452
}
3553
}
3654

37-
Ok(Some(Self { entries }))
55+
Ok(Some(Self { entries, wildcard }))
3856
}
3957

4058
/// Push a directive into the list of entries.
41-
pub fn push(&mut self, prop: EncodingProposal) {
42-
self.entries.push(prop);
59+
pub fn push(&mut self, prop: impl Into<EncodingProposal>) {
60+
self.entries.push(prop.into());
61+
}
62+
63+
/// Returns `true` if a wildcard directive was passed.
64+
pub fn wildcard(&self) -> bool {
65+
self.wildcard
66+
}
67+
68+
/// Set the wildcard directive.
69+
pub fn set_wildcard(&mut self, wildcard: bool) {
70+
self.wildcard = wildcard
4371
}
4472

4573
/// Insert a `HeaderName` + `HeaderValue` pair into a `Headers` instance.
@@ -54,7 +82,17 @@ impl AcceptEncoding {
5482

5583
/// Get the `HeaderValue`.
5684
pub fn value(&self) -> HeaderValue {
57-
todo!();
85+
let mut output = String::new();
86+
for (n, directive) in self.entries.iter().enumerate() {
87+
let directive: HeaderValue = directive.clone().into();
88+
match n {
89+
0 => write!(output, "{}", directive).unwrap(),
90+
_ => write!(output, ", {}", directive).unwrap(),
91+
};
92+
}
93+
94+
// SAFETY: the internal string is validated to be ASCII.
95+
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
5896
}
5997

6098
/// An iterator visiting all entries.
@@ -178,3 +216,24 @@ impl Debug for AcceptEncoding {
178216
list.finish()
179217
}
180218
}
219+
220+
#[cfg(test)]
221+
mod test {
222+
use super::*;
223+
use crate::content::Encoding;
224+
use crate::Response;
225+
226+
#[test]
227+
fn smoke() -> crate::Result<()> {
228+
let mut accept = AcceptEncoding::new();
229+
accept.push(Encoding::Gzip);
230+
231+
let mut headers = Response::new(200);
232+
accept.apply(&mut headers);
233+
234+
let accept = AcceptEncoding::from_headers(headers)?.unwrap();
235+
let mut accept = accept.iter();
236+
assert_eq!(accept.next().unwrap(), Encoding::Gzip);
237+
Ok(())
238+
}
239+
}

src/content/encoding_proposal.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,6 @@ impl EncodingProposal {
4444
}
4545

4646
pub(crate) fn from_str(s: &str) -> crate::Result<Option<Self>> {
47-
let s = s.trim();
48-
49-
// We're dealing with an empty string.
50-
if s.is_empty() {
51-
return Ok(None);
52-
}
53-
5447
let mut parts = s.split(';');
5548
let encoding = match Encoding::from_str(parts.next().unwrap()) {
5649
Some(encoding) => encoding,
@@ -77,6 +70,12 @@ impl PartialEq<Encoding> for EncodingProposal {
7770
}
7871
}
7972

73+
impl PartialEq<Encoding> for &EncodingProposal {
74+
fn eq(&self, other: &Encoding) -> bool {
75+
self.encoding == *other
76+
}
77+
}
78+
8079
// NOTE: Firefox populates Accept-Encoding as `gzip, deflate, br`. This means
8180
// when parsing encodings we should choose the last value in the list under
8281
// equal weights. This impl doesn't know which value was passed later, so that

0 commit comments

Comments
 (0)