1use http::HeaderMap;
2use uuid::Uuid;
3
4use crate::REQUEST_ID_HEADER;
5
6pub const MAX_REQUEST_ID_BYTES: usize = 128;
8
9#[must_use]
11pub fn is_valid_request_id(value: &str) -> bool {
12 !value.is_empty()
13 && value.len() <= MAX_REQUEST_ID_BYTES
14 && value
15 .bytes()
16 .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b':'))
17}
18
19#[must_use]
21pub fn safe_request_id(value: Option<&str>) -> String {
22 value
23 .filter(|value| is_valid_request_id(value))
24 .map_or_else(|| Uuid::now_v7().to_string(), str::to_owned)
25}
26
27#[must_use]
29pub fn request_id_from_headers(headers: &HeaderMap) -> String {
30 safe_request_id(
31 headers
32 .get(&REQUEST_ID_HEADER)
33 .and_then(|value| value.to_str().ok()),
34 )
35}