Skip to content

Commit f9c17f3

Browse files
committed
Merge #812: Fix missing tracker key in torrent
17aecf9 fix: clippy warnings (Jose Celano) 649565f fix: [#811] missing tracker key in torrent (Jose Celano) Pull request description: Fix missing tracker key in torrent when the tracker URL doesn't have a trailing slash. For example, this tracker URL in the configuration: https://127.0.0.1:7070/announce produces this tracker URL in the torrent: https://127.0.0.1:7070/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7 and it should produce: https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7 ACKs for top commit: josecelano: ACK 17aecf9 Tree-SHA512: a90254f6b6062449d1587ef8257ffd42b57d6e500caa345b4b0902494a1032ed4f6b2666f8ebf7980526e195504a521fdc113265a60581695d05612f722d57d1
2 parents 2a45dcc + 17aecf9 commit f9c17f3

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

src/config/v2/net.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl Network {
4646
}
4747

4848
fn default_ip() -> IpAddr {
49-
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
49+
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
5050
}
5151

5252
fn default_port() -> u16 {

src/tracker/api.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const TOTAL_REQUEST_TIMEOUT_IN_SECS: u64 = 5;
2323
pub struct Client {
2424
pub connection_info: ConnectionInfo,
2525
api_base_url: Url,
26-
client: reqwest::Client,
26+
http: reqwest::Client,
2727
token_param: [(String, String); 1],
2828
}
2929

@@ -45,7 +45,7 @@ impl Client {
4545
Ok(Self {
4646
connection_info,
4747
api_base_url,
48-
client,
48+
http: client,
4949
token_param,
5050
})
5151
}
@@ -58,7 +58,7 @@ impl Client {
5858
pub async fn whitelist_torrent(&self, info_hash: &str) -> Result<Response, Error> {
5959
let request_url = format!("{}/whitelist/{}", self.api_base_url, info_hash);
6060

61-
self.client.post(request_url).query(&self.token_param).send().await
61+
self.http.post(request_url).query(&self.token_param).send().await
6262
}
6363

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

72-
self.client.delete(request_url).query(&self.token_param).send().await
72+
self.http.delete(request_url).query(&self.token_param).send().await
7373
}
7474

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

83-
self.client.post(request_url).query(&self.token_param).send().await
83+
self.http.post(request_url).query(&self.token_param).send().await
8484
}
8585

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

94-
self.client.get(request_url).query(&self.token_param).send().await
94+
self.http.get(request_url).query(&self.token_param).send().await
9595
}
9696

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

113-
self.client.get(request_url).query(&query_params).send().await
113+
self.http.get(request_url).query(&query_params).send().await
114114
}
115115
}

src/tracker/service.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,7 @@ impl Service {
376376
/// It builds the announce url appending the user tracker key.
377377
/// Eg: <https://tracker:7070/USER_TRACKER_KEY>
378378
fn announce_url_with_key(&self, tracker_key: &TrackerKey) -> Url {
379-
self.tracker_url
380-
.join(&tracker_key.key)
381-
.expect("a tracker key should be added to the tracker base URL")
379+
build_announce_url_with_key(&self.tracker_url, &tracker_key.key)
382380
}
383381

384382
fn invalid_token_body() -> String {
@@ -390,8 +388,94 @@ impl Service {
390388
}
391389
}
392390

391+
/// Builds the announce URL by properly appending the tracker key to the base URL.
392+
///
393+
/// This function handles the case where the base URL ends with a path segment (like "/announce")
394+
/// and ensures the tracker key is appended as a new path segment rather than replacing the last one.
395+
///
396+
/// # Arguments
397+
/// * `base_url` - The base tracker URL (e.g., `<https://127.0.0.1:7070/announce>`)
398+
/// * `tracker_key` - The user's tracker key to append
399+
///
400+
/// # Returns
401+
/// A URL with the tracker key properly appended (e.g., `<https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7>`)
402+
fn build_announce_url_with_key(base_url: &Url, tracker_key: &str) -> Url {
403+
let mut url = base_url.clone();
404+
405+
// Ensure the path ends with a trailing slash so join() appends rather than replaces
406+
if !url.path().ends_with('/') {
407+
url.set_path(&format!("{}/", url.path()));
408+
}
409+
410+
url.join(tracker_key).expect("tracker key should be a valid URL segment")
411+
}
412+
393413
/// Temporary patch to map `StatusCode` from crate `http` 0.2.11 to `http` v1.0.0
394414
/// until `reqwest` upgrades to hyper 1.0. See <https://github.com/seanmonstar/reqwest/issues/2039>
395415
fn map_status_code(status: reqwest::StatusCode) -> hyper::StatusCode {
396416
StatusCode::from_u16(status.as_u16()).unwrap()
397417
}
418+
419+
#[cfg(test)]
420+
mod tests {
421+
use super::*;
422+
423+
#[test]
424+
fn test_build_announce_url_with_key_with_announce_path() {
425+
let base_url = Url::parse("https://127.0.0.1:7070/announce").unwrap();
426+
let tracker_key = "mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7";
427+
428+
let result = build_announce_url_with_key(&base_url, tracker_key);
429+
430+
assert_eq!(
431+
result.to_string(),
432+
"https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7"
433+
);
434+
}
435+
436+
#[test]
437+
fn test_build_announce_url_with_key_with_trailing_slash() {
438+
let base_url = Url::parse("https://127.0.0.1:7070/announce/").unwrap();
439+
let tracker_key = "mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7";
440+
441+
let result = build_announce_url_with_key(&base_url, tracker_key);
442+
443+
assert_eq!(
444+
result.to_string(),
445+
"https://127.0.0.1:7070/announce/mCGfCr8nvixxA0h8B4iz0sT8V3FIQLi7"
446+
);
447+
}
448+
449+
#[test]
450+
fn test_build_announce_url_with_key_root_path() {
451+
let base_url = Url::parse("https://tracker.example.com/").unwrap();
452+
let tracker_key = "testkey123";
453+
454+
let result = build_announce_url_with_key(&base_url, tracker_key);
455+
456+
assert_eq!(result.to_string(), "https://tracker.example.com/testkey123");
457+
}
458+
459+
#[test]
460+
fn test_build_announce_url_with_key_no_path() {
461+
let base_url = Url::parse("https://tracker.example.com").unwrap();
462+
let tracker_key = "testkey123";
463+
464+
let result = build_announce_url_with_key(&base_url, tracker_key);
465+
466+
assert_eq!(result.to_string(), "https://tracker.example.com/testkey123");
467+
}
468+
469+
#[test]
470+
fn test_build_announce_url_with_key_multiple_path_segments() {
471+
let base_url = Url::parse("https://tracker.example.com/api/v1/announce").unwrap();
472+
let tracker_key = "complexkey456";
473+
474+
let result = build_announce_url_with_key(&base_url, tracker_key);
475+
476+
assert_eq!(
477+
result.to_string(),
478+
"https://tracker.example.com/api/v1/announce/complexkey456"
479+
);
480+
}
481+
}

tests/environments/isolated.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn ephemeral(temp_dir: &TempDir) -> config::Settings {
7979
configuration.logging.threshold = Threshold::Off; // Change to `debug` for tests debugging
8080

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

8484
// Ephemeral Importer API port
8585
configuration.tracker_statistics_importer.port = FREE_PORT;

0 commit comments

Comments
 (0)