Skip to main content

route_util/
extract.rs

1use hyper::Uri;
2
3/// http服务提取物
4#[derive(Debug, Clone)]
5pub struct HttpExtract<'a> {
6    pub service: &'a str,
7    pub method: &'a str,
8}
9
10impl<'a> HttpExtract<'a> {
11    pub fn is_mailbox(&self) -> bool {
12        self.service == "mailbox"
13    }
14}
15
16/// grpc服务提取物
17#[derive(Debug, Clone)]
18pub struct GrpcExtract<'a> {
19    pub package: &'a str,
20    pub service: &'a str,
21    pub method: &'a str,
22}
23
24impl<'a> GrpcExtract<'a> {
25    pub fn is_mailbox(&self) -> bool {
26        self.service == "mailbox"
27    }
28}
29
30/// 提取服务名
31pub trait UriExtract {
32    /// http(s)://host:port/service/method
33    fn extract_http(&self) -> Result<HttpExtract, &str>;
34
35    /// http(s)://host:port/protocol.service/method
36    fn extract_grpc(&self) -> Result<GrpcExtract, &str>;
37}
38
39/// 非合法的path会导致提取失败
40impl UriExtract for Uri {
41    fn extract_http(&self) -> Result<HttpExtract, &str> {
42        let (service, method) = extract_service_method(self.path())?;
43        Ok(HttpExtract { service, method })
44    }
45
46    fn extract_grpc(&self) -> Result<GrpcExtract, &str> {
47        let (svc_full, method) = extract_service_method(self.path())?;
48
49        let (package, service) = svc_full
50            .split_once('.')
51            .filter(|(p, s)| !p.is_empty() && !s.is_empty())
52            .ok_or(self.path())?;
53
54        Ok(GrpcExtract {
55            package,
56            service,
57            method,
58        })
59    }
60}
61
62fn extract_service_method(path: &str) -> Result<(&str, &str), &str> {
63    Ok(path
64        .trim_start_matches('/')
65        .split_once('/')
66        .filter(|(s, m)| !s.is_empty() && !m.is_empty())
67        .ok_or(path)?)
68}
69
70/// 提取服务id
71pub trait HeaderExtract {
72    ///
73    fn extract_target(&self) -> Option<u32>;
74}
75
76impl HeaderExtract for hyper::HeaderMap<hyper::header::HeaderValue> {
77    fn extract_target(&self) -> Option<u32> {
78        for (k, v) in self.iter() {
79            if k.eq("target_service_id") {
80                let id = String::from_utf8_lossy(v.as_bytes());
81                let id: Result<u32, _> = id.parse();
82                return id.ok();
83            }
84        }
85        None
86    }
87}