spacegate_kernel/utils/
str_extract.rs

1use crate::{extension::OriginalIpAddr, SgRequest};
2
3/// #
4/// ## headers:
5/// `parts/header/<header-name>`
6/// ## uri:
7/// `parts/uri`
8/// ### host
9/// `parts/uri/host`
10/// ### port
11/// `parts/uri/port`
12/// ### path
13/// `parts/uri/path`
14/// ### query
15/// `parts/uri/query`
16/// #### query value
17/// `parts/uri/query/<key>`
18/// ### scheme
19/// `parts/uri/scheme`
20/// ## extensions
21/// `ext/<extension-name>`
22#[derive(Debug)]
23pub enum StrExtractorKind<'a> {
24    Parts(StrExtractorPartsKind<'a>),
25    Extension(&'a str),
26}
27
28#[derive(Debug)]
29pub enum StrExtractorPartsKind<'a> {
30    Method,
31    Uri,
32    Header(&'a str),
33}
34
35impl<'a> StrExtractorKind<'a> {
36    pub fn try_from_str(str: &'a str) -> Option<Self> {
37        let kind = match str.split_once('/')? {
38            ("parts", "uri") => StrExtractorKind::Parts(StrExtractorPartsKind::Uri),
39            ("parts", "method") => StrExtractorKind::Parts(StrExtractorPartsKind::Method),
40            ("parts", other_part) => match other_part.split_once("/")? {
41                ("header", header_name) => StrExtractorKind::Parts(StrExtractorPartsKind::Header(header_name)),
42                _ => return None,
43            },
44            ("ext", parts) => StrExtractorKind::Extension(parts),
45            _ => return None,
46        };
47        Some(kind)
48    }
49}
50
51impl<'a> StrExtractorKind<'a> {
52    pub fn extract_to_string(&self, request: &SgRequest) -> Option<String> {
53        match self {
54            StrExtractorKind::Parts(str_extractor_parts_kind) => match str_extractor_parts_kind {
55                StrExtractorPartsKind::Method => Some(request.method().to_string()),
56                StrExtractorPartsKind::Uri => Some(request.uri().to_string()),
57                StrExtractorPartsKind::Header(header_name) => {
58                    let header_name = header_name.to_lowercase();
59                    Some(request.headers().get(header_name.as_str())?.to_str().ok()?.to_string())
60                }
61            },
62            StrExtractorKind::Extension(e) => match *e {
63                "original_ip_addr" => Some(request.extensions().get::<OriginalIpAddr>()?.to_string()),
64                _ => None,
65            },
66        }
67    }
68}