Skip to main content

bulwark_security/request/
normalize.rs

1use super::context::RequestContext;
2
3/// Normalize request context before inspection.
4///
5/// Goals:
6/// - predictable input
7/// - no ambiguity
8/// - reduce bypass surface
9pub struct Normalizer;
10
11impl Normalizer {
12    /// Run all normalization steps.
13    pub fn normalize(ctx: &mut RequestContext) {
14        Self::normalize_path(ctx);
15        Self::normalize_headers(ctx);
16        Self::normalize_query(ctx);
17    }
18
19    /// Normalize request path.
20    ///
21    /// - remove trailing slashes (except root)
22    /// - collapse multiple slashes
23    fn normalize_path(ctx: &mut RequestContext) {
24        let mut path = ctx.path.clone();
25
26        // collapse multiple slashes: ///a//b -> /a/b
27        while path.contains("//") {
28            path = path.replace("//", "/");
29        }
30
31        // remove trailing slash (except "/")
32        if path.len() > 1 && path.ends_with('/') {
33            path.pop();
34        }
35
36        ctx.path = path;
37    }
38
39    /// Normalize headers.
40    ///
41    /// - trim whitespace
42    /// - lowercase keys (already done, but re-assert)
43    fn normalize_headers(ctx: &mut RequestContext) {
44        let mut normalized = std::collections::HashMap::new();
45
46        for (k, v) in ctx.headers.iter() {
47            let key = k.trim().to_lowercase();
48            let value = v.trim().to_string();
49            normalized.insert(key, value);
50        }
51
52        ctx.headers = normalized;
53    }
54
55    /// Normalize query parameters.
56    ///
57    /// - trim whitespace
58    /// - drop empty keys
59    fn normalize_query(ctx: &mut RequestContext) {
60        let mut normalized = std::collections::HashMap::new();
61
62        for (k, v) in ctx.query.iter() {
63            let key = k.trim();
64            if key.is_empty() {
65                continue;
66            }
67
68            normalized.insert(key.to_string(), v.trim().to_string());
69        }
70
71        ctx.query = normalized;
72    }
73}