35 lines
869 B
Rust
35 lines
869 B
Rust
use actix_web::{HttpRequest, http::header::HeaderName};
|
|
use uuid::Uuid;
|
|
|
|
pub const REQUEST_ID_HEADER: &str = "x-request-id";
|
|
|
|
pub fn from_request(request: &HttpRequest) -> String {
|
|
request
|
|
.headers()
|
|
.get(HeaderName::from_static(REQUEST_ID_HEADER))
|
|
.and_then(|value| value.to_str().ok())
|
|
.map(str::trim)
|
|
.filter(|value| is_valid(value))
|
|
.map(str::to_owned)
|
|
.unwrap_or_else(|| Uuid::new_v4().to_string())
|
|
}
|
|
|
|
fn is_valid(value: &str) -> bool {
|
|
!value.is_empty()
|
|
&& value.len() <= 128
|
|
&& value
|
|
.chars()
|
|
.all(|character| character.is_ascii_alphanumeric() || "-_:.".contains(character))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn rejects_header_injection() {
|
|
assert!(!is_valid("abc\nerror"));
|
|
assert!(is_valid("req-123"));
|
|
}
|
|
}
|