Skip to content

Commit

Permalink
Fix @ in URL path confusing the parser
Browse files Browse the repository at this point in the history
Signed-off-by: itowlson <[email protected]>
  • Loading branch information
itowlson committed Nov 5, 2024
1 parent d833301 commit 227aa8c
Showing 1 changed file with 32 additions and 6 deletions.
38 changes: 32 additions & 6 deletions crates/factor-outbound-networking/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,19 @@ impl OutboundUrl {
// we can always url encode the authority even if it is already encoded.
if let Some(at) = url.find('@') {
let scheme_end = url.find("://").map(|e| e + 3).unwrap_or(0);
let userinfo = &url[scheme_end..at];

let encoded = urlencoding::encode(userinfo);
let prefix = &url[..scheme_end];
let suffix = &url[scheme_end + userinfo.len()..];
url = format!("{prefix}{encoded}{suffix}");
let path_start = url[scheme_end..]
.find('/') // This can calculate the wrong index if the username or password contains a '/'
.map(|e| e + scheme_end)
.unwrap_or(usize::MAX);

if at < path_start {
let userinfo = &url[scheme_end..at];

let encoded = urlencoding::encode(userinfo);
let prefix = &url[..scheme_end];
let suffix = &url[scheme_end + userinfo.len()..];
url = format!("{prefix}{encoded}{suffix}");
}
}

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

#[test]
fn outbound_url_handles_at_in_paths() {
let url = "https://example.com/[email protected]";
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
assert_eq!("example.com", url.host);

let url = "https://user:[email protected]/[email protected]";
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
assert_eq!("example.com", url.host);

let url = "https://user:pass#[email protected]/[email protected]";
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
assert_eq!("example.com", url.host);

let url = "https://user:[email protected]";
let url = OutboundUrl::parse(url, "https").expect("should have parsed url");
assert_eq!("example.com", url.host);
}

#[test]
fn test_allowed_hosts_accepts_url_without_port() {
assert_eq!(
Expand Down

0 comments on commit 227aa8c

Please sign in to comment.