Skip to content

url-constructor: '..' against a non-special base must pop the last path segment #1130

Description

@nikneym
  • Note that this crate implements the URL Standard not RFC 1738 or RFC 3986

rust-url tries to remove the trailing slash, but last_slash_can_be_removed("/y/z/C:/") sees the last dir is a drive letter (/C:/), as a consequence returns false, the trailing slash stays. You can reproduce with the following snippet.

use url::Url;

fn join(base: &str, rel: &str) -> String {
    Url::parse(base).unwrap().join(rel).unwrap().into()
}

fn main() {
    // A path segment "C:" is only special for file: URLs (WHATWG URL Standard).
    // For any other scheme it is an ordinary segment, so ".." must pop it.

    // Non-special scheme:
    assert_eq!(join("abc://x/y/z/C:/", ".."), "abc://x/y/z/");
    // Special, non-file scheme — same bug:
    assert_eq!(join("http://x/y/z/C:/", ".."), "http://x/y/z/");
    // The "C|" (pipe) form is affected too:
    assert_eq!(join("abc://x/y/z/C|/", ".."), "abc://x/y/z/");

    // Controls that already behave correctly (ordinary segments pop):
    assert_eq!(join("abc://x/y/z/w/",  ".."), "abc://x/y/z/");
    assert_eq!(join("abc://x/y/z/Ca/", ".."), "abc://x/y/z/");
    // And a drive-letter segment WITHOUT a trailing slash pops fine:
    assert_eq!(join("abc://x/y/z/C:",  ".."), "abc://x/y/");

    println!("ok");
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions