@@ -2,12 +2,15 @@ use rand::Rng;
22use std:: fmt;
33
44use crate :: headers:: { HeaderName , HeaderValue , Headers , TRACEPARENT } ;
5+ use crate :: Status ;
56
67/// Extract and apply [Trace-Context](https://w3c.github.io/trace-context/) headers.
78///
8- /// ## Examples
9+ /// # Examples
910///
1011/// ```
12+ /// # fn main() -> http_types::Result<()> {
13+ /// #
1114/// use http_types::trace::TraceContext;
1215///
1316/// let mut res = http_types::Response::new(200);
@@ -17,14 +20,16 @@ use crate::headers::{HeaderName, HeaderValue, Headers, TRACEPARENT};
1720/// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
1821/// );
1922///
20- /// let context = TraceContext::from_headers(&res).unwrap();
23+ /// let context = TraceContext::from_headers(&res)? .unwrap();
2124///
2225/// let trace_id = u128::from_str_radix("0af7651916cd43dd8448eb211c80319c", 16);
2326/// let parent_id = u64::from_str_radix("00f067aa0ba902b7", 16);
2427///
2528/// assert_eq!(context.trace_id(), trace_id.unwrap());
2629/// assert_eq!(context.parent_id(), parent_id.ok());
2730/// assert_eq!(context.sampled(), true);
31+ /// #
32+ /// # Ok(()) }
2833/// ```
2934#[ derive( Debug ) ]
3035pub struct TraceContext {
@@ -41,7 +46,7 @@ impl TraceContext {
4146 /// By default root TraceContext objects are sampled.
4247 /// To mark it unsampled, call `context.set_sampled(false)`.
4348 ///
44- /// ## Examples
49+ /// # Examples
4550 /// ```
4651 /// use http_types::trace::TraceContext;
4752 ///
@@ -64,8 +69,16 @@ impl TraceContext {
6469
6570 /// Create and return TraceContext object based on `traceparent` HTTP header.
6671 ///
67- /// ## Examples
72+ /// # Errors
73+ ///
74+ /// This function may error if the header is malformed. An error with a
75+ /// status code of `400: Bad Request` will be generated.
76+ ///
77+ /// # Examples
78+ ///
6879 /// ```
80+ /// # fn main() -> http_types::Result<()> {
81+ /// #
6982 /// use http_types::trace::TraceContext;
7083 ///
7184 /// let mut res = http_types::Response::new(200);
@@ -74,35 +87,43 @@ impl TraceContext {
7487 /// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
7588 /// );
7689 ///
77- /// let context = TraceContext::from_headers(&res).unwrap();
90+ /// let context = TraceContext::from_headers(&res)? .unwrap();
7891 ///
7992 /// let trace_id = u128::from_str_radix("0af7651916cd43dd8448eb211c80319c", 16);
8093 /// let parent_id = u64::from_str_radix("00f067aa0ba902b7", 16);
8194 ///
8295 /// assert_eq!(context.trace_id(), trace_id.unwrap());
8396 /// assert_eq!(context.parent_id(), parent_id.ok());
8497 /// assert_eq!(context.sampled(), true);
98+ /// #
99+ /// # Ok(()) }
85100 /// ```
86- pub fn from_headers ( headers : impl AsRef < Headers > ) -> Option < Self > {
101+ pub fn from_headers ( headers : impl AsRef < Headers > ) -> crate :: Result < Option < Self > > {
87102 let headers = headers. as_ref ( ) ;
88103 let mut rng = rand:: thread_rng ( ) ;
89104
90- let traceparent = headers. get ( TRACEPARENT ) ?;
105+ let traceparent = match headers. get ( TRACEPARENT ) {
106+ Some ( header) => header,
107+ None => return Ok ( None ) ,
108+ } ;
91109 let parts: Vec < & str > = traceparent. as_str ( ) . split ( '-' ) . collect ( ) ;
92110
93- Some ( Self {
111+ Ok ( Some ( Self {
94112 id : rng. gen ( ) ,
95- version : u8:: from_str_radix ( parts[ 0 ] , 16 ) . ok ( ) ?,
96- trace_id : u128:: from_str_radix ( parts[ 1 ] , 16 ) . ok ( ) ?,
97- parent_id : Some ( u64:: from_str_radix ( parts[ 2 ] , 16 ) . ok ( ) ?) ,
98- flags : u8:: from_str_radix ( parts[ 3 ] , 16 ) . ok ( ) ?,
99- } )
113+ version : u8:: from_str_radix ( parts[ 0 ] , 16 ) ?,
114+ trace_id : u128:: from_str_radix ( parts[ 1 ] , 16 ) . status ( 400 ) ?,
115+ parent_id : Some ( u64:: from_str_radix ( parts[ 2 ] , 16 ) . status ( 400 ) ?) ,
116+ flags : u8:: from_str_radix ( parts[ 3 ] , 16 ) . status ( 400 ) ?,
117+ } ) )
100118 }
101119
102120 /// Add the traceparent header to the http headers
103121 ///
104- /// ## Examples
122+ /// # Examples
123+ ///
105124 /// ```
125+ /// # fn main() -> http_types::Result<()> {
126+ /// #
106127 /// use http_types::trace::TraceContext;
107128 /// use http_types::{Request, Response, Url, Method};
108129 ///
@@ -112,16 +133,18 @@ impl TraceContext {
112133 /// "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
113134 /// );
114135 ///
115- /// let parent = TraceContext::from_headers(&req).unwrap();
136+ /// let parent = TraceContext::from_headers(&req)? .unwrap();
116137 ///
117138 /// let mut res = Response::new(200);
118139 /// parent.apply(&mut res);
119140 ///
120- /// let child = TraceContext::from_headers(&res).unwrap();
141+ /// let child = TraceContext::from_headers(&res)? .unwrap();
121142 ///
122143 /// assert_eq!(child.version(), parent.version());
123144 /// assert_eq!(child.trace_id(), parent.trace_id());
124145 /// assert_eq!(child.parent_id(), Some(parent.id()));
146+ /// #
147+ /// # Ok(()) }
125148 /// ```
126149 pub fn apply ( & self , mut headers : impl AsMut < Headers > ) {
127150 let headers = headers. as_mut ( ) ;
@@ -182,24 +205,28 @@ impl TraceContext {
182205
183206 /// Returns true if the trace is sampled
184207 ///
185- /// ## Examples
208+ /// # Examples
186209 ///
187210 /// ```
211+ /// # fn main() -> http_types::Result<()> {
212+ /// #
188213 /// use http_types::trace::TraceContext;
189214 /// use http_types::Response;
190215 ///
191216 /// let mut res = Response::new(200);
192217 /// res.insert_header("traceparent", "00-00000000000000000000000000000001-0000000000000002-01");
193- /// let context = TraceContext::from_headers(&res).unwrap();
218+ /// let context = TraceContext::from_headers(&res)? .unwrap();
194219 /// assert_eq!(context.sampled(), true);
220+ /// #
221+ /// # Ok(()) }
195222 /// ```
196223 pub fn sampled ( & self ) -> bool {
197224 ( self . flags & 0b00000001 ) == 1
198225 }
199226
200227 /// Change sampled flag
201228 ///
202- /// ## Examples
229+ /// # Examples
203230 ///
204231 /// ```
205232 /// use http_types::trace::TraceContext;
@@ -233,7 +260,7 @@ mod test {
233260 fn default ( ) -> crate :: Result < ( ) > {
234261 let mut headers = crate :: Headers :: new ( ) ;
235262 headers. insert ( TRACEPARENT , "00-01-deadbeef-00" ) ;
236- let context = TraceContext :: from_headers ( & mut headers) . unwrap ( ) ;
263+ let context = TraceContext :: from_headers ( & mut headers) ? . unwrap ( ) ;
237264 assert_eq ! ( context. version( ) , 0 ) ;
238265 assert_eq ! ( context. trace_id( ) , 1 ) ;
239266 assert_eq ! ( context. parent_id( ) . unwrap( ) , 3735928559 ) ;
@@ -256,7 +283,7 @@ mod test {
256283 fn not_sampled ( ) -> crate :: Result < ( ) > {
257284 let mut headers = crate :: Headers :: new ( ) ;
258285 headers. insert ( TRACEPARENT , "00-01-02-00" ) ;
259- let context = TraceContext :: from_headers ( & mut headers) . unwrap ( ) ;
286+ let context = TraceContext :: from_headers ( & mut headers) ? . unwrap ( ) ;
260287 assert_eq ! ( context. sampled( ) , false ) ;
261288 Ok ( ( ) )
262289 }
@@ -265,7 +292,7 @@ mod test {
265292 fn sampled ( ) -> crate :: Result < ( ) > {
266293 let mut headers = crate :: Headers :: new ( ) ;
267294 headers. insert ( TRACEPARENT , "00-01-02-01" ) ;
268- let context = TraceContext :: from_headers ( & mut headers) . unwrap ( ) ;
295+ let context = TraceContext :: from_headers ( & mut headers) ? . unwrap ( ) ;
269296 assert_eq ! ( context. sampled( ) , true ) ;
270297 Ok ( ( ) )
271298 }
0 commit comments