From 6110de3b8da6f1818eb3cd92e2c571dc76b7cf5b Mon Sep 17 00:00:00 2001 From: Eloi DEMOLIS Date: Sat, 21 Dec 2024 00:41:20 +0100 Subject: [PATCH] PoC authentication Signed-off-by: Eloi DEMOLIS --- bin/src/ctl/request_builder.rs | 2 + command/src/command.proto | 17 ++-- command/src/config.rs | 11 +++ command/src/request.rs | 1 + command/src/response.rs | 2 + lib/src/http.rs | 12 ++- lib/src/https.rs | 16 ++-- lib/src/protocol/kawa_h1/editor.rs | 11 ++- lib/src/protocol/kawa_h1/mod.rs | 94 +++++++++++++-------- lib/src/router/mod.rs | 130 ++++++++++++++++++----------- 10 files changed, 185 insertions(+), 111 deletions(-) diff --git a/bin/src/ctl/request_builder.rs b/bin/src/ctl/request_builder.rs index dd7764b5e..2dbd58727 100644 --- a/bin/src/ctl/request_builder.rs +++ b/bin/src/ctl/request_builder.rs @@ -250,6 +250,7 @@ impl CommandManager { Some(tags) => tags, None => BTreeMap::new(), }, + required_auth: todo!(), redirect: todo!(), redirect_scheme: todo!(), redirect_template: todo!(), @@ -304,6 +305,7 @@ impl CommandManager { Some(tags) => tags, None => BTreeMap::new(), }, + required_auth: todo!(), redirect: todo!(), redirect_scheme: todo!(), redirect_template: todo!(), diff --git a/command/src/command.proto b/command/src/command.proto index d89a60275..d929e0ba1 100644 --- a/command/src/command.proto +++ b/command/src/command.proto @@ -214,9 +214,8 @@ message ListenersList { enum RedirectPolicy { FORWARD = 0; - TEMPORARY = 1; - PERMANENT = 2; - UNAUTHORIZED = 3; + PERMANENT = 1; + UNAUTHORIZED = 2; } enum RedirectScheme { @@ -236,11 +235,12 @@ message RequestHttpFrontend { // custom tags to identify the frontend in the access logs map tags = 7; optional RedirectPolicy redirect = 8; - optional RedirectScheme redirect_scheme = 9; - optional string redirect_template = 10; - optional string rewrite_host = 11; - optional string rewrite_path = 12; - optional uint32 rewrite_port = 13; + optional bool required_auth = 9; + optional RedirectScheme redirect_scheme = 10; + optional string redirect_template = 11; + optional string rewrite_host = 12; + optional string rewrite_path = 13; + optional uint32 rewrite_port = 14; } message RequestTcpFrontend { @@ -371,6 +371,7 @@ message Cluster { optional LoadMetric load_metric = 7; optional uint32 https_redirect_port = 8; map answers = 9; + repeated uint64 authorized_hashes = 10; } enum LoadBalancingAlgorithms { diff --git a/command/src/config.rs b/command/src/config.rs index b4027fe7d..dc7290361 100644 --- a/command/src/config.rs +++ b/command/src/config.rs @@ -625,6 +625,7 @@ pub struct FileClusterFrontendConfig { #[serde(default)] pub position: RulePosition, pub tags: Option>, + pub required_auth: Option, pub redirect: Option, pub redirect_scheme: Option, pub redirect_template: Option, @@ -716,6 +717,7 @@ impl FileClusterFrontendConfig { path, method: self.method.clone(), tags: self.tags.clone(), + required_auth: self.required_auth.unwrap_or(false), redirect: self.redirect, redirect_scheme: self.redirect_scheme, redirect_template: self.redirect_template.clone(), @@ -758,6 +760,8 @@ pub struct FileClusterConfig { pub load_metric: Option, #[serde(default)] pub answers: Option>, + #[serde(default)] + pub authorized_hashes: Vec, } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -845,6 +849,7 @@ impl FileClusterConfig { load_balancing: self.load_balancing, load_metric: self.load_metric, answers: load_answers(self.answers.as_ref())?, + authorized_hashes: self.authorized_hashes, })) } } @@ -866,6 +871,7 @@ pub struct HttpFrontendConfig { #[serde(default)] pub position: RulePosition, pub tags: Option>, + pub required_auth: bool, pub redirect: Option, pub redirect_scheme: Option, pub redirect_template: Option, @@ -909,6 +915,7 @@ impl HttpFrontendConfig { method: self.method.clone(), position: self.position.into(), tags, + required_auth: Some(self.required_auth), redirect: self.redirect.map(Into::into), redirect_scheme: self.redirect_scheme.map(Into::into), redirect_template: self.redirect_template.clone(), @@ -929,6 +936,7 @@ impl HttpFrontendConfig { method: self.method.clone(), position: self.position.into(), tags, + required_auth: Some(self.required_auth), redirect: self.redirect.map(Into::into), redirect_scheme: self.redirect_scheme.map(Into::into), redirect_template: self.redirect_template.clone(), @@ -956,6 +964,7 @@ pub struct HttpClusterConfig { pub load_balancing: LoadBalancingAlgorithms, pub load_metric: Option, pub answers: BTreeMap, + pub authorized_hashes: Vec, } impl HttpClusterConfig { @@ -969,6 +978,7 @@ impl HttpClusterConfig { load_balancing: self.load_balancing as i32, load_metric: self.load_metric.map(|s| s as i32), answers: self.answers.clone(), + authorized_hashes: self.authorized_hashes.clone(), }) .into()]; @@ -1029,6 +1039,7 @@ impl TcpClusterConfig { load_balancing: self.load_balancing as i32, load_metric: self.load_metric.map(|s| s as i32), answers: Default::default(), + authorized_hashes: Default::default(), }) .into()]; diff --git a/command/src/request.rs b/command/src/request.rs index f40938ae8..d70b1b8fb 100644 --- a/command/src/request.rs +++ b/command/src/request.rs @@ -161,6 +161,7 @@ impl RequestHttpFrontend { pub fn to_frontend(self) -> Result { Ok(HttpFrontend { position: self.position(), + required_auth: self.required_auth.unwrap_or(false), redirect: self.redirect(), redirect_scheme: self.redirect_scheme(), redirect_template: self.redirect_template, diff --git a/command/src/response.rs b/command/src/response.rs index 2883b3794..777347420 100644 --- a/command/src/response.rs +++ b/command/src/response.rs @@ -39,6 +39,7 @@ pub struct HttpFrontend { #[serde(default)] pub position: RulePosition, pub tags: Option>, + pub required_auth: bool, pub redirect: RedirectPolicy, pub redirect_scheme: RedirectScheme, #[serde(skip_serializing_if = "Option::is_none")] @@ -61,6 +62,7 @@ impl From for RequestHttpFrontend { method: val.method, position: val.position.into(), tags: val.tags.unwrap_or_default(), + required_auth: Some(val.required_auth), redirect: Some(val.redirect.into()), redirect_scheme: Some(val.redirect_scheme.into()), redirect_template: val.redirect_template, diff --git a/lib/src/http.rs b/lib/src/http.rs index ce7104d55..a430c1f17 100644 --- a/lib/src/http.rs +++ b/lib/src/http.rs @@ -1284,6 +1284,7 @@ mod tests { path: PathRule::prefix(uri1), position: RulePosition::Tree, cluster_id: Some(cluster_id1), + required_auth: false, redirect: RedirectPolicy::Forward, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -1301,6 +1302,7 @@ mod tests { path: PathRule::prefix(uri2), position: RulePosition::Tree, cluster_id: Some(cluster_id2), + required_auth: false, redirect: RedirectPolicy::Forward, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -1318,6 +1320,7 @@ mod tests { path: PathRule::prefix(uri3), position: RulePosition::Tree, cluster_id: Some(cluster_id3), + required_auth: false, redirect: RedirectPolicy::Forward, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -1335,6 +1338,7 @@ mod tests { path: PathRule::prefix("/test".to_owned()), position: RulePosition::Tree, cluster_id: Some("cluster_1".to_owned()), + required_auth: false, redirect: RedirectPolicy::Forward, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -1369,19 +1373,19 @@ mod tests { let frontend5 = listener.frontend_from_request("domain", "/", &Method::Get); assert_eq!( frontend1.expect("should find frontend"), - RouteResult::simple("cluster_1".to_string()) + RouteResult::forward("cluster_1".to_string()) ); assert_eq!( frontend2.expect("should find frontend"), - RouteResult::simple("cluster_1".to_string()) + RouteResult::forward("cluster_1".to_string()) ); assert_eq!( frontend3.expect("should find frontend"), - RouteResult::simple("cluster_2".to_string()) + RouteResult::forward("cluster_2".to_string()) ); assert_eq!( frontend4.expect("should find frontend"), - RouteResult::simple("cluster_3".to_string()) + RouteResult::forward("cluster_3".to_string()) ); assert!(frontend5.is_err()); } diff --git a/lib/src/https.rs b/lib/src/https.rs index c9781c3c6..abaf162c0 100644 --- a/lib/src/https.rs +++ b/lib/src/https.rs @@ -1504,25 +1504,25 @@ mod tests { "lolcatho.st".as_bytes(), &PathRule::Prefix(uri1), &MethodRule::new(None), - &Route::simple(cluster_id1.clone()) + &Route::forward(cluster_id1.clone()) )); assert!(fronts.add_tree_rule( "lolcatho.st".as_bytes(), &PathRule::Prefix(uri2), &MethodRule::new(None), - &Route::simple(cluster_id2) + &Route::forward(cluster_id2) )); assert!(fronts.add_tree_rule( "lolcatho.st".as_bytes(), &PathRule::Prefix(uri3), &MethodRule::new(None), - &Route::simple(cluster_id3) + &Route::forward(cluster_id3) )); assert!(fronts.add_tree_rule( "other.domain".as_bytes(), &PathRule::Prefix("test".to_string()), &MethodRule::new(None), - &Route::simple(cluster_id1) + &Route::forward(cluster_id1) )); let address = SocketAddress::new_v4(127, 0, 0, 1, 1032); @@ -1561,25 +1561,25 @@ mod tests { let frontend1 = listener.frontend_from_request("lolcatho.st", "/", &Method::Get); assert_eq!( frontend1.expect("should find a frontend"), - RouteResult::simple("cluster_1".to_string()) + RouteResult::forward("cluster_1".to_string()) ); println!("TEST {}", line!()); let frontend2 = listener.frontend_from_request("lolcatho.st", "/test", &Method::Get); assert_eq!( frontend2.expect("should find a frontend"), - RouteResult::simple("cluster_1".to_string()) + RouteResult::forward("cluster_1".to_string()) ); println!("TEST {}", line!()); let frontend3 = listener.frontend_from_request("lolcatho.st", "/yolo/test", &Method::Get); assert_eq!( frontend3.expect("should find a frontend"), - RouteResult::simple("cluster_2".to_string()) + RouteResult::forward("cluster_2".to_string()) ); println!("TEST {}", line!()); let frontend4 = listener.frontend_from_request("lolcatho.st", "/yolo/swag", &Method::Get); assert_eq!( frontend4.expect("should find a frontend"), - RouteResult::simple("cluster_3".to_string()) + RouteResult::forward("cluster_3".to_string()) ); println!("TEST {}", line!()); let frontend5 = listener.frontend_from_request("domain", "/", &Method::Get); diff --git a/lib/src/protocol/kawa_h1/editor.rs b/lib/src/protocol/kawa_h1/editor.rs index 7c72ce598..7f6f6a2c1 100644 --- a/lib/src/protocol/kawa_h1/editor.rs +++ b/lib/src/protocol/kawa_h1/editor.rs @@ -1,4 +1,5 @@ use std::{ + hash::{DefaultHasher, Hash, Hasher}, net::{IpAddr, SocketAddr}, str::{from_utf8, from_utf8_unchecked}, }; @@ -24,7 +25,7 @@ pub struct HttpContext { /// the value of the sticky session cookie in the request pub sticky_session_found: Option, /// position of the last authentication header, only valid until prepare is called - pub authentication_found: Option, + pub authentication_found: Option, // ---------- Status Line /// the value of the method in the request line pub method: Option, @@ -137,7 +138,7 @@ impl HttpContext { let mut has_x_port = false; let mut has_x_proto = false; let mut has_connection = false; - for (i, block) in request.blocks.iter_mut().enumerate() { + for block in &mut request.blocks { match block { kawa::Block::Header(header) if !header.is_elided() => { let key = header.key.data(buf); @@ -185,7 +186,11 @@ impl HttpContext { .and_then(|data| from_utf8(data).ok()) .map(ToOwned::to_owned); } else if compare_no_case(key, b"Proxy-Authenticate") { - self.authentication_found = Some(i); + self.authentication_found = header.val.data_opt(buf).map(|auth| { + let mut h = DefaultHasher::new(); + auth.hash(&mut h); + h.finish() + }); } } _ => {} diff --git a/lib/src/protocol/kawa_h1/mod.rs b/lib/src/protocol/kawa_h1/mod.rs index b95baeb1b..efbd10b12 100644 --- a/lib/src/protocol/kawa_h1/mod.rs +++ b/lib/src/protocol/kawa_h1/mod.rs @@ -20,7 +20,6 @@ use sozu_command::{ logging::EndpointRecord, proto::command::{Event, EventKind, ListenerType, RedirectPolicy, RedirectScheme}, }; -// use time::{Duration, Instant}; use crate::{ backends::{Backend, BackendError}, @@ -116,8 +115,8 @@ pub enum DefaultAnswer { duration: String, }, Answer507 { - phase: kawa::ParsingPhaseMarker, message: String, + phase: kawa::ParsingPhaseMarker, capacity: usize, }, } @@ -1024,8 +1023,8 @@ impl Http Http Http "https", }; - match (cluster_id, redirect, redirect_template) { - (_, RedirectPolicy::Unauthorized, _) | (None, RedirectPolicy::Forward, None) => { - self.set_answer(DefaultAnswer::Answer401 {}); - return Err(RetrieveClusterError::UnauthorizedRoute); - } - (_, RedirectPolicy::Permanent, _) => { - self.set_answer(DefaultAnswer::Answer301 { - location: format!("{proto}://{host}{port}{path}"), - }); + let (authorized, https_redirect, https_redirect_port) = + match (&cluster_id, redirect, &redirect_template, required_auth) { + // unauthorized frontends + (_, RedirectPolicy::Unauthorized, _, _) => (false, false, None), + // forward frontends with no target (no cluster nor template) + (None, RedirectPolicy::Forward, None, _) => (false, false, None), + // clusterless frontend with auth (unsupported) + (None, _, _, true) => (false, false, None), + // clusterless frontends + (None, _, _, false) => (true, false, None), + // "attached" frontends + (Some(cluster_id), _, _, _) => { + proxy.borrow().clusters().get(cluster_id).map_or( + (false, false, None), // cluster not found, consider unauthorized + |cluster| { + let authorized = + match (required_auth, self.context.authentication_found) { + // auth not required + (false, _) => true, + // no auth found + (true, None) => false, + // validation + (true, Some(hash)) => { + println!("{hash:?}"); + cluster.authorized_hashes.contains(&hash) + } + }; + ( + authorized, + cluster.https_redirect, + cluster.https_redirect_port, + ) + }, + ) + } + }; + + match (cluster_id, redirect, redirect_template, authorized) { + (cluster_id, RedirectPolicy::Permanent, _, true) => { + let location = format!("{proto}://{host}{port}{path}"); + self.context.cluster_id = cluster_id; + self.set_answer(DefaultAnswer::Answer301 { location }); Err(RetrieveClusterError::Redirected) } - (_, RedirectPolicy::Temporary, _) => todo!(), - (cluster_id, RedirectPolicy::Forward, Some(name)) => { + (cluster_id, RedirectPolicy::Forward, Some(name), true) => { let location = format!("{proto}://{host}{port}{path}"); - // TODO: this feels wrong self.context.cluster_id = cluster_id; self.set_answer(DefaultAnswer::AnswerCustom { name, location }); Err(RetrieveClusterError::Redirected) } - (Some(cluster_id), RedirectPolicy::Forward, None) => { - let (https_redirect, https_redirect_port, authentication) = proxy - .borrow() - .clusters() - .get(&cluster_id) - .map(|cluster| { - ( - cluster.https_redirect, - cluster.https_redirect_port, - None::<()>, - ) - }) - .unwrap_or((false, None, None)); + (Some(cluster_id), RedirectPolicy::Forward, None, true) => { if !is_https && https_redirect { let port = rewritten_port .or_else(|| https_redirect_port.map(|port| port as u16)) .map_or(String::new(), |port| format!(":{port}")); - self.set_answer(DefaultAnswer::Answer301 { - location: format!("https://{host}{port}{path}"), - }); + let location = format!("https://{host}{port}{path}"); + self.context.cluster_id = Some(cluster_id); + self.set_answer(DefaultAnswer::Answer301 { location }); return Err(RetrieveClusterError::Redirected); } - if let Some(authentication) = authentication { - self.set_answer(DefaultAnswer::Answer401 {}); - return Err(RetrieveClusterError::UnauthorizedRoute); - } - return Ok(cluster_id); + Ok(cluster_id) + } + (cluster_id, ..) => { + self.context.cluster_id = cluster_id; + self.set_answer(DefaultAnswer::Answer401 {}); + Err(RetrieveClusterError::UnauthorizedRoute) } } } diff --git a/lib/src/router/mod.rs b/lib/src/router/mod.rs index 6d798f3b7..e4c752cde 100644 --- a/lib/src/router/mod.rs +++ b/lib/src/router/mod.rs @@ -171,6 +171,7 @@ impl Router { front.cluster_id.clone(), &domain_rule, &path_rule, + front.required_auth, front.redirect, front.redirect_scheme, front.redirect_template.clone(), @@ -724,6 +725,7 @@ impl RewriteParts { #[derive(Debug, Clone)] pub struct Route { cluster_id: Option, + required_auth: bool, redirect: RedirectPolicy, redirect_scheme: RedirectScheme, redirect_template: Option, @@ -739,6 +741,7 @@ impl Route { cluster_id: Option, domain_rule: &DomainRule, path_rule: &PathRule, + required_auth: bool, redirect: RedirectPolicy, redirect_scheme: RedirectScheme, redirect_template: Option, @@ -746,22 +749,39 @@ impl Route { rewrite_path: Option, rewrite_port: Option, ) -> Result { - match (&cluster_id, redirect, &redirect_template) { - (None, RedirectPolicy::Forward, None) | (_, RedirectPolicy::Unauthorized, _) => { - return Ok(Self { - cluster_id, - redirect: RedirectPolicy::Unauthorized, - redirect_scheme, - redirect_template: None, - capture_cap_host: 0, - capture_cap_path: 0, - rewrite_host: None, - rewrite_path: None, - rewrite_port: None, - }) + let deny = match (&cluster_id, redirect, &redirect_template, required_auth) { + (_, RedirectPolicy::Unauthorized, _, false) => true, + (_, RedirectPolicy::Unauthorized, _, true) => { + warn!("Frontend[cluster: {:?}, domain: {:?}, path: {:?}, redirect: {:?}]: unauthorized frontends ignore auth", cluster_id, domain_rule, path_rule, redirect); + true + } + (None, RedirectPolicy::Forward, None, _) => { + warn!("Frontend[domain: {:?}, path: {:?}]: forward on clusterless frontends are unauthorized", domain_rule, path_rule); + true + } + (None, _, _, true) => { + warn!( + "Frontend[domain: {:?}, path: {:?}]: clusterless frontends ignore auth", + domain_rule, path_rule + ); + true } - _ => {} + _ => false, }; + if deny { + return Ok(Self { + cluster_id, + required_auth, + redirect: RedirectPolicy::Unauthorized, + redirect_scheme, + redirect_template: None, + capture_cap_host: 0, + capture_cap_path: 0, + rewrite_host: None, + rewrite_path: None, + rewrite_port: None, + }); + } let mut capture_cap_host = match domain_rule { DomainRule::Any => 1, DomainRule::Equals(_) => 1, @@ -811,6 +831,7 @@ impl Route { } Ok(Route { cluster_id, + required_auth, redirect, redirect_scheme, redirect_template, @@ -823,9 +844,10 @@ impl Route { } #[cfg(test)] - pub fn simple(cluster_id: ClusterId) -> Self { + pub fn forward(cluster_id: ClusterId) -> Self { Self { cluster_id: Some(cluster_id), + required_auth: false, redirect: RedirectPolicy::Forward, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -841,6 +863,7 @@ impl Route { #[derive(Debug, Clone, PartialEq, Eq)] pub struct RouteResult { pub cluster_id: Option, + pub required_auth: bool, pub redirect: RedirectPolicy, pub redirect_scheme: RedirectScheme, pub redirect_template: Option, @@ -853,6 +876,7 @@ impl RouteResult { fn deny(cluster_id: &Option) -> Self { Self { cluster_id: cluster_id.clone(), + required_auth: false, redirect: RedirectPolicy::Unauthorized, redirect_scheme: RedirectScheme::UseSame, redirect_template: None, @@ -861,6 +885,21 @@ impl RouteResult { rewritten_port: None, } } + + #[cfg(test)] + pub fn forward(cluster_id: ClusterId) -> Self { + Self { + cluster_id: Some(cluster_id), + required_auth: false, + redirect: RedirectPolicy::Forward, + redirect_scheme: RedirectScheme::UseSame, + redirect_template: None, + rewritten_host: None, + rewritten_path: None, + rewritten_port: None, + } + } + fn new<'a>( captures_host: Vec<&'a str>, path: &'a [u8], @@ -869,6 +908,7 @@ impl RouteResult { ) -> Self { let Route { cluster_id, + required_auth, redirect, redirect_scheme, redirect_template, @@ -899,6 +939,7 @@ impl RouteResult { println!("========PATH_CAPTURES: {captures_path:?}"); Self { cluster_id: cluster_id.clone(), + required_auth: *required_auth, redirect: *redirect, redirect_scheme: *redirect_scheme, redirect_template: redirect_template.clone(), @@ -983,19 +1024,6 @@ impl RouteResult { } Self::new(captures_host, path, path_rule, route) } - - #[cfg(test)] - pub fn simple(cluster_id: ClusterId) -> Self { - Self { - cluster_id: Some(cluster_id), - redirect: RedirectPolicy::Forward, - redirect_scheme: RedirectScheme::UseSame, - redirect_template: None, - rewritten_host: None, - rewritten_path: None, - rewritten_port: None, - } - } } #[cfg(test)] @@ -1114,27 +1142,27 @@ mod tests { b"*.sozu.io", &PathRule::Prefix("".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("base".to_string()) + &Route::forward("base".to_string()) )); println!("{:#?}", router.tree); assert_eq!( router.lookup("www.sozu.io", "/api", &Method::Get), - Ok(RouteResult::simple("base".to_string())) + Ok(RouteResult::forward("base".to_string())) ); assert!(router.add_tree_rule( b"*.sozu.io", &PathRule::Prefix("/api".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("api".to_string()) + &Route::forward("api".to_string()) )); println!("{:#?}", router.tree); assert_eq!( router.lookup("www.sozu.io", "/ap", &Method::Get), - Ok(RouteResult::simple("base".to_string())) + Ok(RouteResult::forward("base".to_string())) ); assert_eq!( router.lookup("www.sozu.io", "/api", &Method::Get), - Ok(RouteResult::simple("api".to_string())) + Ok(RouteResult::forward("api".to_string())) ); } @@ -1153,27 +1181,27 @@ mod tests { b"*.sozu.io", &PathRule::Prefix("".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("base".to_string()) + &Route::forward("base".to_string()) )); println!("{:#?}", router.tree); assert_eq!( router.lookup("www.sozu.io", "/api", &Method::Get), - Ok(RouteResult::simple("base".to_string())) + Ok(RouteResult::forward("base".to_string())) ); assert!(router.add_tree_rule( b"api.sozu.io", &PathRule::Prefix("".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("api".to_string()) + &Route::forward("api".to_string()) )); println!("{:#?}", router.tree); assert_eq!( router.lookup("www.sozu.io", "/api", &Method::Get), - Ok(RouteResult::simple("base".to_string())) + Ok(RouteResult::forward("base".to_string())) ); assert_eq!( router.lookup("api.sozu.io", "/api", &Method::Get), - Ok(RouteResult::simple("api".to_string())) + Ok(RouteResult::forward("api".to_string())) ); } @@ -1185,23 +1213,23 @@ mod tests { b"www./.*/.io", &PathRule::Prefix("".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("base".to_string()) + &Route::forward("base".to_string()) )); println!("{:#?}", router.tree); assert!(router.add_tree_rule( b"www.doc./.*/.io", &PathRule::Prefix("".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("doc".to_string()) + &Route::forward("doc".to_string()) )); println!("{:#?}", router.tree); assert_eq!( router.lookup("www.sozu.io", "/", &Method::Get), - Ok(RouteResult::simple("base".to_string())) + Ok(RouteResult::forward("base".to_string())) ); assert_eq!( router.lookup("www.doc.sozu.io", "/", &Method::Get), - Ok(RouteResult::simple("doc".to_string())) + Ok(RouteResult::forward("doc".to_string())) ); assert!(router.remove_tree_rule( b"www./.*/.io", @@ -1212,7 +1240,7 @@ mod tests { assert!(router.lookup("www.sozu.io", "/", &Method::Get).is_err()); assert_eq!( router.lookup("www.doc.sozu.io", "/", &Method::Get), - Ok(RouteResult::simple("doc".to_string())) + Ok(RouteResult::forward("doc".to_string())) ); } @@ -1224,30 +1252,30 @@ mod tests { &"*".parse::().unwrap(), &PathRule::Prefix("/.well-known/acme-challenge".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("acme".to_string()) + &Route::forward("acme".to_string()) )); assert!(router.add_tree_rule( "www.example.com".as_bytes(), &PathRule::Prefix("/".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("example".to_string()) + &Route::forward("example".to_string()) )); assert!(router.add_tree_rule( "*.test.example.com".as_bytes(), &PathRule::Regex(Regex::new("/hello[A-Z]+/").unwrap()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("examplewildcard".to_string()) + &Route::forward("examplewildcard".to_string()) )); assert!(router.add_tree_rule( "/test[0-9]/.example.com".as_bytes(), &PathRule::Prefix("/".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::simple("exampleregex".to_string()) + &Route::forward("exampleregex".to_string()) )); assert_eq!( router.lookup("www.example.com", "/helloA", &Method::new(&b"GET"[..])), - Ok(RouteResult::simple("example".to_string())) + Ok(RouteResult::forward("example".to_string())) ); assert_eq!( router.lookup( @@ -1255,7 +1283,7 @@ mod tests { "/.well-known/acme-challenge", &Method::new(&b"GET"[..]) ), - Ok(RouteResult::simple("acme".to_string())) + Ok(RouteResult::forward("acme".to_string())) ); assert!(router .lookup("www.test.example.com", "/", &Method::new(&b"GET"[..])) @@ -1266,11 +1294,11 @@ mod tests { "/helloAB/", &Method::new(&b"GET"[..]) ), - Ok(RouteResult::simple("examplewildcard".to_string())) + Ok(RouteResult::forward("examplewildcard".to_string())) ); assert_eq!( router.lookup("test1.example.com", "/helloAB/", &Method::new(&b"GET"[..])), - Ok(RouteResult::simple("exampleregex".to_string())) + Ok(RouteResult::forward("exampleregex".to_string())) ); } }