Skip to content

Commit 649565f

Browse files
committed
fix: [#811] 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
1 parent 2a45dcc commit 649565f

File tree

1 file changed

+87
-3
lines changed

1 file changed

+87
-3
lines changed

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+
}

0 commit comments

Comments
 (0)