linkerd2_proxy_api/
http_types.rs

1use std::{
2    borrow::Cow,
3    convert::{TryFrom, TryInto},
4    sync::Arc,
5};
6use thiserror::Error;
7
8include!("gen/io.linkerd.proxy.http_types.rs");
9
10/// Indicates an HTTP Method could not be decoded.
11#[derive(Clone, Debug, Error)]
12pub enum InvalidMethod {
13    #[error("missing HTTP method type")]
14    MissingType,
15
16    #[error("unexpected registered method: {0}")]
17    Registered(i32),
18
19    #[error("invalid unregistered method: {0}")]
20    Unregistered(#[source] Arc<http::method::InvalidMethod>),
21}
22
23/// Indicates a URI Scheme could not be decoded.
24#[derive(Clone, Debug, Error)]
25pub enum InvalidScheme {
26    #[error("scheme must have a type")]
27    MissingType,
28
29    #[error("unexpected registered scheme: {0}")]
30    Registered(i32),
31
32    #[error("invalid unregistered scheme: {0}")]
33    Unregistered(#[source] Arc<http::uri::InvalidUri>),
34}
35
36// === impl scheme::Type ===
37
38impl TryInto<Cow<'static, str>> for &'_ scheme::Type {
39    type Error = InvalidScheme;
40
41    fn try_into(self) -> Result<Cow<'static, str>, Self::Error> {
42        use scheme::*;
43
44        match *self {
45            Type::Registered(s) if s == Registered::Http as i32 => Ok(Cow::Borrowed("http")),
46            Type::Registered(s) if s == Registered::Https as i32 => Ok(Cow::Borrowed("https")),
47            Type::Registered(s) => Err(InvalidScheme::Registered(s)),
48            Type::Unregistered(ref s) => Ok(Cow::Owned(s.clone())),
49        }
50    }
51}
52
53// === impl http::HttpMethod ===
54
55impl TryFrom<HttpMethod> for http::Method {
56    type Error = InvalidMethod;
57
58    fn try_from(proto: HttpMethod) -> Result<http::Method, Self::Error> {
59        proto.r#type.ok_or(InvalidMethod::MissingType)?.try_into()
60    }
61}
62
63impl TryFrom<http_method::Type> for http::Method {
64    type Error = InvalidMethod;
65
66    fn try_from(proto: http_method::Type) -> Result<http::Method, Self::Error> {
67        use http_method::*;
68
69        match proto {
70            Type::Registered(m) if m == Registered::Connect as i32 => Ok(http::Method::CONNECT),
71            Type::Registered(m) if m == Registered::Delete as i32 => Ok(http::Method::DELETE),
72            Type::Registered(m) if m == Registered::Get as i32 => Ok(http::Method::GET),
73            Type::Registered(m) if m == Registered::Head as i32 => Ok(http::Method::HEAD),
74            Type::Registered(m) if m == Registered::Options as i32 => Ok(http::Method::OPTIONS),
75            Type::Registered(m) if m == Registered::Patch as i32 => Ok(http::Method::PATCH),
76            Type::Registered(m) if m == Registered::Post as i32 => Ok(http::Method::POST),
77            Type::Registered(m) if m == Registered::Put as i32 => Ok(http::Method::PUT),
78            Type::Registered(m) if m == Registered::Trace as i32 => Ok(http::Method::TRACE),
79            Type::Registered(m) => Err(InvalidMethod::Registered(m)),
80            Type::Unregistered(ref m) => m
81                .parse()
82                .map_err(|e| InvalidMethod::Unregistered(Arc::new(e))),
83        }
84    }
85}
86
87impl From<http::Method> for http_method::Type {
88    fn from(m: http::Method) -> Self {
89        use http_method::*;
90
91        match m {
92            http::Method::GET => Type::Registered(Registered::Get.into()),
93            http::Method::POST => Type::Registered(Registered::Post.into()),
94            http::Method::PUT => Type::Registered(Registered::Put.into()),
95            http::Method::DELETE => Type::Registered(Registered::Delete.into()),
96            http::Method::PATCH => Type::Registered(Registered::Patch.into()),
97            http::Method::HEAD => Type::Registered(Registered::Head.into()),
98            http::Method::OPTIONS => Type::Registered(Registered::Options.into()),
99            http::Method::CONNECT => Type::Registered(Registered::Connect.into()),
100            http::Method::TRACE => Type::Registered(Registered::Trace.into()),
101            ref method => Type::Unregistered(method.as_str().into()),
102        }
103    }
104}
105
106impl From<http::Method> for HttpMethod {
107    fn from(m: http::Method) -> Self {
108        HttpMethod {
109            r#type: Some(m.into()),
110        }
111    }
112}
113
114// === impl Scheme ===
115
116impl<'a> From<&'a http::uri::Scheme> for Scheme {
117    fn from(scheme: &'a http::uri::Scheme) -> Self {
118        scheme.as_ref().into()
119    }
120}
121
122impl<'a> From<&'a str> for scheme::Type {
123    fn from(s: &'a str) -> Self {
124        use scheme::*;
125
126        match s {
127            "http" => Type::Registered(Registered::Http.into()),
128            "https" => Type::Registered(Registered::Https.into()),
129            s => Type::Unregistered(s.into()),
130        }
131    }
132}
133
134impl<'a> From<&'a str> for Scheme {
135    fn from(s: &'a str) -> Self {
136        Scheme {
137            r#type: Some(s.into()),
138        }
139    }
140}
141
142impl TryFrom<Scheme> for http::uri::Scheme {
143    type Error = InvalidScheme;
144
145    fn try_from(s: Scheme) -> Result<Self, Self::Error> {
146        match s.r#type.ok_or(InvalidScheme::MissingType)? {
147            scheme::Type::Registered(typ) => {
148                if typ == scheme::Registered::Http as i32 {
149                    Ok(http::uri::Scheme::HTTP)
150                } else if typ == scheme::Registered::Https as i32 {
151                    Ok(http::uri::Scheme::HTTPS)
152                } else {
153                    Err(InvalidScheme::Registered(typ))
154                }
155            }
156            scheme::Type::Unregistered(typ) => typ
157                .parse()
158                .map_err(|e| InvalidScheme::Unregistered(Arc::new(e))),
159        }
160    }
161}
162
163#[cfg(feature = "arbitrary")]
164mod arbitary {
165    use super::*;
166    use quickcheck::*;
167
168    impl Arbitrary for HttpMethod {
169        fn arbitrary(g: &mut Gen) -> Self {
170            HttpMethod {
171                r#type: Arbitrary::arbitrary(g),
172            }
173        }
174    }
175
176    impl Arbitrary for http_method::Type {
177        fn arbitrary(g: &mut Gen) -> Self {
178            match u16::arbitrary(g) % 9 {
179                8 => http_method::Type::Unregistered(String::arbitrary(g)),
180                n => http_method::Type::Registered(n.into()),
181            }
182        }
183    }
184
185    impl Arbitrary for Scheme {
186        fn arbitrary(g: &mut Gen) -> Self {
187            Scheme {
188                r#type: Arbitrary::arbitrary(g),
189            }
190        }
191    }
192
193    impl Arbitrary for scheme::Type {
194        fn arbitrary(g: &mut Gen) -> Self {
195            match u16::arbitrary(g) % 3 {
196                3 => scheme::Type::Unregistered(String::arbitrary(g)),
197                n => scheme::Type::Registered(n.into()),
198            }
199        }
200    }
201}