Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/config/v2/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Network {
}

fn default_ip() -> IpAddr {
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
}

fn default_port() -> u16 {
Expand Down
14 changes: 7 additions & 7 deletions src/tracker/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const TOTAL_REQUEST_TIMEOUT_IN_SECS: u64 = 5;
pub struct Client {
pub connection_info: ConnectionInfo,
api_base_url: Url,
client: reqwest::Client,
http: reqwest::Client,
token_param: [(String, String); 1],
}

Expand All @@ -45,7 +45,7 @@ impl Client {
Ok(Self {
connection_info,
api_base_url,
client,
http: client,
token_param,
})
}
Expand All @@ -58,7 +58,7 @@ impl Client {
pub async fn whitelist_torrent(&self, info_hash: &str) -> Result<Response, Error> {
let request_url = format!("{}/whitelist/{}", self.api_base_url, info_hash);

self.client.post(request_url).query(&self.token_param).send().await
self.http.post(request_url).query(&self.token_param).send().await
}

/// Remove a torrent from the tracker whitelist.
Expand All @@ -69,7 +69,7 @@ impl Client {
pub async fn remove_torrent_from_whitelist(&self, info_hash: &str) -> Result<Response, Error> {
let request_url = format!("{}/whitelist/{}", self.api_base_url, info_hash);

self.client.delete(request_url).query(&self.token_param).send().await
self.http.delete(request_url).query(&self.token_param).send().await
}

/// Retrieve a new tracker key.
Expand All @@ -80,7 +80,7 @@ impl Client {
pub async fn retrieve_new_tracker_key(&self, token_valid_seconds: u64) -> Result<Response, Error> {
let request_url = format!("{}/key/{}", self.api_base_url, token_valid_seconds);

self.client.post(request_url).query(&self.token_param).send().await
self.http.post(request_url).query(&self.token_param).send().await
}

/// Retrieve the info for one torrent.
Expand All @@ -91,7 +91,7 @@ impl Client {
pub async fn get_torrent_info(&self, info_hash: &str) -> Result<Response, Error> {
let request_url = format!("{}/torrent/{}", self.api_base_url, info_hash);

self.client.get(request_url).query(&self.token_param).send().await
self.http.get(request_url).query(&self.token_param).send().await
}

/// Retrieve the info for multiple torrents at the same time.
Expand All @@ -110,6 +110,6 @@ impl Client {
query_params.push(("info_hash".to_string(), info_hash.clone()));
}

self.client.get(request_url).query(&query_params).send().await
self.http.get(request_url).query(&query_params).send().await
}
}
90 changes: 87 additions & 3 deletions src/tracker/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,7 @@ impl Service {
/// It builds the announce url appending the user tracker key.
/// Eg: <https://tracker:7070/USER_TRACKER_KEY>
fn announce_url_with_key(&self, tracker_key: &TrackerKey) -> Url {
self.tracker_url
.join(&tracker_key.key)
.expect("a tracker key should be added to the tracker base URL")
build_announce_url_with_key(&self.tracker_url, &tracker_key.key)
}

fn invalid_token_body() -> String {
Expand All @@ -390,8 +388,94 @@ impl Service {
}
}

/// Builds the announce URL by properly appending the tracker key to the base URL.
///
/// This function handles the case where the base URL ends with a path segment (like "/announce")
/// and ensures the tracker key is appended as a new path segment rather than replacing the last one.
///
/// # Arguments
/// * `base_url` - The base tracker URL (e.g., `<https://127.0.0.1:7070/announce>`)
/// * `tracker_key` - The user's tracker key to append
///
/// # Returns
/// A URL with the tracker key properly appended (e.g., `<https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7>`)
fn build_announce_url_with_key(base_url: &Url, tracker_key: &str) -> Url {
let mut url = base_url.clone();

// Ensure the path ends with a trailing slash so join() appends rather than replaces
if !url.path().ends_with('/') {
url.set_path(&format!("{}/", url.path()));
}

url.join(tracker_key).expect("tracker key should be a valid URL segment")
}

/// Temporary patch to map `StatusCode` from crate `http` 0.2.11 to `http` v1.0.0
/// until `reqwest` upgrades to hyper 1.0. See <https://github.com/seanmonstar/reqwest/issues/2039>
fn map_status_code(status: reqwest::StatusCode) -> hyper::StatusCode {
StatusCode::from_u16(status.as_u16()).unwrap()
}

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

#[test]
fn test_build_announce_url_with_key_with_announce_path() {
let base_url = Url::parse("https://127.0.0.1:7070/announce").unwrap();
let tracker_key = "mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7";

let result = build_announce_url_with_key(&base_url, tracker_key);

assert_eq!(
result.to_string(),
"https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7"
);
}

#[test]
fn test_build_announce_url_with_key_with_trailing_slash() {
let base_url = Url::parse("https://127.0.0.1:7070/announce/").unwrap();
let tracker_key = "mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7";

let result = build_announce_url_with_key(&base_url, tracker_key);

assert_eq!(
result.to_string(),
"https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7"
);
}

#[test]
fn test_build_announce_url_with_key_root_path() {
let base_url = Url::parse("https://tracker.example.com/").unwrap();
let tracker_key = "testkey123";

let result = build_announce_url_with_key(&base_url, tracker_key);

assert_eq!(result.to_string(), "https://tracker.example.com/testkey123");
}

#[test]
fn test_build_announce_url_with_key_no_path() {
let base_url = Url::parse("https://tracker.example.com").unwrap();
let tracker_key = "testkey123";

let result = build_announce_url_with_key(&base_url, tracker_key);

assert_eq!(result.to_string(), "https://tracker.example.com/testkey123");
}

#[test]
fn test_build_announce_url_with_key_multiple_path_segments() {
let base_url = Url::parse("https://tracker.example.com/api/v1/announce").unwrap();
let tracker_key = "complexkey456";

let result = build_announce_url_with_key(&base_url, tracker_key);

assert_eq!(
result.to_string(),
"https://tracker.example.com/api/v1/announce/complexkey456"
);
}
}
2 changes: 1 addition & 1 deletion tests/environments/isolated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fn ephemeral(temp_dir: &TempDir) -> config::Settings {
configuration.logging.threshold = Threshold::Off; // Change to `debug` for tests debugging

// Ephemeral API port
configuration.net.bind_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), FREE_PORT);
configuration.net.bind_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), FREE_PORT);

// Ephemeral Importer API port
configuration.tracker_statistics_importer.port = FREE_PORT;
Expand Down
Loading