hitbox_http/extractors/transform.rs
1//! Shared value transformations for extractors.
2//!
3//! Transforms modify extracted values before they become part of the cache key.
4//! They can be chained to apply multiple transformations in sequence.
5//!
6//! # Examples
7//!
8//! ```
9//! use hitbox_http::extractors::transform::Transform;
10//!
11//! // Hash sensitive values to avoid storing them in cache keys
12//! let transforms = vec![Transform::Hash];
13//!
14//! // Normalize case for case-insensitive matching
15//! let transforms = vec![Transform::Lowercase];
16//! ```
17
18use sha2::{Digest, Sha256};
19
20/// Transforms extracted values before they become cache key parts.
21///
22/// Multiple transforms can be chained and are applied in order.
23#[derive(Debug, Clone, Copy)]
24pub enum Transform {
25 /// SHA256 hash, truncated to 16 hex characters.
26 ///
27 /// Useful for hashing sensitive values (API keys, tokens) to avoid
28 /// storing them directly in cache keys while still differentiating requests.
29 Hash,
30 /// Convert to lowercase.
31 ///
32 /// Useful for case-insensitive cache key matching.
33 Lowercase,
34 /// Convert to uppercase.
35 Uppercase,
36}
37
38/// Apply SHA256 hash to value (truncated to 16 hex chars).
39pub fn apply_hash(value: &str) -> String {
40 let mut hasher = Sha256::new();
41 hasher.update(value.as_bytes());
42 let result = hasher.finalize();
43 hex::encode(&result[..8])
44}
45
46/// Apply a single transform to a value.
47pub fn apply_single_transform(value: String, transform: &Transform) -> String {
48 match transform {
49 Transform::Hash => apply_hash(&value),
50 Transform::Lowercase => value.to_lowercase(),
51 Transform::Uppercase => value.to_uppercase(),
52 }
53}
54
55/// Apply a chain of transforms to a value.
56pub fn apply_transform_chain(mut value: String, chain: &[Transform]) -> String {
57 for transform in chain {
58 value = apply_single_transform(value, transform);
59 }
60 value
61}