Skip to content

Commit a92c250

Browse files
committed
feat(ext): introduce header casing public API
1 parent f9f8f44 commit a92c250

File tree

3 files changed

+47
-24
lines changed

3 files changed

+47
-24
lines changed

src/ext/mod.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ use bytes::Bytes;
4343
))]
4444
use http::header::HeaderName;
4545
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
46+
use http::header::InvalidHeaderName;
47+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
4648
use http::header::{HeaderMap, IntoHeaderName, ValueIter};
4749
#[cfg(feature = "ffi")]
4850
use std::collections::HashMap;
@@ -157,15 +159,15 @@ impl fmt::Debug for Protocol {
157159
///
158160
/// [`preserve_header_case`]: /client/struct.Client.html#method.preserve_header_case
159161
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
160-
#[derive(Clone, Debug)]
161-
pub(crate) struct HeaderCaseMap(HeaderMap<Bytes>);
162+
#[derive(Clone, Debug, Default)]
163+
pub struct HeaderCaseMap(HeaderMap<Bytes>);
162164

163165
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
164166
impl HeaderCaseMap {
165167
/// Returns a view of all spellings associated with that header name,
166168
/// in the order they were found.
167169
#[cfg(feature = "client")]
168-
pub(crate) fn get_all<'a>(
170+
pub fn get_all<'a>(
169171
&'a self,
170172
name: &HeaderName,
171173
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + 'a {
@@ -179,22 +181,23 @@ impl HeaderCaseMap {
179181
self.0.get_all(name).into_iter()
180182
}
181183

182-
#[cfg(any(feature = "client", feature = "server"))]
183-
pub(crate) fn default() -> Self {
184-
Self(Default::default())
185-
}
186-
187-
#[cfg(any(test, feature = "ffi"))]
188-
pub(crate) fn insert(&mut self, name: HeaderName, orig: Bytes) {
184+
/// Inserts a header spelling, replacing any existing ones associated with that header name.
185+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
186+
pub fn insert(&mut self, name: HeaderName, orig: Bytes) -> Result<(), InvalidHeaderName> {
187+
HeaderName::from_bytes(&orig)?;
189188
self.0.insert(name, orig);
189+
Ok(())
190190
}
191191

192-
#[cfg(any(feature = "client", feature = "server"))]
193-
pub(crate) fn append<N>(&mut self, name: N, orig: Bytes)
192+
/// Inserts a header spelling in addition to any existing ones associated with that header name.
193+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
194+
pub fn append<N>(&mut self, name: N, orig: Bytes) -> Result<(), InvalidHeaderName>
194195
where
195196
N: IntoHeaderName,
196197
{
198+
HeaderName::from_bytes(&orig)?;
197199
self.0.append(name, orig);
200+
Ok(())
198201
}
199202
}
200203

src/ffi/http_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ ffi_fn! {
513513
match unsafe { raw_name_value(name, name_len, value, value_len) } {
514514
Ok((name, value, orig_name)) => {
515515
headers.headers.insert(&name, value);
516-
headers.orig_casing.insert(name.clone(), orig_name.clone());
516+
headers.orig_casing.insert(name.clone(), orig_name.clone()).unwrap();
517517
headers.orig_order.insert(name);
518518
hyper_code::HYPERE_OK
519519
}
@@ -533,7 +533,7 @@ ffi_fn! {
533533
match unsafe { raw_name_value(name, name_len, value, value_len) } {
534534
Ok((name, value, orig_name)) => {
535535
headers.headers.append(&name, value);
536-
headers.orig_casing.append(&name, orig_name.clone());
536+
headers.orig_casing.append(&name, orig_name.clone()).unwrap();
537537
headers.orig_order.append(name);
538538
hyper_code::HYPERE_OK
539539
}

src/proto/h1/role.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,9 @@ impl Http1Transaction for Server {
315315
}
316316

317317
if let Some(ref mut header_case_map) = header_case_map {
318-
header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
318+
header_case_map
319+
.append(&name, slice.slice(header.name.0..header.name.1))
320+
.unwrap();
319321
}
320322

321323
#[cfg(feature = "ffi")]
@@ -1106,7 +1108,9 @@ impl Http1Transaction for Client {
11061108
}
11071109

11081110
if let Some(ref mut header_case_map) = header_case_map {
1109-
header_case_map.append(&name, slice.slice(header.name.0..header.name.1));
1111+
header_case_map
1112+
.append(&name, slice.slice(header.name.0..header.name.1))
1113+
.unwrap();
11101114
}
11111115

11121116
#[cfg(feature = "ffi")]
@@ -2487,7 +2491,9 @@ mod tests {
24872491
.insert("content-type", HeaderValue::from_static("application/json"));
24882492

24892493
let mut orig_headers = HeaderCaseMap::default();
2490-
orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2494+
orig_headers
2495+
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2496+
.unwrap();
24912497
head.extensions.insert(orig_headers);
24922498

24932499
let mut vec = Vec::new();
@@ -2524,7 +2530,9 @@ mod tests {
25242530
.insert("content-type", HeaderValue::from_static("application/json"));
25252531

25262532
let mut orig_headers = HeaderCaseMap::default();
2527-
orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2533+
orig_headers
2534+
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2535+
.unwrap();
25282536
head.extensions.insert(orig_headers);
25292537

25302538
let mut vec = Vec::new();
@@ -2619,7 +2627,9 @@ mod tests {
26192627
.insert("content-type", HeaderValue::from_static("application/json"));
26202628

26212629
let mut orig_headers = HeaderCaseMap::default();
2622-
orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2630+
orig_headers
2631+
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2632+
.unwrap();
26232633
head.extensions.insert(orig_headers);
26242634

26252635
let mut vec = Vec::new();
@@ -2655,7 +2665,9 @@ mod tests {
26552665
.insert("content-type", HeaderValue::from_static("application/json"));
26562666

26572667
let mut orig_headers = HeaderCaseMap::default();
2658-
orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2668+
orig_headers
2669+
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2670+
.unwrap();
26592671
head.extensions.insert(orig_headers);
26602672

26612673
let mut vec = Vec::new();
@@ -2692,7 +2704,9 @@ mod tests {
26922704
.insert("content-type", HeaderValue::from_static("application/json"));
26932705

26942706
let mut orig_headers = HeaderCaseMap::default();
2695-
orig_headers.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into());
2707+
orig_headers
2708+
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2709+
.unwrap();
26962710
head.extensions.insert(orig_headers);
26972711

26982712
let mut vec = Vec::new();
@@ -2897,7 +2911,9 @@ mod tests {
28972911
let name = http::header::HeaderName::from_static("x-empty");
28982912
headers.insert(&name, "".parse().expect("parse empty"));
28992913
let mut orig_cases = HeaderCaseMap::default();
2900-
orig_cases.insert(name, Bytes::from_static(b"X-EmptY"));
2914+
orig_cases
2915+
.insert(name, Bytes::from_static(b"X-EmptY"))
2916+
.unwrap();
29012917

29022918
let mut dst = Vec::new();
29032919
super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);
@@ -2916,8 +2932,12 @@ mod tests {
29162932
headers.append(&name, "b".parse().unwrap());
29172933

29182934
let mut orig_cases = HeaderCaseMap::default();
2919-
orig_cases.insert(name.clone(), Bytes::from_static(b"X-Empty"));
2920-
orig_cases.append(name, Bytes::from_static(b"X-EMPTY"));
2935+
orig_cases
2936+
.insert(name.clone(), Bytes::from_static(b"X-Empty"))
2937+
.unwrap();
2938+
orig_cases
2939+
.append(name, Bytes::from_static(b"X-EMPTY"))
2940+
.unwrap();
29212941

29222942
let mut dst = Vec::new();
29232943
super::write_headers_original_case(&headers, &orig_cases, &mut dst, false);

0 commit comments

Comments
 (0)