Skip to content

Commit 9874175

Browse files
committed
fix: append for special std header
1 parent 783f6fd commit 9874175

File tree

6 files changed

+253
-164
lines changed

6 files changed

+253
-164
lines changed

src/ext/fasthttp/consts.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,51 @@ impl StandardHeaders {
5050
StandardHeaders(trie)
5151
}
5252

53-
pub fn is_std_header(&self, header_name: &HeaderName) -> bool {
53+
pub fn is_match(&self, header_name: &HeaderName) -> bool {
54+
let lowercase_header = header_name.as_str().to_ascii_lowercase();
55+
self.0.exact_match(lowercase_header)
56+
}
57+
}
58+
59+
pub(crate) struct NonAppendStandardHeaders(Trie<u8>);
60+
61+
impl NonAppendStandardHeaders {
62+
fn new() -> NonAppendStandardHeaders {
63+
let mut builder = TrieBuilder::new();
64+
65+
// 不可有多个值的特殊 std header
66+
// 调用 append 等同于 insert
67+
builder.push(CONTENT_TYPE);
68+
builder.push(SERVER);
69+
builder.push(SET_COOKIE);
70+
builder.push(CONTENT_LENGTH);
71+
builder.push(CONNECTION);
72+
builder.push(TRANSFER_ENCODING);
73+
builder.push(DATE);
74+
75+
let trie = builder.build();
76+
77+
NonAppendStandardHeaders(trie)
78+
}
79+
80+
pub fn is_match(&self, header_name: &HeaderName) -> bool {
5481
let lowercase_header = header_name.as_str().to_ascii_lowercase();
5582
self.0.exact_match(lowercase_header)
5683
}
5784
}
5885

5986
lazy_static! {
60-
pub(crate) static ref STANDARD_HEADERS: StandardHeaders = StandardHeaders::new();
87+
pub(super) static ref STANDARD_HEADERS: StandardHeaders = StandardHeaders::new();
88+
pub(super) static ref NON_APPEND_STANDARD_HEADERS: NonAppendStandardHeaders =
89+
NonAppendStandardHeaders::new();
90+
}
91+
92+
pub fn is_standard_header(header_name: &HeaderName) -> bool {
93+
STANDARD_HEADERS.is_match(header_name)
94+
}
95+
96+
pub fn is_non_append_standard_headers(header_name: &HeaderName) -> bool {
97+
NON_APPEND_STANDARD_HEADERS.is_match(header_name)
6198
}
6299

63100
#[test]

src/ext/fasthttp/header_name.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ext::fasthttp::consts::STANDARD_HEADERS;
1+
use crate::ext::fasthttp::consts::is_standard_header;
22
use crate::HeaderName;
33

44
const TO_LOWER: u8 = b'a' - b'A';
@@ -30,6 +30,7 @@ lazy_static::lazy_static! {
3030
}
3131

3232
/// 只normalize标准header,其他自定义header保持原样透传
33+
#[allow(warnings)]
3334
pub(crate) fn normalize_header_key_for_std_header(
3435
header_name: &HeaderName,
3536
disable_normalizing: bool,
@@ -38,7 +39,7 @@ pub(crate) fn normalize_header_key_for_std_header(
3839
return header_name.clone();
3940
}
4041

41-
if !STANDARD_HEADERS.is_std_header(&(header_name.clone())) {
42+
if !is_standard_header(&(header_name.clone())) {
4243
return header_name.clone();
4344
}
4445

src/ext/fasthttp/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
mod consts;
1+
pub mod consts;
22
pub mod header_name;

src/header/map.rs

Lines changed: 106 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ pub use self::into_header_name::IntoHeaderName;
33
use super::name::{HdrName, HeaderName, InvalidHeaderName};
44
use super::HeaderValue;
55
#[cfg(feature = "fasthttp")]
6-
use super::{
7-
CONNECTION, CONTENT_LENGTH, CONTENT_TYPE, COOKIE, HOST, TRANSFER_ENCODING, USER_AGENT,
8-
};
6+
use crate::ext::fasthttp::consts::is_non_append_standard_headers;
97
#[cfg(feature = "fasthttp")]
108
use crate::ext::fasthttp::header_name::{
119
normalize_header_key, normalize_header_key_for_std_header,
@@ -1380,6 +1378,63 @@ impl<T> HeaderMap<T> {
13801378
))
13811379
}
13821380

1381+
#[cfg(feature = "fasthttp")]
1382+
fn try_insert2_do(&mut self, key: HeaderName, value: T) -> Result<Option<T>, MaxSizeReached> {
1383+
self.try_reserve_one()?;
1384+
1385+
#[cfg(feature = "fasthttp")]
1386+
{
1387+
Ok(insert_phase_one!(
1388+
self,
1389+
key,
1390+
probe,
1391+
pos,
1392+
hash,
1393+
danger,
1394+
// Vacant
1395+
{
1396+
let _ = danger; // Make lint happy
1397+
self.try_insert_entry(hash, key.into(), value)?;
1398+
let index = self.entries.len() - 1;
1399+
self.indices[probe] = Pos::new(index, hash);
1400+
None
1401+
},
1402+
// Occupied
1403+
Some(self.insert_occupied(pos, value)),
1404+
// Robinhood
1405+
{
1406+
self.try_insert_phase_two(key.into(), value, hash, probe, danger)?;
1407+
None
1408+
}
1409+
))
1410+
}
1411+
1412+
#[cfg(not(feature = "fasthttp"))]
1413+
Ok(insert_phase_one!(
1414+
self,
1415+
key,
1416+
probe,
1417+
pos,
1418+
hash,
1419+
danger,
1420+
// Vacant
1421+
{
1422+
let _ = danger; // Make lint happy
1423+
let index = self.entries.len();
1424+
self.try_insert_entry(hash, key.into(), value)?;
1425+
self.indices[probe] = Pos::new(index, hash);
1426+
None
1427+
},
1428+
// Occupied
1429+
Some(self.insert_occupied(pos, value)),
1430+
// Robinhood
1431+
{
1432+
self.try_insert_phase_two(key.into(), value, hash, probe, danger)?;
1433+
None
1434+
}
1435+
))
1436+
}
1437+
13831438
/// Set an occupied bucket to the given value
13841439
#[inline]
13851440
fn insert_occupied(&mut self, index: usize, value: T) -> T {
@@ -1494,45 +1549,61 @@ impl<T> HeaderMap<T> {
14941549
fn try_append2<K>(&mut self, key: K, value: T) -> Result<bool, MaxSizeReached>
14951550
where
14961551
K: Hash + Into<HeaderName>,
1497-
HeaderName: PartialEq<K>,
14981552
{
14991553
self.try_reserve_one()?;
15001554

1555+
let header_name = key.into();
1556+
15011557
#[cfg(feature = "fasthttp")]
15021558
{
1503-
Ok(insert_phase_one!(
1504-
self,
1505-
key,
1506-
probe,
1507-
pos,
1508-
hash,
1509-
danger,
1510-
// Vacant
1511-
{
1512-
let _ = danger;
1513-
let index = self.entries.len();
1514-
self.try_insert_entry_for_append(hash, key.into(), value)?;
1515-
self.indices[probe] = Pos::new(index, hash);
1516-
false
1517-
},
1518-
// Occupied
1519-
{
1520-
append_value(pos, &mut self.entries[pos], &mut self.extra_values, value);
1521-
true
1522-
},
1523-
// Robinhood
1524-
{
1525-
self.try_insert_phase_two_for_append(key.into(), value, hash, probe, danger)?;
1526-
1527-
false
1559+
let normalized_header_name = normalize_header_key_for_std_header(&header_name, true);
1560+
if is_non_append_standard_headers(&normalized_header_name) {
1561+
match self.try_insert2_do(header_name, value) {
1562+
Ok(None) => return Ok(false),
1563+
Ok(Some(_)) => return Ok(false),
1564+
Err(e) => return Err(e),
15281565
}
1529-
))
1566+
} else {
1567+
Ok(insert_phase_one!(
1568+
self,
1569+
header_name,
1570+
probe,
1571+
pos,
1572+
hash,
1573+
danger,
1574+
// Vacant
1575+
{
1576+
let _ = danger;
1577+
let index = self.entries.len();
1578+
self.try_insert_entry_for_append(hash, header_name, value)?;
1579+
self.indices[probe] = Pos::new(index, hash);
1580+
false
1581+
},
1582+
// Occupied
1583+
{
1584+
append_value(pos, &mut self.entries[pos], &mut self.extra_values, value);
1585+
true
1586+
},
1587+
// Robinhood
1588+
{
1589+
self.try_insert_phase_two_for_append(
1590+
header_name,
1591+
value,
1592+
hash,
1593+
probe,
1594+
danger,
1595+
)?;
1596+
1597+
false
1598+
}
1599+
))
1600+
}
15301601
}
15311602

15321603
#[cfg(not(feature = "fasthttp"))]
15331604
Ok(insert_phase_one!(
15341605
self,
1535-
key,
1606+
header_name,
15361607
probe,
15371608
pos,
15381609
hash,
@@ -1541,7 +1612,7 @@ impl<T> HeaderMap<T> {
15411612
{
15421613
let _ = danger;
15431614
let index = self.entries.len();
1544-
self.try_insert_entry(hash, key.into(), value)?;
1615+
self.try_insert_entry(hash, header_name, value)?;
15451616
self.indices[probe] = Pos::new(index, hash);
15461617
false
15471618
},
@@ -1552,7 +1623,7 @@ impl<T> HeaderMap<T> {
15521623
},
15531624
// Robinhood
15541625
{
1555-
self.try_insert_phase_two(key.into(), value, hash, probe, danger)?;
1626+
self.try_insert_phase_two(header_name, value, hash, probe, danger)?;
15561627

15571628
false
15581629
}
@@ -1699,40 +1770,7 @@ impl<T> HeaderMap<T> {
16991770

17001771
let normalized_key = normalize_header_key(&header_name).into();
17011772

1702-
let mut i;
1703-
let original_key = match self.mapped_keys.get(&normalized_key) {
1704-
Some(original_keys) => match original_keys.iter().next_back() {
1705-
Some(return_original_key) => {
1706-
i = original_keys.len() - 1;
1707-
let mut return_original_key = return_original_key;
1708-
let _a = return_original_key.clone().as_raw_str();
1709-
let _b = header_name.clone().as_raw_str();
1710-
if return_original_key == header_name {
1711-
return_original_key.clone()
1712-
} else {
1713-
let mut is_found = false;
1714-
for original_key in original_keys.iter() {
1715-
i -= 1;
1716-
return_original_key = original_key;
1717-
if original_key == header_name {
1718-
is_found = true;
1719-
break;
1720-
}
1721-
}
1722-
if !is_found {
1723-
return None;
1724-
}
1725-
return_original_key.clone()
1726-
}
1727-
}
1728-
None => return None,
1729-
},
1730-
None => {
1731-
return None;
1732-
}
1733-
};
1734-
1735-
match original_key.find(self) {
1773+
match header_name.find(self) {
17361774
Some((probe, idx)) => {
17371775
if let Some(links) = self.entries[idx].links {
17381776
self.remove_all_extra_values(links.next);
@@ -1741,7 +1779,7 @@ impl<T> HeaderMap<T> {
17411779
let entry = self.remove_found(probe, idx);
17421780

17431781
if let Some(original_keys) = self.mapped_keys.get_mut(&normalized_key) {
1744-
original_keys.remove(i);
1782+
original_keys.retain(|x| x != &header_name);
17451783
}
17461784
Some(entry.value)
17471785
}
@@ -1920,16 +1958,6 @@ impl<T> HeaderMap<T> {
19201958
return Err(MaxSizeReached::new());
19211959
}
19221960

1923-
let normalized_key = normalize_header_key_for_std_header(&(key.clone()), false);
1924-
match normalized_key {
1925-
HOST | CONTENT_TYPE | USER_AGENT | COOKIE | CONTENT_LENGTH | CONNECTION
1926-
| TRANSFER_ENCODING => {
1927-
// 清理掉所有的 insensitive key
1928-
self.remove_key_insensitively(&key);
1929-
}
1930-
_ => {}
1931-
}
1932-
19331961
self.append_to_mapped_keys(key.clone());
19341962

19351963
self.entries.push(Bucket {

src/header/name.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<T: PartialEq> PartialEq for Repr<T> {
8585
(Self::Custom(la, lb), Self::Custom(ra, rb)) => match (lb, rb) {
8686
(Some(lb), Some(rb)) => lb == rb,
8787
(None, None) => la == ra,
88-
_ => la == ra,
88+
_ => false,
8989
},
9090
_ => false,
9191
}

0 commit comments

Comments
 (0)