Skip to content

Commit

Permalink
Fix url splitting (#1989)
Browse files Browse the repository at this point in the history
# Description
Fixes #1988

# Changes
Added a helper function to split a URL into base and path which is used
for the `legacy` solver adapter.

## How to test
added a unit test
  • Loading branch information
MartinquaXD authored Oct 19, 2023
1 parent 8ded528 commit 3bb4797
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 10 deletions.
7 changes: 1 addition & 6 deletions crates/shared/src/price_estimation/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,12 +559,7 @@ impl PriceEstimatorCreating for HttpPriceEstimator {

impl From<&LegacySolver> for HttpPriceEstimatorParams {
fn from(solver: &LegacySolver) -> Self {
let base = {
let mut url = solver.url.clone();
url.set_path("");
url
};
let solve_path = solver.url.path().to_owned();
let (base, solve_path) = crate::url::split_at_path(&solver.url).unwrap();
Self {
base,
solve_path,
Expand Down
68 changes: 67 additions & 1 deletion crates/shared/src/url.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use url::Url;
use {
anyhow::{Context, Result},
url::Url,
};

/// Join a path with a URL, ensuring that there is only one slash between them.
/// It doesn't matter if the URL ends with a slash or the path starts with one.
Expand All @@ -12,3 +15,66 @@ pub fn join(url: &Url, mut path: &str) -> Url {
}
Url::parse(&format!("{url}/{path}")).unwrap()
}

/// Splits a URL right where the path begins into base and endpoint.
/// https://my.solver.xyz/solve/1?param=1#fragment=some
/// becomes
/// (https://my.solver.xyz/, /solve/1?param=1#fragment=some)
/// Path that were split like this can be joined to the original URL using
/// [`join`].
pub fn split_at_path(url: &Url) -> Result<(Url, String)> {
let base = format!(
"{}://{}{}/",
url.scheme(),
url.host().context("URL should have a host")?,
url.port()
.map(|port| format!(":{port}"))
.unwrap_or_default()
)
.parse()
.expect("stripping off the path is always safe");
let endpoint = format!(
"{}{}{}",
url.path(),
url.query()
.map(|params| format!("?{params}"))
.unwrap_or_default(),
url.fragment()
.map(|params| format!("#{params}"))
.unwrap_or_default(),
);
Ok((base, endpoint))
}

#[cfg(test)]
mod tests {
use super::*;

/// Tests that we can split a URL and join it back together without messing
/// up the URL on the way.
#[test]
fn split_and_join() {
let round_trip = |s: &str| {
let url = s.parse().unwrap();
let (base, endpoint) = split_at_path(&url).unwrap();
assert_eq!(url, join(&base, &endpoint));
};

// base + port + path + multiple params + multiple fragments
round_trip("https://my.solver.xyz:1234/solve/1?param1=1&param2=2#fragment=1&fragment2=2");
// base + path + multiple params + multiple fragments
round_trip("https://my.solver.xyz/solve/1?param1=1&param2=2#fragment=1&fragment2=2");
// base + path + multiple params
round_trip("https://my.solver.xyz/solve/1?param1=1&param2=2");
// base + path + multiple fragments
round_trip("https://my.solver.xyz/solve/1#fragment1=1&fragment2=2");
// base + path + single param + single fragment
round_trip("https://my.solver.xyz/solve/1?param=1#fragment1=1");
// base + path
round_trip("https://my.solver.xyz/solve/1");
// base
round_trip("http://my.solver.xyz");
// base + multiple params + multiple fragments
round_trip("https://my.solver.xyz?param1=1&param2=2#fragment=1&fragment2=2");
}
}
4 changes: 1 addition & 3 deletions crates/solvers/src/boundary/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ pub struct Legacy {

impl Legacy {
pub fn new(config: crate::domain::solver::legacy::Config) -> Self {
let solve_path = config.endpoint.path().to_owned();
let mut base = config.endpoint;
base.set_path("");
let (base, solve_path) = shared::url::split_at_path(&config.endpoint).unwrap();

Self {
solver: DefaultHttpSolverApi {
Expand Down

0 comments on commit 3bb4797

Please sign in to comment.