cratestack_axum/headers/
traceparent.rs1use axum::http::HeaderMap;
2use cratestack_core::CoolError;
3
4pub fn parse_traceparent(headers: &HeaderMap) -> Result<Option<String>, CoolError> {
14 let Some(value) = headers.get("traceparent") else {
15 return Ok(None);
16 };
17 let raw = value
18 .to_str()
19 .map_err(|_| CoolError::BadRequest("traceparent must be ASCII".to_owned()))?
20 .trim();
21 if raw.is_empty() {
22 return Ok(None);
23 }
24 let parts: Vec<&str> = raw.split('-').collect();
25 if parts.len() != 4 {
26 return Err(CoolError::BadRequest(
27 "traceparent must have 4 hyphen-delimited segments".to_owned(),
28 ));
29 }
30 let trace_id = parts[1];
31 if trace_id.len() != 32 || !trace_id.chars().all(|c| c.is_ascii_hexdigit()) {
32 return Err(CoolError::BadRequest(
33 "traceparent trace-id must be 32 lowercase hex characters".to_owned(),
34 ));
35 }
36 if trace_id == "00000000000000000000000000000000" {
37 return Err(CoolError::BadRequest(
38 "traceparent trace-id must not be all zeros".to_owned(),
39 ));
40 }
41 Ok(Some(trace_id.to_owned()))
42}