Skip to content

Commit 8bd1165

Browse files
committed
Handle updating the hostname when the first path segment is empty
1 parent 21cada8 commit 8bd1165

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

url/src/lib.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,7 @@ impl Url {
21292129
} else {
21302130
self.host_end
21312131
};
2132-
let suffix = self.slice(old_suffix_pos..).to_owned();
2132+
let mut suffix = self.slice(old_suffix_pos..).to_owned();
21332133
self.serialization.truncate(self.host_start as usize);
21342134
if !self.has_authority() {
21352135
debug_assert!(self.slice(self.scheme_end..self.host_start) == ":");
@@ -2143,6 +2143,23 @@ impl Url {
21432143
self.host_end = to_u32(self.serialization.len()).unwrap();
21442144
self.host = host.into();
21452145

2146+
// Adjust serialization to switch between host and empty segment
2147+
if suffix.starts_with("/.//") {
2148+
suffix = suffix["/.".len()..].to_string();
2149+
// pathname should be "//p" not "p" given that the first segment was empty
2150+
self.path_start -= "//".len() as u32;
2151+
} else if self.host == HostInternal::None && suffix.starts_with("//") {
2152+
if let Some(index) = self.serialization.find(":") {
2153+
if self.serialization.len() == index + "://".len()
2154+
&& self.serialization.as_bytes().get(index + 1) == Some(&b'/')
2155+
&& self.serialization.as_bytes().get(index + 2) == Some(&b'/')
2156+
{
2157+
self.serialization
2158+
.replace_range(index..index + "://".len(), ":/.");
2159+
}
2160+
}
2161+
}
2162+
21462163
if let Some(new_port) = opt_new_port {
21472164
self.port = new_port;
21482165
if let Some(port) = new_port {

url/tests/expected_failures.txt

-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
<file:/.//p>
3737
<http://example.net/path> set hostname to <example.com:8080>
3838
<http://example.net:8080/path> set hostname to <example.com:>
39-
<non-spec:/.//p> set hostname to <h>
40-
<non-spec:/.//p> set hostname to <>
4139
<foo:///some/path> set pathname to <>
4240
<file:///var/log/system.log> set href to <http://0300.168.0xF0>
4341
<file://monkey/> set pathname to <\\\\>

url/tests/unit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,7 @@ fn serde_error_message() {
13821382

13831383
#[test]
13841384
fn test_can_be_a_base_with_set_path() {
1385+
use url::quirks;
13851386
let mut url = Url::parse("web+demo:/").unwrap();
13861387
assert!(!url.cannot_be_a_base());
13871388

@@ -1396,6 +1397,10 @@ fn test_can_be_a_base_with_set_path() {
13961397
assert_eq!(segments, vec!["", "not-a-host"]);
13971398

13981399
assert_eq!(url.as_str(), "web+demo:/.//not-a-host");
1400+
quirks::set_hostname(&mut url, "test").unwrap();
1401+
assert_eq!(url.as_str(), "web+demo://test//not-a-host");
1402+
quirks::set_hostname(&mut url, "").unwrap();
1403+
assert_eq!(url.as_str(), "web+demo:/.//not-a-host");
13991404
}
14001405

14011406
#[test]

0 commit comments

Comments
 (0)