use async_trait::async_trait;
use std::collections::HashMap;
#[async_trait]
pub trait RouteResolver: Send + Sync {
async fn resolve(&self, key: &str) -> Option<String>;
}
pub struct StaticRouteResolver {
routes: HashMap<String, String>,
}
impl StaticRouteResolver {
pub fn new() -> Self {
Self {
routes: HashMap::new(),
}
}
pub fn add_route(mut self, key: impl Into<String>, backend_url: impl Into<String>) -> Self {
self.routes.insert(key.into(), backend_url.into());
self
}
pub fn with_routes(mut self, routes: HashMap<String, String>) -> Self {
self.routes = routes;
self
}
}
impl Default for StaticRouteResolver {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl RouteResolver for StaticRouteResolver {
async fn resolve(&self, key: &str) -> Option<String> {
self.routes.get(key).cloned()
}
}
pub fn extract_subdomain(host: &str) -> Option<String> {
let host = host.split(':').next().unwrap_or(host);
let parts: Vec<&str> = host.split('.').collect();
if parts.len() >= 3 {
Some(parts[0].to_string())
} else if parts.len() == 2 {
None
} else if parts.len() == 1 && parts[0] == "localhost" {
Some("infra".to_string())
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_subdomain() {
assert_eq!(
extract_subdomain("infra.example.com"),
Some("infra".to_string())
);
assert_eq!(
extract_subdomain("api.example.com"),
Some("api".to_string())
);
assert_eq!(extract_subdomain("example.com"), None);
assert_eq!(extract_subdomain("localhost"), Some("infra".to_string()));
assert_eq!(
extract_subdomain("infra.example.com:8080"),
Some("infra".to_string())
);
assert_eq!(
extract_subdomain("my-service.example.com"),
Some("my-service".to_string())
);
}
#[tokio::test]
async fn test_static_route_resolver() {
let resolver = StaticRouteResolver::new()
.add_route("api", "http://api-backend:8080")
.add_route("admin", "http://admin-backend:9000");
assert_eq!(
resolver.resolve("api").await,
Some("http://api-backend:8080".to_string())
);
assert_eq!(
resolver.resolve("admin").await,
Some("http://admin-backend:9000".to_string())
);
assert_eq!(resolver.resolve("unknown").await, None);
}
}