fix(engine): compare online servers' paths with their case

same_server lowercased the whole address, so files on /Team/ and /team/
(which a proxy can route to different servers) counted as one server and
the online refresh sent both files' owner tokens to whichever answered.
The scheme and host still compare without case; the path keeps its.
This commit is contained in:
Dylan M. Taylor committed 2026-11-03 04:21:45 +00:00
1 parent 02c38a6d95
commit 8864068cd5
2 files changed
+11 -5

No files matched your search

+3
View File
@@ -590,4 +590,7 @@ fn same_server_ignores_the_default_port_before_a_path() {
assert!(same_server("wss://share.example:443/figcraft/", "wss://share.example/figcraft/"));
assert!(same_server("ws://host:80/x", "ws://host/x"));
assert!(!same_server("wss://share.example:8443/figcraft/", "wss://share.example/figcraft/"));
// The path is a route: owner tokens for /Team/ must never be sent to /team/.
assert!(same_server("WSS://Share.Example/team/", "wss://share.example/team"));
assert!(!same_server("wss://share.example/Team/", "wss://share.example/team/"));
}
+8 -5
View File
@@ -117,14 +117,17 @@ pub(crate) fn plain_server(server: &str) -> String {
/// Two addresses name the same server (case, a closing slash and the scheme's own port aside).
pub fn same_server(a: &str, b: &str) -> bool {
let norm = |s: &str| {
let s = plain_server(s).to_ascii_lowercase();
let s = plain_server(s);
let s = s.trim_end_matches('/');
let port = if s.starts_with("wss://") { ":443" } else { ":80" };
let start = s.find("://").map_or(0, |i| i + 3);
let end = s[start..].find('/').map_or(s.len(), |i| start + i);
match s[start..end].strip_suffix(port) {
Some(host) => format!("{}{}{}", &s[..start], host, &s[end..]),
None => s.to_string(),
// The scheme and host compare without case; the path routes (a proxy may send
// `/Team/` and `/team/` to different servers), so it keeps its case.
let head = s[..end].to_ascii_lowercase();
let port = if head.starts_with("wss://") { ":443" } else { ":80" };
match head[start..].strip_suffix(port) {
Some(host) => format!("{}{}{}", &head[..start], host, &s[end..]),
None => format!("{head}{}", &s[end..]),
}
};
norm(a) == norm(b)