Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rattler_networking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ system-integration = ["keyring", "netrc-rs", "dirs"]
features = ["gcs", "s3"]

[dependencies]
rattler_conda_types = { workspace = true }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm sucks a little bit that we have to add this dependency just to get to that type. Maybe we should not do it and use your previous fix instead. Sorry for the noise.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm sucks a little bit that we have to add this dependency just to get to that type. Maybe we should not do it and use your previous fix instead. Sorry for the noise.

no worries about the noise i agree that adding a dependency just for that type might not be ideal if you'd prefer the previous implementation i can revert the change and update the pr

anyhow = { workspace = true }
async-once-cell = { workspace = true }
async-trait = { workspace = true }
Expand Down
49 changes: 48 additions & 1 deletion crates/rattler_networking/src/mirror_middleware.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Middleware to handle mirrors
use rattler_conda_types::utils::url_with_trailing_slash::UrlWithTrailingSlash;
use std::{
collections::HashMap,
sync::atomic::{self, AtomicUsize},
Expand Down Expand Up @@ -118,7 +119,9 @@ impl Middleware for MirrorMiddleware {
};

let mirror = &selected_mirror.mirror;
let selected_url = mirror.url.join(url_rest).unwrap();

let base = UrlWithTrailingSlash::from(mirror.url.clone());
let selected_url = base.as_ref().join(url_rest).unwrap();

// Short-circuit if the mirror does not support the file type
if url_rest.ends_with(".json.zst") && mirror.no_zstd {
Expand Down Expand Up @@ -301,4 +304,48 @@ mod test {
len = path.0.len();
}
}

#[tokio::test]
async fn test_mirror_middleware_path_rewrite() {
// Start a server that serves at /channel/count
let state = String::from("mirror server");
let router = Router::new()
.route("/channel/count", get(count))
.with_state(state);

let addr = SocketAddr::new([127, 0, 0, 1].into(), 0);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
let addr = listener.local_addr().unwrap();
tokio::spawn(axum::serve(listener, router.into_make_service()).into_future());

let mirror_url: Url = format!("http://{}:{}/channel", addr.ip(), addr.port())
.parse()
.unwrap();

let mut mirror_map = std::collections::HashMap::new();

// Upstream key includes a path segment (e.g. conda-forge)
// Mirror URL also has a path segment (e.g. channel)
// The mirror path must fully replace the upstream path.
mirror_map.insert(
"https://prefix.dev/conda-forge".parse().unwrap(),
vec![mirror_setting(mirror_url)],
);

let middleware = MirrorMiddleware::from_map(mirror_map);
let client = reqwest_middleware::ClientBuilder::new(reqwest::Client::new())
.with(middleware)
.build();

// Request to upstream: https://prefix.dev/conda-forge/count
// Should be rewritten to: http://127.0.0.1:PORT/channel/count
let res = client
.get("https://prefix.dev/conda-forge/count")
.send()
.await
.unwrap();
assert!(res.status().is_success(), "status: {}", res.status());
let body = res.text().await.unwrap();
assert_eq!(body, "Hi from counter: mirror server");
}
}
Loading