Skip to main content

rama_http_headers/common/
host.rs

1use std::convert::TryFrom;
2use std::fmt;
3
4use rama_core::{bytes::Bytes, telemetry::tracing};
5use rama_http_types::{HeaderName, HeaderValue};
6use rama_net::address::{self, HostWithOptPort};
7
8use crate::{Error, HeaderDecode, HeaderEncode, TypedHeader};
9
10/// The `Host` header.
11#[derive(Clone, Debug, PartialEq, Eq, Hash)]
12pub struct Host(pub HostWithOptPort);
13
14impl TypedHeader for Host {
15    fn name() -> &'static HeaderName {
16        &::rama_http_types::header::HOST
17    }
18}
19
20impl HeaderDecode for Host {
21    fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, Error> {
22        let addr = values
23            .next()
24            .and_then(|val| HostWithOptPort::try_from(val.as_bytes()).ok())
25            .ok_or_else(Error::invalid)?;
26        Ok(Self(addr))
27    }
28}
29
30impl HeaderEncode for Host {
31    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
32        let s = self.to_string();
33        let bytes = Bytes::from_owner(s);
34
35        match HeaderValue::from_maybe_shared(bytes) {
36            Ok(value) => values.extend(::std::iter::once(value)),
37            Err(err) => {
38                tracing::debug!(
39                    "failed to encode stringified authority (host w/ opt port) as header value: {err}"
40                );
41            }
42        }
43    }
44}
45
46impl From<address::Host> for Host {
47    #[inline(always)]
48    fn from(host: address::Host) -> Self {
49        Self(host.into())
50    }
51}
52
53impl From<Host> for address::Host {
54    #[inline(always)]
55    fn from(value: Host) -> Self {
56        value.0.host
57    }
58}
59
60impl From<HostWithOptPort> for Host {
61    #[inline(always)]
62    fn from(addr: HostWithOptPort) -> Self {
63        Self(addr)
64    }
65}
66
67impl From<Host> for HostWithOptPort {
68    #[inline(always)]
69    fn from(host: Host) -> Self {
70        host.0
71    }
72}
73
74impl From<address::HostWithPort> for Host {
75    #[inline(always)]
76    fn from(addr: address::HostWithPort) -> Self {
77        Self(addr.into())
78    }
79}
80
81impl fmt::Display for Host {
82    #[inline(always)]
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        self.0.fmt(f)
85    }
86}