-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Temporary support writing/decoding headers in old format
- Loading branch information
Showing
5 changed files
with
151 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//! Based on `http-serde` crate | ||
|
||
/// For `HeaderMap` | ||
/// | ||
/// `#[serde(with = "casper_server::http::serde::header_map")]` | ||
pub mod header_map { | ||
use std::borrow::Cow; | ||
use std::fmt; | ||
|
||
use ntex::http::header::{HeaderMap, HeaderName, HeaderValue}; | ||
use serde::de::{self, Deserializer, MapAccess, Unexpected, Visitor}; | ||
use serde::ser::SerializeSeq; | ||
use serde::{Serialize, Serializer}; | ||
|
||
struct ToSeq<'a>(&'a HeaderMap, &'a HeaderName); | ||
|
||
impl<'a> Serialize for ToSeq<'a> { | ||
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> { | ||
let name = self.1; | ||
let count = self.0.get_all(name).count(); | ||
if ser.is_human_readable() { | ||
if count == 1 { | ||
let v = self.0.get(name).expect("header is present"); | ||
if let Ok(s) = v.to_str() { | ||
return ser.serialize_str(s); | ||
} | ||
} | ||
ser.collect_seq(self.0.get_all(name).filter_map(|v| v.to_str().ok())) | ||
} else { | ||
let mut seq = ser.serialize_seq(Some(count))?; | ||
for v in self.0.get_all(name) { | ||
seq.serialize_element(v.as_bytes())?; | ||
} | ||
seq.end() | ||
} | ||
} | ||
} | ||
|
||
/// Implementation detail. Use derive annotations instead. | ||
pub fn serialize<S: Serializer>(headers: &HeaderMap, ser: S) -> Result<S::Ok, S::Error> { | ||
ser.collect_map(headers.keys().map(|k| (k.as_str(), ToSeq(headers, k)))) | ||
} | ||
|
||
#[derive(serde::Deserialize)] | ||
#[serde(untagged)] | ||
enum OneOrMore<'a> { | ||
One(Cow<'a, str>), | ||
Strings(Vec<Cow<'a, str>>), | ||
Bytes(Vec<Cow<'a, [u8]>>), | ||
} | ||
|
||
struct HeaderMapVisitor { | ||
is_human_readable: bool, | ||
} | ||
|
||
impl<'de> Visitor<'de> for HeaderMapVisitor { | ||
type Value = HeaderMap; | ||
|
||
// Format a message stating what data this Visitor expects to receive. | ||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | ||
formatter.write_str("lots of things can go wrong with HeaderMap") | ||
} | ||
|
||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> | ||
where | ||
M: MapAccess<'de>, | ||
{ | ||
let mut map = HeaderMap::with_capacity(access.size_hint().unwrap_or(0)); | ||
|
||
if !self.is_human_readable { | ||
while let Some((key, arr)) = access.next_entry::<Cow<str>, Vec<Cow<[u8]>>>()? { | ||
let key = HeaderName::from_bytes(key.as_bytes()) | ||
.map_err(|_| de::Error::invalid_value(Unexpected::Str(&key), &self))?; | ||
for val in arr { | ||
let val = HeaderValue::from_bytes(&val).map_err(|_| { | ||
de::Error::invalid_value(Unexpected::Bytes(&val), &self) | ||
})?; | ||
map.append(key.clone(), val); | ||
} | ||
} | ||
} else { | ||
while let Some((key, val)) = access.next_entry::<Cow<str>, OneOrMore>()? { | ||
let key = HeaderName::from_bytes(key.as_bytes()) | ||
.map_err(|_| de::Error::invalid_value(Unexpected::Str(&key), &self))?; | ||
match val { | ||
OneOrMore::One(val) => { | ||
let val = val.parse().map_err(|_| { | ||
de::Error::invalid_value(Unexpected::Str(&val), &self) | ||
})?; | ||
map.insert(key, val); | ||
} | ||
OneOrMore::Strings(arr) => { | ||
for val in arr { | ||
let val = val.parse().map_err(|_| { | ||
de::Error::invalid_value(Unexpected::Str(&val), &self) | ||
})?; | ||
map.append(key.clone(), val); | ||
} | ||
} | ||
OneOrMore::Bytes(arr) => { | ||
for val in arr { | ||
let val = HeaderValue::from_bytes(&val).map_err(|_| { | ||
de::Error::invalid_value(Unexpected::Bytes(&val), &self) | ||
})?; | ||
map.append(key.clone(), val); | ||
} | ||
} | ||
}; | ||
} | ||
} | ||
Ok(map) | ||
} | ||
} | ||
|
||
/// Implementation detail. | ||
pub fn deserialize<'de, D>(de: D) -> Result<HeaderMap, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let is_human_readable = de.is_human_readable(); | ||
de.deserialize_map(HeaderMapVisitor { is_human_readable }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,29 @@ | ||
use ntex::http::header::HeaderMap; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
pub fn encode_headers(headers: &HeaderMap) -> Result<Vec<u8>, flexbuffers::SerializationError> { | ||
use crate::http::serde as http_serde; | ||
|
||
pub fn encode_headers( | ||
headers: &HeaderMap, | ||
v2: bool, | ||
) -> Result<Vec<u8>, flexbuffers::SerializationError> { | ||
let mut serializer = flexbuffers::FlexbufferSerializer::new(); | ||
headers.serialize(&mut serializer)?; | ||
if v2 { | ||
headers.serialize(&mut serializer)?; | ||
} else { | ||
http_serde::header_map::serialize(headers, &mut serializer)?; | ||
} | ||
Ok(serializer.take_buffer()) | ||
} | ||
|
||
pub fn decode_headers(data: &[u8]) -> Result<HeaderMap, flexbuffers::DeserializationError> { | ||
pub fn decode_headers( | ||
data: &[u8], | ||
v2: bool, | ||
) -> Result<HeaderMap, flexbuffers::DeserializationError> { | ||
let deserializer = flexbuffers::Reader::get_root(data)?; | ||
HeaderMap::deserialize(deserializer) | ||
if v2 { | ||
HeaderMap::deserialize(deserializer) | ||
} else { | ||
http_serde::header_map::deserialize(deserializer) | ||
} | ||
} |