1mod predicates;
20
21#[cfg(test)]
22mod tests;
23
24pub use predicates::*;
25
26use std::collections::HashMap;
27use std::sync::Arc;
28use async_trait::async_trait;
29use tokio::sync::RwLock;
30use serde::{Serialize, Deserialize};
31
32use crate::config::Config;
33use crate::core::{ProxyRequest, ProxyError, Route};
34use crate::FilterFactory;
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct RouteConfig {
39 pub id: String,
41 pub target: String,
43 #[serde(default)]
45 pub filters: Vec<FilterConfig>,
46 #[serde(default = "default_priority")]
48 pub priority: i32,
49 #[serde(default)]
51 pub predicates: Vec<PredicateConfig>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct FilterConfig {
57 #[serde(rename = "type")]
59 pub type_: String,
60 pub config: serde_json::Value,
62}
63
64fn default_priority() -> i32 {
65 0
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct PredicateConfig {
71 pub type_: String,
73 pub config: serde_json::Value,
75}
76
77#[async_trait]
79pub trait Predicate: Send + Sync + std::fmt::Debug {
80 async fn matches(&self, request: &ProxyRequest) -> bool;
82
83 fn predicate_type(&self) -> &str;
85}
86
87#[derive(Debug)]
89pub struct PredicateRouter {
90 routes: RwLock<HashMap<String, RouteWithPredicates>>,
92 sorted_routes: RwLock<Vec<RouteWithPredicates>>,
94 config: Arc<Config>,
96}
97
98#[derive(Debug, Clone)]
100struct RouteWithPredicates {
101 route: Route,
103 predicates: Vec<Arc<dyn Predicate>>,
105 priority: i32,
107}
108
109impl PredicateRouter {
110 pub async fn new(config: Arc<Config>) -> Result<Self, ProxyError> {
112 let router = Self {
113 routes: RwLock::new(HashMap::new()),
114 sorted_routes: RwLock::new(Vec::new()),
115 config,
116 };
117
118 router.load_routes_from_config().await?;
120
121 Ok(router)
122 }
123
124 async fn load_routes_from_config(&self) -> Result<(), ProxyError> {
126 let route_configs: Option<Vec<RouteConfig>> = self.config.get("routes")?;
128
129 if let Some(route_configs) = route_configs {
130 for route_config in route_configs {
132 let mut predicates = Vec::new();
134 for predicate_config in &route_config.predicates {
135 let predicate = PredicateFactory::create_predicate(
136 &predicate_config.type_,
137 predicate_config.config.clone(),
138 )?;
139 predicates.push(predicate);
140 }
141
142 let mut filters = Vec::new();
144 for filter_config in &route_config.filters {
145 let filter = FilterFactory::create_filter(
146 &filter_config.type_,
147 filter_config.config.clone(),
148 )?;
149 filters.push(filter);
150 }
151
152 let path_pattern = route_config.predicates.iter()
154 .find(|p| p.type_ == "path")
155 .map(|p| p.config.get("pattern")
156 .and_then(|v| v.as_str())
157 .unwrap_or("/*"))
158 .unwrap_or("/*")
159 .to_string();
160
161 let route = Route {
162 id: route_config.id.clone(),
163 target_base_url: route_config.target.clone(),
164 path_pattern,
165 filters: if filters.is_empty() { None } else { Some(filters) },
166 };
167
168 self.add_route_with_predicates(
170 route,
171 predicates,
172 route_config.priority,
173 ).await?;
174 }
175 }
176
177 Ok(())
178 }
179
180 async fn add_route_with_predicates(
182 &self,
183 route: Route,
184 predicates: Vec<Arc<dyn Predicate>>,
185 priority: i32,
186 ) -> Result<(), ProxyError> {
187 let route_with_predicates = RouteWithPredicates {
188 route: route.clone(),
189 predicates,
190 priority,
191 };
192
193 {
195 let mut routes = self.routes.write().await;
196 routes.insert(route.id.clone(), route_with_predicates.clone());
197 }
198
199 {
201 let mut sorted_routes = self.sorted_routes.write().await;
202 sorted_routes.push(route_with_predicates);
203
204 sorted_routes.sort_by(|a, b| b.priority.cmp(&a.priority));
206 }
207
208 Ok(())
209 }
210}
211
212#[async_trait]
213impl crate::core::Router for PredicateRouter {
214 async fn route(&self, request: &ProxyRequest) -> Result<Route, ProxyError> {
215 let sorted_routes = self.sorted_routes.read().await;
217
218 for route_with_predicates in sorted_routes.iter() {
219 let mut all_match = true;
221
222 for predicate in &route_with_predicates.predicates {
223 if !predicate.matches(request).await {
224 all_match = false;
225 break;
226 }
227 }
228
229 if all_match {
231 return Ok(route_with_predicates.route.clone());
232 }
233 }
234
235 Err(ProxyError::RoutingError(format!("No route matched the request: {} {}",
237 request.method, request.path)))
238 }
239
240 async fn get_routes(&self) -> Vec<Route> {
241 let routes = self.routes.read().await;
242 routes.values().map(|r| r.route.clone()).collect()
243 }
244
245 async fn add_route(&self, route: Route) -> Result<(), ProxyError> {
246 self.add_route_with_predicates(route, Vec::new(), 0).await
249 }
250
251 async fn remove_route(&self, route_id: &str) -> Result<(), ProxyError> {
252 {
254 let mut routes = self.routes.write().await;
255 if routes.remove(route_id).is_none() {
256 return Err(ProxyError::RoutingError(format!("Route not found: {}", route_id)));
257 }
258 }
259
260 {
262 let mut sorted_routes = self.sorted_routes.write().await;
263 sorted_routes.retain(|r| r.route.id != route_id);
264 }
265
266 Ok(())
267 }
268}
269
270#[derive(Debug)]
272pub struct PredicateFactory;
273
274impl PredicateFactory {
275 pub fn create_predicate(
277 predicate_type: &str,
278 config: serde_json::Value,
279 ) -> Result<Arc<dyn Predicate>, ProxyError> {
280 match predicate_type {
281 "path" => {
282 let path_config: PathPredicateConfig = serde_json::from_value(config)
283 .map_err(|e| ProxyError::RoutingError(
284 format!("Invalid path predicate config: {}", e)
285 ))?;
286 Ok(Arc::new(PathPredicate::new(path_config)))
287 },
288 "method" => {
289 let method_config: MethodPredicateConfig = serde_json::from_value(config)
290 .map_err(|e| ProxyError::RoutingError(
291 format!("Invalid method predicate config: {}", e)
292 ))?;
293 Ok(Arc::new(MethodPredicate::new(method_config)))
294 },
295 "header" => {
296 let header_config: HeaderPredicateConfig = serde_json::from_value(config)
297 .map_err(|e| ProxyError::RoutingError(
298 format!("Invalid header predicate config: {}", e)
299 ))?;
300 Ok(Arc::new(HeaderPredicate::new(header_config)))
301 },
302 "query" => {
303 let query_config: QueryPredicateConfig = serde_json::from_value(config)
304 .map_err(|e| ProxyError::RoutingError(
305 format!("Invalid query predicate config: {}", e)
306 ))?;
307 Ok(Arc::new(QueryPredicate::new(query_config)))
308 },
309 _ => Err(ProxyError::RoutingError(
310 format!("Unknown predicate type: {}", predicate_type)
311 )),
312 }
313 }
314}