Skip to content

Commit 0685481

Browse files
authored
Merge pull request #2906 from itowlson/fix-at-in-url-path-host
Fix `@` in URL path confusing the parser
2 parents 4441c8c + 227aa8c commit 0685481

File tree

1 file changed

+32
-6
lines changed
  • crates/factor-outbound-networking/src

1 file changed

+32
-6
lines changed

crates/factor-outbound-networking/src/config.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -443,12 +443,19 @@ impl OutboundUrl {
443443
// we can always url encode the authority even if it is already encoded.
444444
if let Some(at) = url.find('@') {
445445
let scheme_end = url.find("://").map(|e| e + 3).unwrap_or(0);
446-
let userinfo = &url[scheme_end..at];
447-
448-
let encoded = urlencoding::encode(userinfo);
449-
let prefix = &url[..scheme_end];
450-
let suffix = &url[scheme_end + userinfo.len()..];
451-
url = format!("{prefix}{encoded}{suffix}");
446+
let path_start = url[scheme_end..]
447+
.find('/') // This can calculate the wrong index if the username or password contains a '/'
448+
.map(|e| e + scheme_end)
449+
.unwrap_or(usize::MAX);
450+
451+
if at < path_start {
452+
let userinfo = &url[scheme_end..at];
453+
454+
let encoded = urlencoding::encode(userinfo);
455+
let prefix = &url[..scheme_end];
456+
let suffix = &url[scheme_end + userinfo.len()..];
457+
url = format!("{prefix}{encoded}{suffix}");
458+
}
452459
}
453460

454461
let parsed = match url::Url::parse(&url) {
@@ -562,6 +569,25 @@ mod test {
562569
use super::*;
563570
use std::net::{Ipv4Addr, Ipv6Addr};
564571

572+
#[test]
573+
fn outbound_url_handles_at_in_paths() {
574+
let url = "https://example.com/[email protected]";
575+
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
576+
assert_eq!("example.com", url.host);
577+
578+
let url = "https://user:[email protected]/[email protected]";
579+
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
580+
assert_eq!("example.com", url.host);
581+
582+
let url = "https://user:pass#[email protected]/[email protected]";
583+
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
584+
assert_eq!("example.com", url.host);
585+
586+
let url = "https://user:[email protected]";
587+
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
588+
assert_eq!("example.com", url.host);
589+
}
590+
565591
#[test]
566592
fn test_allowed_hosts_accepts_url_without_port() {
567593
assert_eq!(

0 commit comments

Comments
 (0)