openapi_context/
header.rs1use chrono::{DateTime, Utc};
2use headers::{HeaderValue, HeaderName, Header, HeaderMapExt};
3use lazy_static::lazy_static;
4use std::convert::TryFrom;
5use std::fmt;
6use std::ops::Deref;
7use uuid::Uuid;
8
9pub const X_SPAN_ID: &str = "x-span-id";
11
12lazy_static! {
13 pub static ref X_SPAN_ID_HEADER: HeaderName = HeaderName::from_static(X_SPAN_ID);
14}
15
16#[derive(Debug, Clone)]
18pub struct XSpanId(pub String);
19
20impl XSpanId {
21 pub fn get_or_generate<T>(req: &hyper::Request<T>) -> Self {
24 let x_span_id = req.headers().typed_get::<XSpanId>();
25
26 match x_span_id {
27 Some(ref x) => x.clone(),
28 None => Self::default(),
29 }
30 }
31}
32
33impl Header for XSpanId {
34 fn name() -> &'static HeaderName {
35 &X_SPAN_ID_HEADER
36 }
37
38 fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
39 where
40 I: Iterator<Item = &'i HeaderValue>,
41 {
42 let value = values
43 .next()
44 .ok_or_else(headers::Error::invalid)?;
45
46 let value = value.to_str().map_err(|_| headers::Error::invalid())?;
47 Ok(XSpanId(value.to_owned()))
48 }
49
50 fn encode<E>(&self, values: &mut E)
51 where
52 E: Extend<HeaderValue>,
53 {
54 let value = HeaderValue::from_str(&self.0.to_string()).unwrap();
55
56 values.extend(std::iter::once(value));
57 }
58}
59
60impl Default for XSpanId {
61 fn default() -> Self {
62 XSpanId(Uuid::new_v4().to_string())
63 }
64}
65
66impl fmt::Display for XSpanId {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f, "{}", self.0)
69 }
70}
71
72#[derive(Debug, Clone)]
76pub struct IntoHeaderValue<T>(pub T);
77
78impl<T> Deref for IntoHeaderValue<T> {
81 type Target = T;
82
83 fn deref(&self) -> &T {
84 &self.0
85 }
86}
87
88macro_rules! ihv_generate {
91 ($t:ident) => {
92 impl std::convert::TryFrom<HeaderValue> for IntoHeaderValue<$t> {
93 type Error = headers::Error;
94 fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
95 let value = hdr_value.to_str().map_err(|_| headers::Error::invalid())?;
96 let value = value.parse().map_err(|_| headers::Error::invalid())?;
97 Ok(IntoHeaderValue(value))
98 }
99 }
100
101 impl Into<HeaderValue> for IntoHeaderValue<$t> {
102 fn into(self) -> HeaderValue {
103 HeaderValue::from_str(&self.0.to_string()).unwrap()
104 }
105 }
106 };
107}
108
109ihv_generate!(u64);
110ihv_generate!(i64);
111ihv_generate!(i16);
112ihv_generate!(u16);
113ihv_generate!(u32);
114ihv_generate!(usize);
115ihv_generate!(isize);
116ihv_generate!(i32);
117
118impl TryFrom<HeaderValue> for IntoHeaderValue<Vec<String>> {
121 type Error = headers::Error;
122 fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
123 Ok(IntoHeaderValue(
124 hdr_value
125 .to_str()
126 .map_err(|_| headers::Error::invalid())?
127 .split(',')
128 .filter_map(|x| match x.trim() {
129 "" => None,
130 y => Some(y.to_string()),
131 })
132 .collect(),
133 ))
134 }
135}
136
137impl Into<HeaderValue> for IntoHeaderValue<Vec<String>> {
138 fn into(self) -> HeaderValue {
139 HeaderValue::from_str(&self.0.join(", ")).unwrap()
140 }
141}
142
143impl TryFrom<HeaderValue> for IntoHeaderValue<String> {
144 type Error = headers::Error;
145 fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
146 let v = hdr_value
147 .to_str()
148 .map_err(|_| headers::Error::invalid())?
149 .to_string();
150 Ok(IntoHeaderValue(v))
151 }
152}
153
154impl Into<HeaderValue> for IntoHeaderValue<String> {
155 fn into(self) -> HeaderValue {
156 HeaderValue::from_str(&self.0).unwrap()
157 }
158}
159
160impl TryFrom<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
161 type Error = headers::Error;
162 fn try_from(hdr_value: HeaderValue) -> Result<Self, Self::Error> {
163 let v = hdr_value.to_str().map_err(|_| headers::Error::invalid())?;
164 Ok(IntoHeaderValue(
165 DateTime::parse_from_rfc3339(v)
166 .map_err(|_| headers::Error::invalid())?
167 .with_timezone(&Utc)
168 ))
169 }
170}
171
172impl Into<HeaderValue> for IntoHeaderValue<DateTime<Utc>> {
173 fn into(self) -> HeaderValue {
174 HeaderValue::from_str(self.0.to_rfc3339().as_str()).unwrap()
175 }
176}