diff --git a/src/web/api/v1/contexts/torrent/handlers.rs b/src/web/api/v1/contexts/torrent/handlers.rs index aaf6043f..ccb4a7a9 100644 --- a/src/web/api/v1/contexts/torrent/handlers.rs +++ b/src/web/api/v1/contexts/torrent/handlers.rs @@ -88,6 +88,25 @@ pub async fn get_torrents_handler(State(app_data): State>, Query(cr } } +#[allow(clippy::unused_async)] +pub async fn get_torrent_info_handler( + State(app_data): State>, + Extract(maybe_bearer_token): Extract, + Path(info_hash): Path, +) -> Response { + let Ok(info_hash) = InfoHash::from_str(&info_hash.0) else { return ServiceError::BadRequest.into_response() }; + + let opt_user_id = match get_optional_logged_in_user(maybe_bearer_token, app_data.clone()).await { + Ok(opt_user_id) => opt_user_id, + Err(err) => return err.into_response(), + }; + + match app_data.torrent_service.get_torrent_info(&info_hash, opt_user_id).await { + Ok(torrent_response) => Json(OkResponseData { data: torrent_response }).into_response(), + Err(err) => err.into_response(), + } +} + /// If the user is logged in, returns the user's ID. Otherwise, returns `None`. /// /// # Errors diff --git a/src/web/api/v1/contexts/torrent/routes.rs b/src/web/api/v1/contexts/torrent/routes.rs index 5618ef5b..61df6cac 100644 --- a/src/web/api/v1/contexts/torrent/routes.rs +++ b/src/web/api/v1/contexts/torrent/routes.rs @@ -6,14 +6,17 @@ use std::sync::Arc; use axum::routing::{get, post}; use axum::Router; -use super::handlers::{download_torrent_handler, get_torrents_handler, upload_torrent_handler}; +use super::handlers::{download_torrent_handler, get_torrent_info_handler, get_torrents_handler, upload_torrent_handler}; use crate::common::AppData; /// Routes for the [`torrent`](crate::web::api::v1::contexts::torrent) API context for single resources. pub fn router_for_single_resources(app_data: Arc) -> Router { + let torrent_info_routes = Router::new().route("/", get(get_torrent_info_handler).with_state(app_data.clone())); + Router::new() .route("/upload", post(upload_torrent_handler).with_state(app_data.clone())) .route("/download/:info_hash", get(download_torrent_handler).with_state(app_data)) + .nest("/:info_hash", torrent_info_routes) } /// Routes for the [`torrent`](crate::web::api::v1::contexts::torrent) API context for multiple resources. diff --git a/tests/e2e/contexts/torrent/contract.rs b/tests/e2e/contexts/torrent/contract.rs index 2f35786c..9aa8825f 100644 --- a/tests/e2e/contexts/torrent/contract.rs +++ b/tests/e2e/contexts/torrent/contract.rs @@ -632,13 +632,12 @@ mod with_axum_implementation { use torrust_index_backend::web::api; use crate::common::client::Client; - //use crate::common::contexts::category::fixtures::software_predefined_category_id; - //use crate::common::contexts::torrent::asserts::assert_expected_torrent_details; + use crate::common::contexts::category::fixtures::software_predefined_category_id; + use crate::common::contexts::torrent::asserts::assert_expected_torrent_details; use crate::common::contexts::torrent::requests::InfoHash; - use crate::common::contexts::torrent::responses::TorrentListResponse; - //use crate::common::contexts::torrent::responses::{ - // Category, File, TorrentDetails, TorrentDetailsResponse, TorrentListResponse, - //}; + use crate::common::contexts::torrent::responses::{ + Category, File, TorrentDetails, TorrentDetailsResponse, TorrentListResponse, + }; use crate::common::http::{Query, QueryParam}; use crate::e2e::config::ENV_VAR_E2E_EXCLUDE_AXUM_IMPL; use crate::e2e::contexts::torrent::asserts::expected_torrent; @@ -785,8 +784,6 @@ mod with_axum_implementation { assert!(response.is_json_and_ok()); } - /* - #[tokio::test] async fn it_should_allow_guests_to_get_torrent_details_searching_by_info_hash() { let mut env = TestEnv::new(); @@ -855,8 +852,6 @@ mod with_axum_implementation { assert!(response.is_json_and_ok()); } - */ - #[tokio::test] async fn it_should_allow_guests_to_download_a_torrent_file_searching_by_info_hash() { let mut env = TestEnv::new();