Skip to content

Commit 50f4779

Browse files
authored
Fix not correctly encoding web viewer URLs (#11128)
`ViewerOpenURL::sharable_url` didn't correctly encode the parameters for web urls. That works for surprisingly many urls just fine, but once you start adding fragments & parameters within those URLs it naturally breaks down! Fixes RR-2225
1 parent 7f8dfbe commit 50f4779

File tree

1 file changed

+28
-29
lines changed

1 file changed

+28
-29
lines changed

crates/viewer/re_viewer/src/open_url.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -370,13 +370,14 @@ impl ViewerOpenUrl {
370370
// Combine the URL(s) with the web viewer base URL if provided.
371371
if let Some(web_viewer_base_url) = web_viewer_base_url {
372372
let mut share_url = web_viewer_base_url.clone();
373-
share_url.set_query(Some(
374-
&urls
375-
.into_iter()
376-
.map(|url| format!("url={url}"))
377-
.collect::<Vec<_>>()
378-
.join("&"),
379-
));
373+
374+
// Use the form_urlencoded::Serializer to build the query string with multiple "url" parameters.
375+
// It's important to not just append the strings, since we have to take care of correctly escaping.
376+
let mut serializer = url::form_urlencoded::Serializer::new(String::new());
377+
for url in &urls {
378+
serializer.append_pair("url", url);
379+
}
380+
share_url.set_query(Some(&serializer.finish()));
380381

381382
Ok(share_url.to_string())
382383
} else if urls.len() == 1 {
@@ -978,60 +979,58 @@ mod tests {
978979
ViewerOpenUrl::IntraRecordingSelection("my/path".parse().unwrap())
979980
.sharable_url(base_url_param)
980981
.unwrap(),
981-
"https://foo.com/test?url=recording://my/path"
982-
);
983-
984-
assert_eq!(
985-
ViewerOpenUrl::RrdHttpUrl(Url::parse("https://example.com/data.rrd").unwrap())
986-
.sharable_url(base_url_param)
987-
.unwrap(),
988-
"https://foo.com/test?url=https://example.com/data.rrd"
982+
"https://foo.com/test?url=recording%3A%2F%2Fmy%2Fpath"
989983
);
990984

991985
assert_eq!(
992-
ViewerOpenUrl::FilePath("/path/to/file.rrd".into())
986+
ViewerOpenUrl::RrdHttpUrl("https://example.com/data.rrd".parse().unwrap())
993987
.sharable_url(base_url_param)
994988
.unwrap(),
995-
"https://foo.com/test?url=/path/to/file.rrd"
989+
"https://foo.com/test?url=https%3A%2F%2Fexample.com%2Fdata.rrd"
996990
);
997991

998-
let uri =
999-
"rerun://127.0.0.1:1234/dataset/1830B33B45B963E7774455beb91701ae?partition_id=pid";
1000992
assert_eq!(
1001-
ViewerOpenUrl::RedapDatasetPartition(uri.parse().unwrap())
1002-
.sharable_url(base_url_param)
1003-
.unwrap(),
1004-
format!("https://foo.com/test?url={uri}")
993+
ViewerOpenUrl::RedapDatasetPartition(
994+
"rerun://127.0.0.1:1234/dataset/1830B33B45B963E7774455beb91701ae?partition_id=pid"
995+
.parse()
996+
.unwrap()
997+
)
998+
.sharable_url(base_url_param)
999+
.unwrap(),
1000+
format!(
1001+
"https://foo.com/test?url=rerun%3A%2F%2F127.0.0.1%3A1234%2Fdataset%2F1830B33B45B963E7774455beb91701ae%3Fpartition_id%3Dpid"
1002+
)
10051003
);
10061004

10071005
assert_eq!(
10081006
ViewerOpenUrl::RedapProxy("rerun://localhost:51234/proxy".parse().unwrap())
10091007
.sharable_url(base_url_param)
10101008
.unwrap(),
1011-
"https://foo.com/test?url=rerun://localhost:51234/proxy"
1009+
"https://foo.com/test?url=rerun%3A%2F%2Flocalhost%3A51234%2Fproxy"
10121010
);
10131011

10141012
assert_eq!(
10151013
ViewerOpenUrl::RedapCatalog("rerun://localhost:51234/catalog".parse().unwrap())
10161014
.sharable_url(base_url_param)
10171015
.unwrap(),
1018-
"https://foo.com/test?url=rerun://localhost:51234/catalog"
1016+
"https://foo.com/test?url=rerun%3A%2F%2Flocalhost%3A51234%2Fcatalog"
10191017
);
10201018

10211019
let entry_id = EntryId::new();
10221020
let url = format!("rerun://localhost:51234/entry/{entry_id}");
1021+
let encoded_url = url::form_urlencoded::byte_serialize(url.as_bytes()).collect::<String>();
10231022
assert_eq!(
10241023
ViewerOpenUrl::RedapEntry(url.parse().unwrap())
10251024
.sharable_url(base_url_param)
10261025
.unwrap(),
1027-
format!("https://foo.com/test?url={url}")
1026+
format!("https://foo.com/test?url={encoded_url}")
10281027
);
10291028

10301029
assert_eq!(
10311030
ViewerOpenUrl::WebEventListener
10321031
.sharable_url(base_url_param)
10331032
.unwrap(),
1034-
"https://foo.com/test?url=web_event:"
1033+
"https://foo.com/test?url=web_event%3A"
10351034
);
10361035

10371036
assert_eq!(
@@ -1043,7 +1042,7 @@ mod tests {
10431042
}
10441043
.sharable_url(base_url_param)
10451044
.unwrap(),
1046-
"https://foo.com/test?url=https://example.com/data.rrd",
1045+
"https://foo.com/test?url=https%3A%2F%2Fexample.com%2Fdata.rrd",
10471046
);
10481047
assert_eq!(
10491048
ViewerOpenUrl::WebViewerUrl {
@@ -1055,7 +1054,7 @@ mod tests {
10551054
}
10561055
.sharable_url(base_url_param)
10571056
.unwrap(),
1058-
"https://foo.com/test?url=https://example.com/bar.rrd&url=rerun://localhost:51234/proxy",
1057+
"https://foo.com/test?url=https%3A%2F%2Fexample.com%2Fbar.rrd&url=rerun%3A%2F%2Flocalhost%3A51234%2Fproxy",
10591058
);
10601059
}
10611060
}

0 commit comments

Comments
 (0)