Merge PR #2431: Keep file name and query for fragment-only redirect Location

This commit is contained in:
aiongg
2026-10-22 02:38:11 +00:00
+13
View File
@@ -173,6 +173,10 @@ impl Url {
if l.starts_with('/') { if l.starts_with('/') {
return Url::parse(&format!("{base}{l}")); return Url::parse(&format!("{base}{l}"));
} }
// empty or fragment-only: the same document
if l.is_empty() || l.starts_with('#') {
return Ok(self.clone());
}
// relative to the current directory // relative to the current directory
let dir = self.path.split('?').next().unwrap_or("/"); let dir = self.path.split('?').next().unwrap_or("/");
// a query-only reference keeps the whole path, file name included (RFC 3986 §5.2.2) // a query-only reference keeps the whole path, file name included (RFC 3986 §5.2.2)
@@ -654,6 +658,15 @@ mod tests_connect {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn fragment_only_or_empty_location_keeps_file_name_and_query() {
let base = Url::parse("https://a.example/x/y/file?q").unwrap();
for l in ["#top", "", " "] {
let u = base.join(l).unwrap();
assert_eq!((u.tls, u.host.as_str(), u.port, u.path.as_str()), (true, "a.example", 443, "/x/y/file?q"), "{l:?}");
}
}
#[test] #[test]
fn rejects_oversized_and_control_character_urls() { fn rejects_oversized_and_control_character_urls() {
assert!(Url::parse(&format!("https://example.com/{}", "x".repeat(16 * 1024))).is_err()); assert!(Url::parse(&format!("https://example.com/{}", "x".repeat(16 * 1024))).is_err());