0.34.6_repo_cleanup
This commit is contained in:
1 parent
ce1a90397c
commit
133d2f0f91
273 files changed
+5969
-6926
No files matched your search
+21
-36
@@ -1,13 +1,8 @@
|
||||
impl Snapshot {
|
||||
// Exact-first lookups with stack-buffered wildcard keys for normal hosts.
|
||||
fn find_host_pattern<T>(
|
||||
host: &str,
|
||||
mut lookup: impl FnMut(&str) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
fn find_host_pattern<T>(host: &str, mut lookup: impl FnMut(&str) -> Option<T>) -> Option<T> {
|
||||
if let Some(value) = lookup(host) {
|
||||
return Some(value);
|
||||
}
|
||||
// Skip the final dot: only one label follows it.
|
||||
let last_dot = host.rfind('.')?;
|
||||
let mut wildcard = [0u8; 256];
|
||||
wildcard[..2].copy_from_slice(b"*.");
|
||||
@@ -25,7 +20,6 @@ impl Snapshot {
|
||||
return Some(value);
|
||||
}
|
||||
} else if let Some(value) = lookup(&format!("*.{suffix}")) {
|
||||
// Preserve behavior for unusual overlong internal host inputs.
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +34,6 @@ impl Snapshot {
|
||||
})
|
||||
.unwrap_or(true)
|
||||
}
|
||||
/// RFC 8441 is connection-scoped; requests still enforce vhost opt-in.
|
||||
pub fn websocket_rfc8441_on(&self, local: SocketAddr, tls: bool) -> bool {
|
||||
self.frontends.values().flatten().any(|frontend| {
|
||||
frontend.websockets
|
||||
@@ -51,7 +44,6 @@ impl Snapshot {
|
||||
})
|
||||
})
|
||||
}
|
||||
/// RFC 9220 is connection-scoped; requests still enforce vhost opt-in.
|
||||
pub fn websocket_rfc9220_on(&self, local: SocketAddr) -> bool {
|
||||
self.frontends.values().flatten().any(|frontend| {
|
||||
frontend.websockets
|
||||
@@ -62,8 +54,6 @@ impl Snapshot {
|
||||
})
|
||||
})
|
||||
}
|
||||
/// Production routing always uses the TCP connection's local endpoint.
|
||||
/// Exact hostnames win over the longest matching wildcard hostname.
|
||||
pub fn select_on(
|
||||
&self,
|
||||
host: &str,
|
||||
@@ -73,7 +63,6 @@ impl Snapshot {
|
||||
) -> 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,
|
||||
@@ -87,7 +76,6 @@ impl Snapshot {
|
||||
.iter()
|
||||
.find(|route| route.bindings.iter().any(|l| l.matches(local, tls)))
|
||||
})?;
|
||||
// The claimed vhost owns its fallback ahead of broader wildcards.
|
||||
self.routes
|
||||
.get(pattern)
|
||||
.and_then(|routes| {
|
||||
@@ -112,7 +100,6 @@ impl Snapshot {
|
||||
})
|
||||
})
|
||||
}
|
||||
/// Resolve protocol-error attribution with the routing precedence and bindings.
|
||||
pub fn resolve_logging_vhost(
|
||||
&self,
|
||||
local: SocketAddr,
|
||||
@@ -136,11 +123,7 @@ impl Snapshot {
|
||||
});
|
||||
}
|
||||
}
|
||||
for (candidate, matched_by) in [
|
||||
(authority, "authority"),
|
||||
(host, "host"),
|
||||
(sni, "sni"),
|
||||
] {
|
||||
for (candidate, matched_by) in [(authority, "authority"), (host, "host"), (sni, "sni")] {
|
||||
let Some(candidate) = candidate else {
|
||||
continue;
|
||||
};
|
||||
@@ -156,7 +139,6 @@ impl Snapshot {
|
||||
}
|
||||
None
|
||||
}
|
||||
/// Select redirects using accepted socket, TLS state and normalized path.
|
||||
pub fn redirect_on(
|
||||
&self,
|
||||
host: &str,
|
||||
@@ -189,7 +171,6 @@ impl Snapshot {
|
||||
})
|
||||
})
|
||||
}
|
||||
/// Select a host-owned local 404/static response using the accepted socket.
|
||||
pub fn not_found_host_on(
|
||||
&self,
|
||||
host: &str,
|
||||
@@ -209,10 +190,12 @@ impl Snapshot {
|
||||
})
|
||||
})
|
||||
}
|
||||
/// Legacy inspection helper only; network handlers must call select_on.
|
||||
pub fn select(&self, host: &str, path: &str) -> Option<&CompiledRoute> {
|
||||
Self::find_host_pattern(host, |pattern| {
|
||||
let fallback = self.fallbacks.get(pattern).and_then(|routes| routes.first())?;
|
||||
let fallback = self
|
||||
.fallbacks
|
||||
.get(pattern)
|
||||
.and_then(|routes| routes.first())?;
|
||||
self.routes
|
||||
.get(pattern)
|
||||
.and_then(|routes| select_route(routes, path, |_| true))
|
||||
@@ -269,17 +252,25 @@ where
|
||||
prefix
|
||||
}
|
||||
impl CompiledRoute {
|
||||
pub fn redirect_location(&self, path: &str, uri: &http::Uri) -> Result<Option<http::HeaderValue>> {
|
||||
pub fn redirect_location(
|
||||
&self,
|
||||
path: &str,
|
||||
uri: &http::Uri,
|
||||
) -> Result<Option<http::HeaderValue>> {
|
||||
let Some(spec) = &self.redirect else {
|
||||
return Ok(None);
|
||||
};
|
||||
let target = if let Some(regex) = &spec.rewrite_regex {
|
||||
ensure!(regex.is_match(path), "location redirect rewrite regex did not match");
|
||||
ensure!(
|
||||
regex.is_match(path),
|
||||
"location redirect rewrite regex did not match"
|
||||
);
|
||||
regex.replace(path, spec.target.as_str()).into_owned()
|
||||
} else {
|
||||
spec.target.clone()
|
||||
};
|
||||
let mut target = url::Url::parse(&target).context("invalid compiled location redirect target")?;
|
||||
let mut target =
|
||||
url::Url::parse(&target).context("invalid compiled location redirect target")?;
|
||||
if spec.preserve_query {
|
||||
if let Some(query) = uri.query() {
|
||||
let merged = match target.query() {
|
||||
@@ -289,10 +280,11 @@ impl CompiledRoute {
|
||||
target.set_query(Some(&merged));
|
||||
}
|
||||
}
|
||||
Ok(Some(http::HeaderValue::from_str(target.as_str()).context("invalid redirect Location header")?))
|
||||
Ok(Some(
|
||||
http::HeaderValue::from_str(target.as_str())
|
||||
.context("invalid redirect Location header")?,
|
||||
))
|
||||
}
|
||||
/// Return a normalized replacement path for the upstream hop. `None` means
|
||||
/// preserve the client's exact origin-form path bytes.
|
||||
pub fn rewritten_path(&self, path: &str) -> Result<Option<String>> {
|
||||
use crate::vhost::RewriteMode;
|
||||
let rewritten = match self.rewrite.mode {
|
||||
@@ -346,7 +338,6 @@ pub(crate) fn valid_id(id: &str) -> bool {
|
||||
.bytes()
|
||||
.all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_')
|
||||
}
|
||||
/// Vhost names are ASCII DNS names (IDNs must be provided as punycode) or IPv4.
|
||||
pub fn normalize_host(value: &str) -> Result<String> {
|
||||
let host = value
|
||||
.strip_suffix('.')
|
||||
@@ -370,8 +361,6 @@ pub fn normalize_host(value: &str) -> Result<String> {
|
||||
);
|
||||
Ok(host)
|
||||
}
|
||||
/// Configured frontend patterns may use a single leading `*.` wildcard.
|
||||
/// Runtime Host values remain exact and are normalized by `normalize_host`.
|
||||
pub fn normalize_host_pattern(value: &str) -> Result<String> {
|
||||
let value = value.trim();
|
||||
if let Some(base) = value.strip_prefix("*.") {
|
||||
@@ -395,13 +384,10 @@ pub fn normalize_host_pattern(value: &str) -> Result<String> {
|
||||
pub fn request_host(value: &str) -> Result<String> {
|
||||
ensure!(!value.contains('@'), "invalid Host");
|
||||
let authority: Authority = value.parse().context("invalid Host authority")?;
|
||||
// Authority::port() returns None for both an absent and an invalid port.
|
||||
// Inspect the explicit suffix so an out-of-range port cannot bypass validation.
|
||||
let raw_host = authority.host();
|
||||
let suffix = &authority.as_str()[raw_host.len()..];
|
||||
if !suffix.is_empty() {
|
||||
let port = suffix.strip_prefix(':').context("invalid Host port")?;
|
||||
// HTTP permits an empty port suffix, which selects the default port.
|
||||
if !port.is_empty() {
|
||||
let number: u16 = port.parse().context("invalid Host port")?;
|
||||
ensure!(number > 0, "invalid Host port");
|
||||
@@ -461,7 +447,6 @@ pub(crate) fn ip_policy(ip: IpAddr, allow_private: bool) -> Result<()> {
|
||||
!(s[0] == 0x2001 && s[1] == 0x0db8),
|
||||
"documentation address is not a backend"
|
||||
);
|
||||
// Only global unicast, ULA and loopback. Reject IPv4 translation/tunnel special ranges.
|
||||
let ula = s[0] & 0xfe00 == 0xfc00;
|
||||
let global =
|
||||
s[0] & 0xe000 == 0x2000 && s[0] != 0x2002 && !(s[0] == 0x2001 && s[1] == 0);
|
||||
|
||||
Reference in new issue
Block a user