v0.34.0_1
This commit is contained in:
1 parent
9b3d6731cc
commit
00f29f92c8
68 files changed
+2599
-513
No files matched your search
@@ -207,8 +207,8 @@ fn compile_local_hosts(config: &Config) -> Result<LocalHostBuild> {
|
||||
}
|
||||
|
||||
struct RoutingBuild {
|
||||
routes: HashMap<String, Vec<CompiledRoute>>,
|
||||
fallbacks: HashMap<String, Vec<CompiledRoute>>,
|
||||
routes: HashMap<String, Vec<Arc<CompiledRoute>>>,
|
||||
fallbacks: HashMap<String, Vec<Arc<CompiledRoute>>>,
|
||||
frontends: HashMap<String, Vec<Arc<CompiledFrontend>>>,
|
||||
redirects: HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>>,
|
||||
not_found_hosts: HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>>,
|
||||
|
||||
@@ -10,8 +10,20 @@ impl Snapshot {
|
||||
local: SocketAddr,
|
||||
tls: bool,
|
||||
) -> Option<&CompiledRoute> {
|
||||
self.select_internal_on_arc(host, vhost_id, target, local, tls)
|
||||
.map(Arc::as_ref)
|
||||
}
|
||||
|
||||
pub fn select_internal_on_arc(
|
||||
&self,
|
||||
host: &str,
|
||||
vhost_id: &str,
|
||||
target: &str,
|
||||
local: SocketAddr,
|
||||
tls: bool,
|
||||
) -> Option<&Arc<CompiledRoute>> {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
let owns_host = self.fallbacks.get(&pattern).is_some_and(|routes| {
|
||||
let owns_host = self.fallbacks.get(pattern.as_ref()).is_some_and(|routes| {
|
||||
routes.iter().any(|route| {
|
||||
route.frontend.as_ref().is_some_and(|frontend| frontend.id == vhost_id)
|
||||
&& route.bindings.iter().any(|binding| binding.matches(local, tls))
|
||||
@@ -20,7 +32,7 @@ impl Snapshot {
|
||||
if !owns_host {
|
||||
continue;
|
||||
}
|
||||
return self.routes.get(&pattern).and_then(|routes| {
|
||||
return self.routes.get(pattern.as_ref()).and_then(|routes| {
|
||||
routes.iter().find(|route| {
|
||||
route.internal
|
||||
&& route.name == target
|
||||
|
||||
+2
-2
@@ -289,9 +289,9 @@ pub struct Snapshot {
|
||||
frontends: HashMap<String, Vec<Arc<CompiledFrontend>>>,
|
||||
pub tls: Option<Arc<rustls::ServerConfig>>,
|
||||
pub envelope: Envelope,
|
||||
routes: HashMap<String, Vec<CompiledRoute>>,
|
||||
routes: HashMap<String, Vec<Arc<CompiledRoute>>>,
|
||||
/// Main vhost backend fallback, kept separate from user Custom locations.
|
||||
fallbacks: HashMap<String, Vec<CompiledRoute>>,
|
||||
fallbacks: HashMap<String, Vec<Arc<CompiledRoute>>>,
|
||||
redirects: HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>>,
|
||||
not_found_hosts: HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>>,
|
||||
host_acls: HashMap<String, Arc<CompiledAcl>>,
|
||||
|
||||
@@ -9,8 +9,8 @@ fn compile_routing(
|
||||
effective_tls: &crate::tls::Settings,
|
||||
tls: &Option<Arc<rustls::ServerConfig>>,
|
||||
) -> Result<RoutingBuild> {
|
||||
let mut routes: HashMap<String, Vec<CompiledRoute>> = HashMap::new();
|
||||
let mut fallbacks: HashMap<String, Vec<CompiledRoute>> = HashMap::new();
|
||||
let mut routes: HashMap<String, Vec<Arc<CompiledRoute>>> = HashMap::new();
|
||||
let mut fallbacks: HashMap<String, Vec<Arc<CompiledRoute>>> = HashMap::new();
|
||||
let mut frontends: HashMap<String, Vec<Arc<CompiledFrontend>>> = HashMap::new();
|
||||
let (redirects, not_found_hosts, mut claimed_hosts) = compile_local_hosts(config)?;
|
||||
let mut pools = Vec::new();
|
||||
@@ -247,7 +247,7 @@ fn compile_routing(
|
||||
None,
|
||||
),
|
||||
};
|
||||
let fallback = CompiledRoute {
|
||||
let fallback = Arc::new(CompiledRoute {
|
||||
backend_id: None,
|
||||
bindings: frontend.bindings.clone(),
|
||||
frontend: Some(frontend.clone()),
|
||||
@@ -273,7 +273,7 @@ fn compile_routing(
|
||||
method_policy: crate::vhost::MethodPolicy::default(),
|
||||
headers: crate::headers::CompiledHeaders::default(),
|
||||
unavailable: host.transient_unavailable && host.source.is_reverse_proxy(),
|
||||
};
|
||||
});
|
||||
for name in &routing_hosts {
|
||||
fallbacks
|
||||
.entry(name.clone())
|
||||
@@ -389,7 +389,7 @@ fn compile_routing(
|
||||
),
|
||||
}
|
||||
};
|
||||
let compiled = CompiledRoute {
|
||||
let compiled = Arc::new(CompiledRoute {
|
||||
backend_id: route.backend_id.clone(),
|
||||
bindings: frontend.bindings.clone(),
|
||||
frontend: Some(frontend.clone()),
|
||||
@@ -415,7 +415,7 @@ fn compile_routing(
|
||||
method_policy: route.method_policy.clone(),
|
||||
headers,
|
||||
unavailable: false,
|
||||
};
|
||||
});
|
||||
for name in &routing_hosts {
|
||||
routes
|
||||
.entry(name.clone())
|
||||
|
||||
+31
-21
@@ -1,17 +1,16 @@
|
||||
impl Snapshot {
|
||||
fn host_patterns(host: &str) -> Vec<String> {
|
||||
let mut patterns = vec![host.to_owned()];
|
||||
for (index, _) in host.match_indices('.') {
|
||||
let suffix = &host[index + 1..];
|
||||
if suffix.contains('.') {
|
||||
patterns.push(format!("*.{suffix}"));
|
||||
}
|
||||
}
|
||||
patterns
|
||||
// Exact host: no allocation. Wildcards: lazy and most-specific-first.
|
||||
fn host_patterns(host: &str) -> impl Iterator<Item = std::borrow::Cow<'_, str>> {
|
||||
std::iter::once(std::borrow::Cow::Borrowed(host)).chain(
|
||||
host.match_indices('.').filter_map(move |(index, _)| {
|
||||
let suffix = &host[index + 1..];
|
||||
suffix.contains('.').then(|| std::borrow::Cow::Owned(format!("*.{suffix}")))
|
||||
}),
|
||||
)
|
||||
}
|
||||
pub fn host_allowed(&self, host: &str, peer: IpAddr) -> bool {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
if let Some(acl) = self.host_acls.get(&pattern) {
|
||||
if let Some(acl) = self.host_acls.get(pattern.as_ref()) {
|
||||
return acl.allows(peer);
|
||||
}
|
||||
}
|
||||
@@ -53,8 +52,19 @@ impl Snapshot {
|
||||
local: SocketAddr,
|
||||
tls: bool,
|
||||
) -> Option<&CompiledRoute> {
|
||||
self.select_on_arc(host, path, local, tls).map(Arc::as_ref)
|
||||
}
|
||||
|
||||
/// Shared compiled-route handle for middleware and forward().
|
||||
pub fn select_on_arc(
|
||||
&self,
|
||||
host: &str,
|
||||
path: &str,
|
||||
local: SocketAddr,
|
||||
tls: bool,
|
||||
) -> Option<&Arc<CompiledRoute>> {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
let fallback = self.fallbacks.get(&pattern).and_then(|routes| {
|
||||
let fallback = self.fallbacks.get(pattern.as_ref()).and_then(|routes| {
|
||||
routes
|
||||
.iter()
|
||||
.find(|route| route.bindings.iter().any(|l| l.matches(local, tls)))
|
||||
@@ -65,7 +75,7 @@ impl Snapshot {
|
||||
if let Some(fallback) = fallback {
|
||||
return self
|
||||
.routes
|
||||
.get(&pattern)
|
||||
.get(pattern.as_ref())
|
||||
.and_then(|routes| {
|
||||
select_route(routes, path, |r| {
|
||||
r.bindings.iter().any(|l| l.matches(local, tls))
|
||||
@@ -76,7 +86,6 @@ impl Snapshot {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn frontend(
|
||||
&self,
|
||||
host: &str,
|
||||
@@ -84,7 +93,7 @@ impl Snapshot {
|
||||
tls: bool,
|
||||
) -> Option<&Arc<CompiledFrontend>> {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
if let Some(frontend) = self.frontends.get(&pattern).and_then(|frontends| {
|
||||
if let Some(frontend) = self.frontends.get(pattern.as_ref()).and_then(|frontends| {
|
||||
frontends
|
||||
.iter()
|
||||
.find(|f| f.bindings.iter().any(|l| l.matches(local, tls)))
|
||||
@@ -155,7 +164,7 @@ impl Snapshot {
|
||||
&crate::redirect::CompiledRule,
|
||||
)> {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
if let Some((redirect, rule)) = self.redirects.get(&pattern).and_then(|redirects| {
|
||||
if let Some((redirect, rule)) = self.redirects.get(pattern.as_ref()).and_then(|redirects| {
|
||||
redirects.iter().find_map(|redirect| {
|
||||
if !redirect
|
||||
.bindings
|
||||
@@ -184,7 +193,7 @@ impl Snapshot {
|
||||
tls: bool,
|
||||
) -> Option<&Arc<crate::not_found::CompiledHost>> {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
if let Some(item) = self.not_found_hosts.get(&pattern).and_then(|items| {
|
||||
if let Some(item) = self.not_found_hosts.get(pattern.as_ref()).and_then(|items| {
|
||||
items.iter().find(|item| {
|
||||
item.bindings
|
||||
.iter()
|
||||
@@ -202,14 +211,15 @@ impl Snapshot {
|
||||
for pattern in Self::host_patterns(host) {
|
||||
if let Some(fallback) = self
|
||||
.fallbacks
|
||||
.get(&pattern)
|
||||
.get(pattern.as_ref())
|
||||
.and_then(|routes| routes.first())
|
||||
{
|
||||
return self
|
||||
.routes
|
||||
.get(&pattern)
|
||||
.get(pattern.as_ref())
|
||||
.and_then(|routes| select_route(routes, path, |_| true))
|
||||
.or(Some(fallback));
|
||||
.or(Some(fallback))
|
||||
.map(Arc::as_ref);
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -217,10 +227,10 @@ impl Snapshot {
|
||||
}
|
||||
|
||||
fn select_route<'a, F>(
|
||||
routes: &'a [CompiledRoute],
|
||||
routes: &'a [Arc<CompiledRoute>],
|
||||
path: &str,
|
||||
allowed: F,
|
||||
) -> Option<&'a CompiledRoute>
|
||||
) -> Option<&'a Arc<CompiledRoute>>
|
||||
where
|
||||
F: Fn(&CompiledRoute) -> bool,
|
||||
{
|
||||
|
||||
@@ -9,6 +9,19 @@ fn policy() -> ValidationPolicy {
|
||||
admin_addr: "127.0.0.1:9090".parse().unwrap(),
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn route_handles_reuse_snapshot_ownership_without_cloning_compiled_routes() {
|
||||
let snapshot = compile(demo_config("127.0.0.1:9000".parse().unwrap()), 1, &policy()).unwrap();
|
||||
let local = "127.0.0.1:8080".parse().unwrap();
|
||||
let first = snapshot.select_on_arc("localhost", "/", local, false).unwrap();
|
||||
let second = snapshot.select_on_arc("localhost", "/child", local, false).unwrap();
|
||||
// Both selectors point into one immutable compiled snapshot.
|
||||
assert!(std::sync::Arc::ptr_eq(first, second));
|
||||
let legacy = snapshot.select_on("localhost", "/", local, false).unwrap();
|
||||
assert!(std::ptr::eq(first.as_ref(), legacy));
|
||||
assert!(snapshot.select_on_arc("not-this-host", "/", local, false).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_http2_settings_use_release_defaults() {
|
||||
let config: Config = serde_json::from_value(serde_json::json!({})).unwrap();
|
||||
|
||||
Reference in new issue
Block a user