use hyper::Uri;
#[derive(Debug, Clone)]
pub struct HttpExtract<'a> {
pub service: &'a str,
pub method: &'a str,
}
impl<'a> HttpExtract<'a> {
pub fn is_mailbox(&self) -> bool {
self.service == "mailbox"
}
}
#[derive(Debug, Clone)]
pub struct GrpcExtract<'a> {
pub package: &'a str,
pub service: &'a str,
pub method: &'a str,
}
impl<'a> GrpcExtract<'a> {
pub fn is_mailbox(&self) -> bool {
self.service == "mailbox"
}
}
pub trait UriExtract {
fn extract_http(&self) -> Result<HttpExtract, &str>;
fn extract_grpc(&self) -> Result<GrpcExtract, &str>;
}
impl UriExtract for Uri {
fn extract_http(&self) -> Result<HttpExtract, &str> {
let (service, method) = extract_service_method(self.path())?;
Ok(HttpExtract { service, method })
}
fn extract_grpc(&self) -> Result<GrpcExtract, &str> {
let (svc_full, method) = extract_service_method(self.path())?;
let (package, service) = svc_full
.split_once('.')
.filter(|(p, s)| !p.is_empty() && !s.is_empty())
.ok_or(self.path())?;
Ok(GrpcExtract {
package,
service,
method,
})
}
}
fn extract_service_method(path: &str) -> Result<(&str, &str), &str> {
Ok(path
.trim_start_matches('/')
.split_once('/')
.filter(|(s, m)| !s.is_empty() && !m.is_empty())
.ok_or(path)?)
}
pub trait HeaderExtract {
fn extract_target(&self) -> Option<u32>;
}
impl HeaderExtract for hyper::HeaderMap<hyper::header::HeaderValue> {
fn extract_target(&self) -> Option<u32> {
for (k, v) in self.iter() {
if k.eq("target_service_id") {
let id = String::from_utf8_lossy(v.as_bytes());
let id: Result<u32, _> = id.parse();
return id.ok();
}
}
None
}
}