linkerd2_proxy_api/
http_types.rs1use 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#[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#[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
36impl 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
53impl 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
114impl<'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}