From 684f2fa76d44fa2b1b063ad0443a1b0d16dfad0e Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Fri, 6 Aug 2021 02:00:57 +0200 Subject: [PATCH] fix(http1): apply header title case for consecutive dashes (#2613) Fix the header title-casing to work with consecutive dashes. Previously with two dashes in a row the first dash would uppercase the second dash which would then not count, so `weird--header` would be cased as `Weird--header` instead of `Weird--Header`. --- src/proto/h1/role.rs | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 8828b94a0a..5e8bd43a07 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -1308,36 +1308,18 @@ fn record_header_indices( Ok(()) } -// Write header names as title case. The header name is assumed to be ASCII, -// therefore it is trivial to convert an ASCII character from lowercase to -// uppercase. It is as simple as XORing the lowercase character byte with -// space. +// Write header names as title case. The header name is assumed to be ASCII. fn title_case(dst: &mut Vec, name: &[u8]) { dst.reserve(name.len()); - let mut iter = name.iter(); - - // Uppercase the first character - if let Some(c) = iter.next() { - if *c >= b'a' && *c <= b'z' { - dst.push(*c ^ b' '); - } else { - dst.push(*c); - } - } - - while let Some(c) = iter.next() { - dst.push(*c); - - if *c == b'-' { - if let Some(c) = iter.next() { - if *c >= b'a' && *c <= b'z' { - dst.push(*c ^ b' '); - } else { - dst.push(*c); - } - } + // Ensure first character is uppercased + let mut prev = b'-'; + for &(mut c) in name { + if prev == b'-' { + c.make_ascii_uppercase(); } + dst.push(c); + prev = c; } } @@ -2316,6 +2298,8 @@ mod tests { .insert("content-length", HeaderValue::from_static("10")); head.headers .insert("content-type", HeaderValue::from_static("application/json")); + head.headers + .insert("weird--header", HeaderValue::from_static("")); let mut vec = Vec::new(); Server::encode( @@ -2331,7 +2315,7 @@ mod tests { .unwrap(); let expected_response = - b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: application/json\r\n"; + b"HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: application/json\r\nWeird--Header: \r\n"; assert_eq!(&vec[..expected_response.len()], &expected_response[..]); }