ntex-http 1.3.0

Http types for ntex framework
Documentation
use std::{collections::hash_map::Entry, fmt};

use serde::de::{self, Deserialize, Deserializer, MapAccess, Unexpected, Visitor};
use serde::ser::{self, Serialize, SerializeMap, Serializer};

use super::{HeaderMap, HeaderName, HeaderValue, Value};

impl Serialize for HeaderMap {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (name, value) in &self.inner {
            map.serialize_entry(name.as_str(), value)?;
        }
        map.end()
    }
}

impl<'de> Deserialize<'de> for HeaderMap {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(HeaderMapVisitor)
    }
}

struct HeaderMapVisitor;

impl<'de> Visitor<'de> for HeaderMapVisitor {
    type Value = HeaderMap;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("a header map")
    }

    fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut headers = HeaderMap::with_capacity(map.size_hint().unwrap_or(0));
        while let Some((NameKey(name), value)) = map.next_entry::<NameKey, Value>()? {
            // names are case-insensitive, merge values of duplicate keys
            match headers.inner.entry(name) {
                Entry::Occupied(mut entry) => entry.get_mut().extend(value),
                Entry::Vacant(entry) => {
                    entry.insert(value);
                }
            }
        }
        Ok(headers)
    }
}

/// Header name map key, supports both borrowed and owned strings.
#[derive(Debug)]
struct NameKey(HeaderName);

impl<'de> Deserialize<'de> for NameKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(NameKeyVisitor)
    }
}

struct NameKeyVisitor;

impl Visitor<'_> for NameKeyVisitor {
    type Value = NameKey;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("a header name")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderName::from_bytes(v.as_bytes())
            .map(NameKey)
            .map_err(|_| de::Error::invalid_value(Unexpected::Str(v), &"a valid header name"))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderName::from_bytes(v)
            .map(NameKey)
            .map_err(|_| de::Error::invalid_value(Unexpected::Bytes(v), &"a valid header name"))
    }
}

impl Serialize for Value {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Value::One(val) if serializer.is_human_readable() => val.serialize(serializer),
            // For non-human-readable formats, always serialize as a sequence
            Value::One(val) => [val].as_slice().serialize(serializer),
            Value::Multi(vec) => vec.serialize(serializer),
        }
    }
}

impl<'de> Deserialize<'de> for Value {
    fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            return deserializer.deserialize_any(ValueVisitor);
        }
        deserializer.deserialize_seq(ValueVisitor)
    }
}

struct ValueVisitor;

impl<'de> Visitor<'de> for ValueVisitor {
    type Value = Value;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("a single header value or sequence of values")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(Value::One(HeaderValueVisitor.visit_str(v)?))
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(Value::One(HeaderValueVisitor.visit_string(v)?))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(Value::One(HeaderValueVisitor.visit_bytes(v)?))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(Value::One(HeaderValueVisitor.visit_byte_buf(v)?))
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: de::SeqAccess<'de>,
    {
        let mut value: Option<Value> = None;
        while let Some(next_val) = seq.next_element()? {
            match value.as_mut() {
                Some(value) => value.append(next_val),
                None => value = Some(Value::One(next_val)),
            }
        }
        value.ok_or_else(|| de::Error::invalid_length(0, &"non-empty value"))
    }
}

impl Serialize for HeaderValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if serializer.is_human_readable() {
            return serializer.serialize_str(
                self.to_str()
                    .map_err(|err| ser::Error::custom(err.to_string()))?,
            );
        }
        serializer.serialize_bytes(self.as_bytes())
    }
}

impl<'de> Deserialize<'de> for HeaderValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            return deserializer.deserialize_string(HeaderValueVisitor);
        }
        deserializer.deserialize_byte_buf(HeaderValueVisitor)
    }
}

struct HeaderValueVisitor;

impl Visitor<'_> for HeaderValueVisitor {
    type Value = HeaderValue;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("a header value")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderValue::from_str(v)
            .map_err(|_| de::Error::invalid_value(Unexpected::Str(v), &"a valid header value"))
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderValue::from_shared(v).map_err(|err| de::Error::custom(err.to_string()))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderValue::from_bytes(v)
            .map_err(|_| de::Error::invalid_value(Unexpected::Bytes(v), &"a valid header value"))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        HeaderValue::from_shared(v).map_err(|err| de::Error::custom(err.to_string()))
    }
}

#[cfg(test)]
mod tests {
    use crate::header::*;

    #[test]
    fn test_serde_json() {
        let mut map = HeaderMap::new();
        map.insert(USER_AGENT, HeaderValue::from_static("hello"));
        map.append(USER_AGENT, HeaderValue::from_static("world"));
        assert_eq!(
            serde_json::to_string(&map).unwrap(),
            r#"{"user-agent":["hello","world"]}"#
        );

        // Make roundtrip
        map.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
        map.insert(CONTENT_LENGTH, 0.into());
        let map_json = serde_json::to_string(&map).unwrap();
        let map2 = serde_json::from_str::<HeaderMap>(&map_json).unwrap();
        assert_eq!(map, map2);

        // Try mixed case header names
        let map_uc = serde_json::from_str::<HeaderMap>(r#"{"X-Foo":"BAR"}"#).unwrap();
        assert_eq!(map_uc.get("x-foo").unwrap(), "BAR");
        assert_eq!(
            serde_json::to_string(&map_uc).unwrap(),
            r#"{"x-foo":"BAR"}"#
        );

        // Try decode empty header value
        let map_empty = serde_json::from_str::<HeaderMap>(r#"{"user-agent":[]}"#);
        assert!(map_empty.is_err());
        assert!(
            map_empty
                .unwrap_err()
                .to_string()
                .contains("invalid length 0, expected non-empty value")
        );
    }

    #[test]
    fn test_serde_bincode() {
        let mut map = HeaderMap::new();
        map.insert(USER_AGENT, HeaderValue::from_static("hello"));
        map.append(USER_AGENT, HeaderValue::from_static("world"));
        map.insert(HeaderName::from_static("x-foo"), "bar".parse().unwrap());
        let map_bin = bincode::serialize(&map).unwrap();
        let map2 = bincode::deserialize::<HeaderMap>(&map_bin).unwrap();
        assert_eq!(map, map2);
    }

    #[test]
    fn test_serde_owned_keys() {
        // non-borrowed keys
        let v = serde_json::json!({"x-foo": "bar"});
        let map = serde_json::from_value::<HeaderMap>(v).unwrap();
        assert_eq!(map.get("x-foo").unwrap(), "bar");

        let map = serde_json::from_reader::<_, HeaderMap>(&br#"{"x-foo":"bar"}"#[..]).unwrap();
        assert_eq!(map.get("x-foo").unwrap(), "bar");

        let map = serde_json::from_str::<HeaderMap>(r#"{"x-f\u006fo":"bar"}"#).unwrap();
        assert_eq!(map.get("x-foo").unwrap(), "bar");

        // duplicate keys are merged
        let map = serde_json::from_str::<HeaderMap>(r#"{"x-foo":"a","X-Foo":["b","c"]}"#).unwrap();
        assert_eq!(map.len(), 1);
        assert_eq!(map.get_all("x-foo").collect::<Vec<_>>(), ["a", "b", "c"]);

        let err = serde_json::from_str::<HeaderMap>(r#"{"x foo":"a"}"#).unwrap_err();
        assert!(
            err.to_string().contains("expected a valid header name"),
            "{err}"
        );
        let err = serde_json::from_value::<HeaderMap>(serde_json::json!([1])).unwrap_err();
        assert!(err.to_string().contains("expected a header map"), "{err}");
    }

    #[test]
    fn test_serde_visitors() {
        use serde::de::{Visitor, value::Error as DeError};

        use super::{HeaderValueVisitor, NameKey, NameKeyVisitor, Value, ValueVisitor};

        let NameKey(name) = NameKeyVisitor.visit_bytes::<DeError>(b"x-foo").unwrap();
        assert_eq!(name, "x-foo");
        assert!(NameKeyVisitor.visit_bytes::<DeError>(b"x foo").is_err());

        let v = ValueVisitor.visit_bytes::<DeError>(b"a").unwrap();
        assert_eq!(v, Value::One(HeaderValue::from_static("a")));
        let v = ValueVisitor
            .visit_byte_buf::<DeError>(b"b".to_vec())
            .unwrap();
        assert_eq!(v, Value::One(HeaderValue::from_static("b")));
        let v = ValueVisitor
            .visit_string::<DeError>("c".to_string())
            .unwrap();
        assert_eq!(v, Value::One(HeaderValue::from_static("c")));
        assert!(ValueVisitor.visit_bytes::<DeError>(b"\n").is_err());
        assert!(
            HeaderValueVisitor
                .visit_byte_buf::<DeError>(b"\n".to_vec())
                .is_err()
        );
        assert!(
            HeaderValueVisitor
                .visit_string::<DeError>("\n".to_string())
                .is_err()
        );

        // `expecting` messages
        let map = serde_json::from_str::<HeaderMap>(r#"{"1":"a"}"#).unwrap();
        assert_eq!(map.get("1").unwrap(), "a");
        let err = serde_json::from_str::<HeaderMap>(r#"{"x":1}"#).unwrap_err();
        assert!(
            err.to_string()
                .contains("a single header value or sequence"),
            "{err}"
        );
        let err = serde_json::from_str::<HeaderMap>(r#"{"x":[1]}"#).unwrap_err();
        assert!(err.to_string().contains("a header value"), "{err}");
        let err = serde_json::from_str::<HeaderMap>(r#"{"x":"\u0001"}"#).unwrap_err();
        assert!(err.to_string().contains("a valid header value"), "{err}");
        let err =
            serde_json::from_value::<HeaderMap>(serde_json::json!({"x": ["\u{1}"]})).unwrap_err();
        assert_ne!(err.to_string(), "");
        let err = NameKeyVisitor.visit_u8::<DeError>(1).unwrap_err();
        assert!(err.to_string().contains("a header name"), "{err}");

        // non-visible values can not be serialized to human readable formats
        let mut map = HeaderMap::new();
        map.insert(USER_AGENT, HeaderValue::from_bytes(b"caf\xc3\xa9").unwrap());
        assert!(serde_json::to_string(&map).is_err());
        let map2 = bincode::deserialize::<HeaderMap>(&bincode::serialize(&map).unwrap()).unwrap();
        assert_eq!(map, map2);
    }
}