Skip to content

Commit ffea587

Browse files
committed
refactor(ext): add new CasedHeaderName struct for HeaderCaseMap
1 parent a92c250 commit ffea587

File tree

3 files changed

+84
-23
lines changed

3 files changed

+84
-23
lines changed

src/ext/mod.rs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@ use bytes::Bytes;
4242
feature = "ffi"
4343
))]
4444
use http::header::HeaderName;
45+
#[cfg(all(feature = "http1", feature = "ffi"))]
46+
use http::header::IntoHeaderName;
4547
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
4648
use http::header::InvalidHeaderName;
4749
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
48-
use http::header::{HeaderMap, IntoHeaderName, ValueIter};
50+
use http::header::{HeaderMap, ValueIter};
4951
#[cfg(feature = "ffi")]
5052
use std::collections::HashMap;
5153
#[cfg(feature = "http2")]
@@ -183,24 +185,65 @@ impl HeaderCaseMap {
183185

184186
/// Inserts a header spelling, replacing any existing ones associated with that header name.
185187
#[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)?;
188-
self.0.insert(name, orig);
188+
pub fn insert(&mut self, name: CasedHeaderName) -> Result<(), InvalidHeaderName> {
189+
self.0.insert(name.0, name.1);
189190
Ok(())
190191
}
191192

192193
/// Inserts a header spelling in addition to any existing ones associated with that header name.
193194
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
194-
pub fn append<N>(&mut self, name: N, orig: Bytes) -> Result<(), InvalidHeaderName>
195-
where
196-
N: IntoHeaderName,
197-
{
198-
HeaderName::from_bytes(&orig)?;
199-
self.0.append(name, orig);
195+
pub fn append(&mut self, name: CasedHeaderName) -> Result<(), InvalidHeaderName> {
196+
self.0.append(name.0, name.1);
200197
Ok(())
201198
}
202199
}
203200

201+
/// An error converting a header name spelling to a [`CasedHeaderName`].
202+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
203+
#[derive(Debug)]
204+
pub enum CasedHeaderNameError {
205+
/// Error parsing the header name
206+
Invalid(InvalidHeaderName),
207+
/// The parsed header name doesn't match the spelling's
208+
NoMatch,
209+
}
210+
211+
/// A header casing representation, guaranteed to be a valid [`http::HeaderName`].
212+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
213+
#[derive(Debug)]
214+
pub struct CasedHeaderName(HeaderName, Bytes);
215+
216+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
217+
impl CasedHeaderName {
218+
/// Constructs a header casing representation.
219+
pub fn new(name: HeaderName, orig: Bytes) -> Result<Self, CasedHeaderNameError> {
220+
let orig_parsed =
221+
HeaderName::from_bytes(&orig).map_err(|err| CasedHeaderNameError::Invalid(err))?;
222+
223+
if orig_parsed != name {
224+
Err(CasedHeaderNameError::NoMatch)
225+
} else {
226+
Ok(CasedHeaderName(name.into(), orig))
227+
}
228+
}
229+
}
230+
231+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
232+
impl TryFrom<Bytes> for CasedHeaderName {
233+
type Error = InvalidHeaderName;
234+
235+
fn try_from(orig: Bytes) -> Result<Self, Self::Error> {
236+
HeaderName::from_bytes(&orig).map(|name| CasedHeaderName(name, orig))
237+
}
238+
}
239+
240+
#[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
241+
impl From<CasedHeaderName> for HeaderName {
242+
fn from(value: CasedHeaderName) -> Self {
243+
value.0
244+
}
245+
}
246+
204247
#[cfg(feature = "ffi")]
205248
#[derive(Clone, Debug)]
206249
/// Hashmap<Headername, numheaders with that name>

src/ffi/http_types.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::error::hyper_code;
77
use super::task::{hyper_task_return_type, AsTaskType};
88
use super::{UserDataPointer, HYPER_ITER_CONTINUE};
99
use crate::body::Incoming as IncomingBody;
10-
use crate::ext::{HeaderCaseMap, OriginalHeaderOrder, ReasonPhrase};
10+
use crate::ext::{CasedHeaderName, HeaderCaseMap, OriginalHeaderOrder, ReasonPhrase};
1111
use crate::ffi::size_t;
1212
use crate::header::{HeaderName, HeaderValue};
1313
use crate::{HeaderMap, Method, Request, Response, Uri};
@@ -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()).unwrap();
516+
headers.orig_casing.insert(CasedHeaderName::new(name.clone(), orig_name).unwrap()).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()).unwrap();
536+
headers.orig_casing.append(CasedHeaderName::new(name.clone(), orig_name).unwrap()).unwrap();
537537
headers.orig_order.append(name);
538538
hyper_code::HYPERE_OK
539539
}

src/proto/h1/role.rs

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

317317
if let Some(ref mut header_case_map) = header_case_map {
318+
use crate::ext::CasedHeaderName;
319+
318320
header_case_map
319-
.append(&name, slice.slice(header.name.0..header.name.1))
321+
.append(
322+
CasedHeaderName::new(
323+
name.clone(),
324+
slice.slice(header.name.0..header.name.1),
325+
)
326+
.unwrap(),
327+
)
320328
.unwrap();
321329
}
322330

@@ -1108,8 +1116,16 @@ impl Http1Transaction for Client {
11081116
}
11091117

11101118
if let Some(ref mut header_case_map) = header_case_map {
1119+
use crate::ext::CasedHeaderName;
1120+
11111121
header_case_map
1112-
.append(&name, slice.slice(header.name.0..header.name.1))
1122+
.append(
1123+
CasedHeaderName::new(
1124+
name.clone(),
1125+
slice.slice(header.name.0..header.name.1),
1126+
)
1127+
.unwrap(),
1128+
)
11131129
.unwrap();
11141130
}
11151131

@@ -1645,6 +1661,8 @@ fn extend(dst: &mut Vec<u8>, data: &[u8]) {
16451661
mod tests {
16461662
use bytes::BytesMut;
16471663

1664+
use crate::ext::CasedHeaderName;
1665+
16481666
use super::*;
16491667

16501668
#[cfg(feature = "server")]
@@ -2492,7 +2510,7 @@ mod tests {
24922510

24932511
let mut orig_headers = HeaderCaseMap::default();
24942512
orig_headers
2495-
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2513+
.insert(CasedHeaderName::new(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap())
24962514
.unwrap();
24972515
head.extensions.insert(orig_headers);
24982516

@@ -2531,7 +2549,7 @@ mod tests {
25312549

25322550
let mut orig_headers = HeaderCaseMap::default();
25332551
orig_headers
2534-
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2552+
.insert(CasedHeaderName::new(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap())
25352553
.unwrap();
25362554
head.extensions.insert(orig_headers);
25372555

@@ -2628,7 +2646,7 @@ mod tests {
26282646

26292647
let mut orig_headers = HeaderCaseMap::default();
26302648
orig_headers
2631-
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2649+
.insert(CasedHeaderName::new(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap())
26322650
.unwrap();
26332651
head.extensions.insert(orig_headers);
26342652

@@ -2666,7 +2684,7 @@ mod tests {
26662684

26672685
let mut orig_headers = HeaderCaseMap::default();
26682686
orig_headers
2669-
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2687+
.insert(CasedHeaderName::new(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap())
26702688
.unwrap();
26712689
head.extensions.insert(orig_headers);
26722690

@@ -2705,7 +2723,7 @@ mod tests {
27052723

27062724
let mut orig_headers = HeaderCaseMap::default();
27072725
orig_headers
2708-
.insert(CONTENT_LENGTH, "CONTENT-LENGTH".into())
2726+
.insert(CasedHeaderName::new(CONTENT_LENGTH, "CONTENT-LENGTH".into()).unwrap())
27092727
.unwrap();
27102728
head.extensions.insert(orig_headers);
27112729

@@ -2912,7 +2930,7 @@ mod tests {
29122930
headers.insert(&name, "".parse().expect("parse empty"));
29132931
let mut orig_cases = HeaderCaseMap::default();
29142932
orig_cases
2915-
.insert(name, Bytes::from_static(b"X-EmptY"))
2933+
.insert(CasedHeaderName::new(name, Bytes::from_static(b"X-EmptY")).unwrap())
29162934
.unwrap();
29172935

29182936
let mut dst = Vec::new();
@@ -2933,10 +2951,10 @@ mod tests {
29332951

29342952
let mut orig_cases = HeaderCaseMap::default();
29352953
orig_cases
2936-
.insert(name.clone(), Bytes::from_static(b"X-Empty"))
2954+
.insert(CasedHeaderName::new(name.clone(), Bytes::from_static(b"X-Empty")).unwrap())
29372955
.unwrap();
29382956
orig_cases
2939-
.append(name, Bytes::from_static(b"X-EMPTY"))
2957+
.append(CasedHeaderName::new(name, Bytes::from_static(b"X-EMPTY")).unwrap())
29402958
.unwrap();
29412959

29422960
let mut dst = Vec::new();

0 commit comments

Comments
 (0)