diff --git a/bin/src/cli.rs b/bin/src/cli.rs index 454dc9dbd..c529b9ac1 100644 --- a/bin/src/cli.rs +++ b/bin/src/cli.rs @@ -454,6 +454,8 @@ pub enum HttpFrontendCmd { method: Option, #[clap(long = "tags", help = "Specify tag (key-value pair) to apply on front-end (example: 'key=value, other-key=other-value')", value_parser = parse_tags)] tags: Option>, + #[clap(help = "the frontend uses http2 with prio-knowledge")] + h2: Option, }, #[clap(name = "remove")] Remove { diff --git a/bin/src/ctl/command.rs b/bin/src/ctl/command.rs index d291b1e3f..a96aea86b 100644 --- a/bin/src/ctl/command.rs +++ b/bin/src/ctl/command.rs @@ -434,7 +434,7 @@ impl CommandManager { if let Some(response_content) = response.content { let certs = match response_content.content_type { Some(ContentType::CertificatesWithFingerprints(certs)) => certs.certs, - _ => bail!(format!("Wrong response content {:?}", response_content)), + _ => bail!(format!("Wrong response content {response_content:?}")), }; if certs.is_empty() { bail!("No certificates match your request."); diff --git a/bin/src/ctl/display.rs b/bin/src/ctl/display.rs index ba33ebe4e..07531af0e 100644 --- a/bin/src/ctl/display.rs +++ b/bin/src/ctl/display.rs @@ -609,7 +609,7 @@ pub fn print_cluster_responses( clusters_table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS); let mut header = vec![cell!("cluster id")]; for worker_id in worker_responses.map.keys() { - header.push(cell!(format!("worker {}", worker_id))); + header.push(cell!(format!("worker {worker_id}"))); } header.push(cell!("desynchronized")); clusters_table.add_row(Row::new(header)); @@ -657,14 +657,14 @@ pub fn print_certificates_by_worker( } for (worker_id, response_content) in response_contents.iter() { - println!("Worker {}", worker_id); + println!("Worker {worker_id}"); match &response_content.content_type { Some(ContentType::CertificatesByAddress(list)) => { for certs in list.certificates.iter() { println!("\t{}:", certs.address); for summary in certs.certificate_summaries.iter() { - println!("\t\t{}", summary); + println!("\t\t{summary}"); } println!(); diff --git a/bin/src/ctl/request_builder.rs b/bin/src/ctl/request_builder.rs index 64afc4274..253cc1b5c 100644 --- a/bin/src/ctl/request_builder.rs +++ b/bin/src/ctl/request_builder.rs @@ -202,6 +202,7 @@ impl CommandManager { method, cluster_id: route, tags, + h2, } => self.send_request( RequestType::AddHttpFrontend(RequestHttpFrontend { cluster_id: route.into(), @@ -214,6 +215,7 @@ impl CommandManager { Some(tags) => tags, None => BTreeMap::new(), }, + h2: h2.unwrap_or(false), }) .into(), ), @@ -250,6 +252,7 @@ impl CommandManager { method, cluster_id: route, tags, + h2, } => self.send_request( RequestType::AddHttpsFrontend(RequestHttpFrontend { cluster_id: route.into(), @@ -262,6 +265,7 @@ impl CommandManager { Some(tags) => tags, None => BTreeMap::new(), }, + h2: h2.unwrap_or(false), }) .into(), ), diff --git a/command/src/command.proto b/command/src/command.proto index a3a7055e3..5d3bcc30f 100644 --- a/command/src/command.proto +++ b/command/src/command.proto @@ -218,6 +218,7 @@ message RequestHttpFrontend { required RulePosition position = 6 [default = TREE]; // custom tags to identify the frontend in the access logs map tags = 7; + required bool h2 = 8; } message RequestTcpFrontend { diff --git a/command/src/config.rs b/command/src/config.rs index c75a1f02d..f59a70872 100644 --- a/command/src/config.rs +++ b/command/src/config.rs @@ -664,6 +664,7 @@ pub struct FileClusterFrontendConfig { #[serde(default)] pub position: RulePosition, pub tags: Option>, + pub h2: Option, } impl FileClusterFrontendConfig { @@ -749,6 +750,7 @@ impl FileClusterFrontendConfig { path, method: self.method.clone(), tags: self.tags.clone(), + h2: self.h2.unwrap_or(false), }) } } @@ -774,6 +776,7 @@ pub struct FileClusterConfig { pub frontends: Vec, pub backends: Vec, pub protocol: FileClusterProtocolConfig, + pub http_version: Option, pub sticky_session: Option, pub https_redirect: Option, #[serde(default)] @@ -899,6 +902,7 @@ pub struct HttpFrontendConfig { #[serde(default)] pub position: RulePosition, pub tags: Option>, + pub h2: bool, } impl HttpFrontendConfig { @@ -934,6 +938,7 @@ impl HttpFrontendConfig { path: self.path.clone(), method: self.method.clone(), position: self.position.into(), + h2: self.h2, tags, }) .into(), @@ -948,6 +953,7 @@ impl HttpFrontendConfig { path: self.path.clone(), method: self.method.clone(), position: self.position.into(), + h2: self.h2, tags, }) .into(), @@ -1269,13 +1275,13 @@ impl ConfigBuilder { Ok(()) } - fn push_http_listener(&mut self, mut listener: ListenerBuilder) -> Result<(), ConfigError> { + fn push_http_listener(&mut self, listener: ListenerBuilder) -> Result<(), ConfigError> { let listener = listener.to_http(Some(&self.built))?; self.built.http_listeners.push(listener); Ok(()) } - fn push_tcp_listener(&mut self, mut listener: ListenerBuilder) -> Result<(), ConfigError> { + fn push_tcp_listener(&mut self, listener: ListenerBuilder) -> Result<(), ConfigError> { let listener = listener.to_tcp(Some(&self.built))?; self.built.tcp_listeners.push(listener); Ok(()) diff --git a/command/src/proto/display.rs b/command/src/proto/display.rs index c21d2a1c5..7f76ae5eb 100644 --- a/command/src/proto/display.rs +++ b/command/src/proto/display.rs @@ -33,9 +33,9 @@ impl Display for CertificateSummary { impl Display for QueryCertificatesFilters { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if let Some(d) = self.domain.clone() { - write!(f, "domain:{}", d) + write!(f, "domain:{d}") } else if let Some(fp) = self.fingerprint.clone() { - write!(f, "domain:{}", fp) + write!(f, "domain:{fp}") } else { write!(f, "all certificates") } diff --git a/command/src/request.rs b/command/src/request.rs index 3e055a332..648ebcff3 100644 --- a/command/src/request.rs +++ b/command/src/request.rs @@ -149,6 +149,7 @@ impl RequestHttpFrontend { value: self.position, })?, tags: Some(self.tags), + h2: self.h2, }) } } diff --git a/command/src/response.rs b/command/src/response.rs index 85b410441..ce43e5baa 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 h2: bool, } impl From for RequestHttpFrontend { @@ -54,6 +55,7 @@ impl From for RequestHttpFrontend { path: val.path, method: val.method, position: val.position.into(), + h2: val.h2, tags, } } diff --git a/command/src/state.rs b/command/src/state.rs index af2e85d72..4ba13e9c5 100644 --- a/command/src/state.rs +++ b/command/src/state.rs @@ -474,7 +474,7 @@ impl ConfigState { if tcp_frontends.contains(&tcp_frontend) { return Err(StateError::Exists { kind: ObjectKind::TcpFrontend, - id: format!("{:?}", tcp_frontend), + id: format!("{tcp_frontend:?}"), }); } @@ -493,7 +493,7 @@ impl ConfigState { .get_mut(&front_to_remove.cluster_id) .ok_or(StateError::NotFound { kind: ObjectKind::TcpFrontend, - id: format!("{:?}", front_to_remove), + id: format!("{front_to_remove:?}"), })?; let len = tcp_frontends.len(); diff --git a/lib/src/http.rs b/lib/src/http.rs index 05ffaa244..85c119622 100644 --- a/lib/src/http.rs +++ b/lib/src/http.rs @@ -667,7 +667,7 @@ impl HttpProxy { if !socket_errors.is_empty() { return Err(ProxyError::SoftStop { proxy_protocol: "HTTP".to_string(), - error: format!("Error deregistering listen sockets: {:?}", socket_errors), + error: format!("Error deregistering listen sockets: {socket_errors:?}"), }); } @@ -690,7 +690,7 @@ impl HttpProxy { if !socket_errors.is_empty() { return Err(ProxyError::HardStop { proxy_protocol: "HTTP".to_string(), - error: format!("Error deregistering listen sockets: {:?}", socket_errors), + error: format!("Error deregistering listen sockets: {socket_errors:?}"), }); } @@ -1463,6 +1463,7 @@ mod tests { position: RulePosition::Tree, cluster_id: Some(cluster_id1), tags: None, + h2: false, }) .expect("Could not add http frontend"); fronts @@ -1474,6 +1475,7 @@ mod tests { position: RulePosition::Tree, cluster_id: Some(cluster_id2), tags: None, + h2: false, }) .expect("Could not add http frontend"); fronts @@ -1485,6 +1487,7 @@ mod tests { position: RulePosition::Tree, cluster_id: Some(cluster_id3), tags: None, + h2: false, }) .expect("Could not add http frontend"); fronts @@ -1496,6 +1499,7 @@ mod tests { position: RulePosition::Tree, cluster_id: Some("cluster_1".to_owned()), tags: None, + h2: false, }) .expect("Could not add http frontend"); @@ -1527,19 +1531,31 @@ mod tests { let frontend5 = listener.frontend_from_request("domain", "/", &Method::Get); assert_eq!( frontend1.expect("should find frontend"), - Route::ClusterId("cluster_1".to_string()) + Route::Cluster { + id: "cluster_1".to_string(), + h2: false + } ); assert_eq!( frontend2.expect("should find frontend"), - Route::ClusterId("cluster_1".to_string()) + Route::Cluster { + id: "cluster_1".to_string(), + h2: false + } ); assert_eq!( frontend3.expect("should find frontend"), - Route::ClusterId("cluster_2".to_string()) + Route::Cluster { + id: "cluster_2".to_string(), + h2: false + } ); assert_eq!( frontend4.expect("should find frontend"), - Route::ClusterId("cluster_3".to_string()) + Route::Cluster { + id: "cluster_3".to_string(), + h2: false + } ); assert!(frontend5.is_err()); } diff --git a/lib/src/https.rs b/lib/src/https.rs index 6a54b7bcd..7195af71d 100644 --- a/lib/src/https.rs +++ b/lib/src/https.rs @@ -876,7 +876,7 @@ impl HttpsProxy { if !socket_errors.is_empty() { return Err(ProxyError::SoftStop { proxy_protocol: "HTTPS".to_string(), - error: format!("Error deregistering listen sockets: {:?}", socket_errors), + error: format!("Error deregistering listen sockets: {socket_errors:?}"), }); } @@ -899,7 +899,7 @@ impl HttpsProxy { if !socket_errors.is_empty() { return Err(ProxyError::HardStop { proxy_protocol: "HTTPS".to_string(), - error: format!("Error deregistering listen sockets: {:?}", socket_errors), + error: format!("Error deregistering listen sockets: {socket_errors:?}"), }); } @@ -1623,25 +1623,37 @@ mod tests { "lolcatho.st".as_bytes(), &PathRule::Prefix(uri1), &MethodRule::new(None), - &Route::ClusterId(cluster_id1.clone()) + &Route::Cluster { + id: cluster_id1.clone(), + h2: false + } )); assert!(fronts.add_tree_rule( "lolcatho.st".as_bytes(), &PathRule::Prefix(uri2), &MethodRule::new(None), - &Route::ClusterId(cluster_id2) + &Route::Cluster { + id: cluster_id2, + h2: false + } )); assert!(fronts.add_tree_rule( "lolcatho.st".as_bytes(), &PathRule::Prefix(uri3), &MethodRule::new(None), - &Route::ClusterId(cluster_id3) + &Route::Cluster { + id: cluster_id3, + h2: false + } )); assert!(fronts.add_tree_rule( "other.domain".as_bytes(), &PathRule::Prefix("test".to_string()), &MethodRule::new(None), - &Route::ClusterId(cluster_id1) + &Route::Cluster { + id: cluster_id1, + h2: false + } )); let address: StdSocketAddr = FromStr::from_str("127.0.0.1:1032") @@ -1683,25 +1695,37 @@ mod tests { let frontend1 = listener.frontend_from_request("lolcatho.st", "/", &Method::Get); assert_eq!( frontend1.expect("should find a frontend"), - Route::ClusterId("cluster_1".to_string()) + Route::Cluster { + id: "cluster_1".to_string(), + h2: false + } ); println!("TEST {}", line!()); let frontend2 = listener.frontend_from_request("lolcatho.st", "/test", &Method::Get); assert_eq!( frontend2.expect("should find a frontend"), - Route::ClusterId("cluster_1".to_string()) + Route::Cluster { + id: "cluster_1".to_string(), + h2: false + } ); println!("TEST {}", line!()); let frontend3 = listener.frontend_from_request("lolcatho.st", "/yolo/test", &Method::Get); assert_eq!( frontend3.expect("should find a frontend"), - Route::ClusterId("cluster_2".to_string()) + Route::Cluster { + id: "cluster_2".to_string(), + h2: false + } ); println!("TEST {}", line!()); let frontend4 = listener.frontend_from_request("lolcatho.st", "/yolo/swag", &Method::Get); assert_eq!( frontend4.expect("should find a frontend"), - Route::ClusterId("cluster_3".to_string()) + Route::Cluster { + id: "cluster_3".to_string(), + h2: false + } ); println!("TEST {}", line!()); let frontend5 = listener.frontend_from_request("domain", "/", &Method::Get); diff --git a/lib/src/protocol/kawa_h1/mod.rs b/lib/src/protocol/kawa_h1/mod.rs index 1040bf41e..02e2c4107 100644 --- a/lib/src/protocol/kawa_h1/mod.rs +++ b/lib/src/protocol/kawa_h1/mod.rs @@ -1074,8 +1074,8 @@ impl Http cluster_id, + let (cluster_id, h2) = match route { + Route::Cluster { id, h2 } => (id, h2), Route::Deny => { self.set_answer(DefaultAnswerStatus::Answer401, None); return Err(RetrieveClusterError::UnauthorizedRoute); diff --git a/lib/src/router/mod.rs b/lib/src/router/mod.rs index 9c9a7b1c8..08639c7dc 100644 --- a/lib/src/router/mod.rs +++ b/lib/src/router/mod.rs @@ -117,7 +117,10 @@ impl Router { let method_rule = MethodRule::new(front.method.clone()); let route = match &front.cluster_id { - Some(cluster_id) => Route::ClusterId(cluster_id.clone()), + Some(cluster_id) => Route::Cluster { + id: cluster_id.clone(), + h2: front.h2, + }, None => Route::Deny, }; @@ -145,7 +148,7 @@ impl Router { } }; if !success { - return Err(RouterError::AddRoute(format!("{:?}", front))); + return Err(RouterError::AddRoute(format!("{front:?}"))); } Ok(()) } @@ -180,7 +183,7 @@ impl Router { } }; if !remove_success { - return Err(RouterError::RemoveRoute(format!("{:?}", front))); + return Err(RouterError::RemoveRoute(format!("{front:?}"))); } Ok(()) } @@ -581,7 +584,7 @@ pub enum Route { /// send a 401 default answer Deny, /// the cluster to which the frontend belongs - ClusterId(ClusterId), + Cluster { id: ClusterId, h2: bool }, } #[cfg(test)] @@ -693,25 +696,37 @@ mod tests { &"*".parse::().unwrap(), &PathRule::Prefix("/.well-known/acme-challenge".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::ClusterId("acme".to_string()) + &Route::Cluster { + id: "acme".to_string(), + h2: false + } )); assert!(router.add_tree_rule( "www.example.com".as_bytes(), &PathRule::Prefix("/".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::ClusterId("example".to_string()) + &Route::Cluster { + id: "example".to_string(), + h2: false + } )); 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::ClusterId("examplewildcard".to_string()) + &Route::Cluster { + id: "examplewildcard".to_string(), + h2: false + } )); assert!(router.add_tree_rule( "/test[0-9]/.example.com".as_bytes(), &PathRule::Prefix("/".to_string()), &MethodRule::new(Some("GET".to_string())), - &Route::ClusterId("exampleregex".to_string()) + &Route::Cluster { + id: "exampleregex".to_string(), + h2: false + } )); assert_eq!( @@ -720,7 +735,10 @@ mod tests { "/helloA".as_bytes(), &Method::new(&b"GET"[..]) ), - Some(Route::ClusterId("example".to_string())) + Some(Route::Cluster { + id: "example".to_string(), + h2: false + }) ); assert_eq!( router.lookup( @@ -728,7 +746,10 @@ mod tests { "/.well-known/acme-challenge".as_bytes(), &Method::new(&b"GET"[..]) ), - Some(Route::ClusterId("acme".to_string())) + Some(Route::Cluster { + id: "acme".to_string(), + h2: false + }) ); assert_eq!( router.lookup( @@ -744,7 +765,10 @@ mod tests { "/helloAB/".as_bytes(), &Method::new(&b"GET"[..]) ), - Some(Route::ClusterId("examplewildcard".to_string())) + Some(Route::Cluster { + id: "examplewildcard".to_string(), + h2: false + }) ); assert_eq!( router.lookup( @@ -752,7 +776,10 @@ mod tests { "/helloAB/".as_bytes(), &Method::new(&b"GET"[..]) ), - Some(Route::ClusterId("exampleregex".to_string())) + Some(Route::Cluster { + id: "exampleregex".to_string(), + h2: false + }) ); } } diff --git a/lib/src/server.rs b/lib/src/server.rs index 6ed3b1bec..2a7c7bc7e 100644 --- a/lib/src/server.rs +++ b/lib/src/server.rs @@ -1309,8 +1309,7 @@ impl Server { None => { let error = format!( - "Couldn't deactivate HTTPS listener at address {:?}", - address + "Couldn't deactivate HTTPS listener at address {address:?}", ); error!("{}", error); return WorkerResponse::error(req_id, error); @@ -1349,7 +1348,7 @@ impl Server { Some((token, listener)) => (token, listener), None => { let error = - format!("Couldn't deactivate TCP listener at address {:?}", address); + format!("Couldn't deactivate TCP listener at address {address:?}"); error!("{}", error); return WorkerResponse::error(req_id, error); }