Skip to content

Commit ec23e7c

Browse files
committed
Segment delimiters and path trimming.
1 parent 1099d8b commit ec23e7c

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,8 +1397,12 @@ impl Url {
13971397
}
13981398
parser.parse_cannot_be_a_base_path(parser::Input::new(path));
13991399
} else {
1400+
let path_start = parser.serialization.len();
14001401
let mut has_host = true; // FIXME
14011402
parser.parse_path_start(scheme_type, &mut has_host, parser::Input::new(path));
1403+
if scheme_type.is_file() {
1404+
parser::trim_path(&mut parser.serialization, path_start);
1405+
}
14021406
}
14031407
});
14041408
self.restore_after_path(old_after_path_pos, &after_path);

src/parser.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,24 @@ impl<'a> Parser<'a> {
798798
self.serialization.push_str(before_query);
799799
// FIXME spec says just "remove last entry", not the "pop" algorithm
800800
self.pop_path(scheme_type, base_url.path_start as usize);
801-
let remaining =
802-
self.parse_path(scheme_type, &mut true, base_url.path_start as usize, input);
801+
// A special url always has a path.
802+
// A path always starts with '/'
803+
if self.serialization.len() == base_url.path_start as usize {
804+
if SchemeType::from(base_url.scheme()).is_special() || !input.is_empty() {
805+
self.serialization.push('/');
806+
}
807+
}
808+
let remaining = match input.split_first() {
809+
(Some('/'), remaining) => self.parse_path(
810+
scheme_type,
811+
&mut true,
812+
base_url.path_start as usize,
813+
remaining,
814+
),
815+
_ => {
816+
self.parse_path(scheme_type, &mut true, base_url.path_start as usize, input)
817+
}
818+
};
803819
self.with_query_and_fragment(
804820
scheme_type,
805821
base_url.scheme_end,
@@ -1427,12 +1443,14 @@ impl<'a> Parser<'a> {
14271443

14281444
// Trim path start forward slashes when no authority is present
14291445
// https://github.com/whatwg/url/issues/232
1430-
fn trim_path(serialization: &mut String, path_start: usize) {
1446+
pub fn trim_path(serialization: &mut String, path_start: usize) {
14311447
let path = serialization.split_off(path_start);
14321448
if path.starts_with("/") {
14331449
let mut trimmed_path = "/".to_string();
14341450
trimmed_path.push_str(path.trim_start_matches("/"));
14351451
serialization.push_str(&trimmed_path);
1452+
} else {
1453+
serialization.push_str(&path);
14361454
}
14371455
}
14381456

src/quirks.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,10 @@ pub fn set_pathname(url: &mut Url, new_pathname: &str) {
236236
if url.cannot_be_a_base() {
237237
return;
238238
}
239-
if !SchemeType::from(url.scheme()).is_special()
240-
|| Some('/') == new_pathname.chars().nth(0)
241-
// \\ is a segment delimiter for 'special' URLs"
242-
|| Some('\\') == new_pathname.chars().nth(0)
239+
if Some('/') == new_pathname.chars().nth(0)
240+
|| SchemeType::from(url.scheme()).is_special()
241+
// \ is a segment delimiter for 'special' URLs"
242+
&& Some('\\') == new_pathname.chars().nth(0)
243243
{
244244
url.set_path(new_pathname)
245245
} else {

0 commit comments

Comments
 (0)