Skip to main content

rama_http_hyperium/into_rama/
leaf.rs

1//! Leaf-type conversions (method, status, version, uri, header map).
2
3use rama_http_types::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Version};
4use rama_net::uri::Uri;
5
6use super::TryIntoRamaHttp;
7
8impl TryIntoRamaHttp for http::Method {
9    type Output = Method;
10    type Error = rama_http_types::Error;
11
12    fn try_into_rama_http(self) -> Result<Method, rama_http_types::Error> {
13        Ok(Method::from_bytes(self.as_str().as_bytes())?)
14    }
15}
16
17impl TryIntoRamaHttp for http::StatusCode {
18    type Output = StatusCode;
19    type Error = rama_http_types::Error;
20
21    fn try_into_rama_http(self) -> Result<StatusCode, rama_http_types::Error> {
22        Ok(StatusCode::from_u16(self.as_u16())?)
23    }
24}
25
26impl TryIntoRamaHttp for http::Version {
27    type Output = Version;
28    type Error = rama_http_types::Error;
29
30    fn try_into_rama_http(self) -> Result<Version, rama_http_types::Error> {
31        Ok(match self {
32            Self::HTTP_09 => Version::HTTP_09,
33            Self::HTTP_10 => Version::HTTP_10,
34            Self::HTTP_11 => Version::HTTP_11,
35            Self::HTTP_2 => Version::HTTP_2,
36            Self::HTTP_3 => Version::HTTP_3,
37            // `http::Version` exposes no other variant; defensive for its
38            // `#[non_exhaustive]` future-proofing.
39            _ => return Err(rama_net::http::InvalidVersion::new().into()),
40        })
41    }
42}
43
44impl TryIntoRamaHttp for http::Uri {
45    type Output = Uri;
46    type Error = rama_http_types::Error;
47
48    fn try_into_rama_http(self) -> Result<Uri, rama_http_types::Error> {
49        if self == Self::from_static("*") {
50            return Ok(Uri::from_static("*"));
51        }
52        // Authority-form (a CONNECT target like `example.com:443`): no scheme,
53        // an authority, and no path/query. The graceful parser would read it as
54        // `scheme:path` and silently drop the host, so route it through the
55        // authority-form parser instead.
56        if self.scheme().is_none() && self.authority().is_some() && self.path_and_query().is_none()
57        {
58            return Ok(Uri::parse_authority_form(self.to_string())?);
59        }
60        Ok(Uri::parse(self.to_string().as_str())?)
61    }
62}
63
64impl TryIntoRamaHttp for http::HeaderMap {
65    type Output = HeaderMap;
66    type Error = rama_http_types::Error;
67
68    fn try_into_rama_http(self) -> Result<HeaderMap, rama_http_types::Error> {
69        let mut out = HeaderMap::with_capacity(self.len());
70        let mut last: Option<HeaderName> = None;
71        for (name, hv) in self {
72            let mut out_hv = HeaderValue::from_bytes(hv.as_bytes())?;
73            out_hv.set_sensitive(hv.is_sensitive());
74            match name {
75                Some(name) => {
76                    let name = HeaderName::from_bytes(name.as_str().as_bytes())?;
77                    out.append(name.clone(), out_hv);
78                    last = Some(name);
79                }
80                None => {
81                    if let Some(name) = &last {
82                        out.append(name.clone(), out_hv);
83                    }
84                }
85            }
86        }
87        Ok(out)
88    }
89}
90
91impl TryIntoRamaHttp for &http::HeaderMap {
92    type Output = HeaderMap;
93    type Error = rama_http_types::Error;
94
95    /// Borrowing variant, for boundaries that only hand out a `&http::HeaderMap`
96    /// (e.g. a `multer` multipart field). Iterating by reference already repeats
97    /// the name per value, so no multi-value bookkeeping is needed.
98    fn try_into_rama_http(self) -> Result<HeaderMap, rama_http_types::Error> {
99        let mut out = HeaderMap::with_capacity(self.len());
100        for (name, hv) in self {
101            let name = HeaderName::from_bytes(name.as_str().as_bytes())?;
102            let mut out_hv = HeaderValue::from_bytes(hv.as_bytes())?;
103            out_hv.set_sensitive(hv.is_sensitive());
104            out.append(name, out_hv);
105        }
106        Ok(out)
107    }
108}