diff --git a/Cargo.lock b/Cargo.lock index c4755225f..c2d68639a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4380,6 +4380,7 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", + "url", ] [[package]] @@ -4512,6 +4513,7 @@ dependencies = [ "tokio", "tower-http", "tracing", + "url", ] [[package]] diff --git a/packages/axum-health-check-api-server/Cargo.toml b/packages/axum-health-check-api-server/Cargo.toml index e24e609bf..6766ce587 100644 --- a/packages/axum-health-check-api-server/Cargo.toml +++ b/packages/axum-health-check-api-server/Cargo.toml @@ -26,6 +26,7 @@ torrust-server-lib = { version = "3.0.0-develop", path = "../server-lib" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } tracing = "0" +url = "2.5.4" [dev-dependencies] reqwest = { version = "0", features = ["json"] } diff --git a/packages/axum-health-check-api-server/src/handlers.rs b/packages/axum-health-check-api-server/src/handlers.rs index 7e54d36ec..66390f089 100644 --- a/packages/axum-health-check-api-server/src/handlers.rs +++ b/packages/axum-health-check-api-server/src/handlers.rs @@ -31,6 +31,7 @@ pub(crate) async fn health_check_handler(State(register): State let jobs = checks.drain(..).map(|c| { tokio::spawn(async move { CheckReport { + listen_url: c.listen_url.clone(), binding: c.binding, info: c.info.clone(), service_type: c.service_type, diff --git a/packages/axum-health-check-api-server/src/resources.rs b/packages/axum-health-check-api-server/src/resources.rs index c01547fad..24079b00f 100644 --- a/packages/axum-health-check-api-server/src/resources.rs +++ b/packages/axum-health-check-api-server/src/resources.rs @@ -1,6 +1,7 @@ use std::net::SocketAddr; use serde::{Deserialize, Serialize}; +use url::Url; #[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] pub enum Status { @@ -11,6 +12,7 @@ pub enum Status { #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] pub struct CheckReport { + pub listen_url: Url, pub binding: SocketAddr, pub service_type: String, pub info: String, diff --git a/packages/axum-health-check-api-server/src/server.rs b/packages/axum-health-check-api-server/src/server.rs index 733fec3a0..cc721f5eb 100644 --- a/packages/axum-health-check-api-server/src/server.rs +++ b/packages/axum-health-check-api-server/src/server.rs @@ -25,6 +25,7 @@ use tower_http::request_id::{MakeRequestUuid, SetRequestIdLayer}; use tower_http::trace::{DefaultMakeSpan, TraceLayer}; use tower_http::LatencyUnit; use tracing::{instrument, Level, Span}; +use url::Url; use crate::handlers::health_check_handler; use crate::HEALTH_CHECK_API_LOG_TARGET; @@ -101,6 +102,9 @@ pub fn start( let socket = std::net::TcpListener::bind(bind_to).expect("Could not bind tcp_listener to address."); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); + let protocol = "http"; // The health check API only supports HTTP directly now. Use a reverse proxy for HTTPS. + let listen_url = + Url::parse(&format!("{protocol}://{address}")).expect("Could not parse internal service url for health check API."); let handle = Handle::new(); @@ -116,7 +120,7 @@ pub fn start( .handle(handle) .serve(router.into_make_service_with_connect_info::()); - tx.send(Started { address }) + tx.send(Started { listen_url, address }) .expect("the Health Check API server should not be dropped"); running diff --git a/packages/axum-http-tracker-server/src/server.rs b/packages/axum-http-tracker-server/src/server.rs index cc965e1d7..eefb124e8 100644 --- a/packages/axum-http-tracker-server/src/server.rs +++ b/packages/axum-http-tracker-server/src/server.rs @@ -7,6 +7,7 @@ use axum_server::Handle; use bittorrent_http_tracker_core::container::HttpTrackerCoreContainer; use derive_more::Constructor; use futures::future::BoxFuture; +use reqwest::Url; use tokio::sync::oneshot::{Receiver, Sender}; use torrust_axum_server::custom_axum_server::{self, TimeoutAcceptor}; use torrust_axum_server::signals::graceful_shutdown; @@ -63,8 +64,10 @@ impl Launcher { let tls = self.tls.clone(); let protocol = if tls.is_some() { "https" } else { "http" }; + let listen_url = + Url::parse(&format!("{protocol}://{address}")).expect("Could not parse internal service url for HTTP tracker."); - tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "Starting on: {protocol}://{}", address); + tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "Starting on: {protocol}://{address}"); let app = router(http_tracker_container, address); @@ -90,7 +93,7 @@ impl Launcher { tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "{STARTED_ON}: {protocol}://{}", address); tx_start - .send(Started { address }) + .send(Started { listen_url, address }) .expect("the HTTP(s) Tracker service should not be dropped"); running @@ -177,9 +180,12 @@ impl HttpServer { launcher }); - let binding = rx_start.await.expect("it should be able to start the service").address; + let started = rx_start.await.expect("it should be able to start the service"); - form.send(ServiceRegistration::new(binding, check_fn)) + let listen_url = started.listen_url; + let binding = started.address; + + form.send(ServiceRegistration::new(listen_url, binding, check_fn)) .expect("it should be able to send service registration"); Ok(HttpServer { @@ -220,7 +226,7 @@ impl HttpServer { /// This function will return an error if unable to connect. /// Or if the request returns an error. #[must_use] -pub fn check_fn(binding: &SocketAddr) -> ServiceHealthCheckJob { +pub fn check_fn(listen_url: &Url, binding: &SocketAddr) -> ServiceHealthCheckJob { let url = format!("http://{binding}/health_check"); // DevSkim: ignore DS137138 let info = format!("checking http tracker health check at: {url}"); @@ -232,7 +238,7 @@ pub fn check_fn(binding: &SocketAddr) -> ServiceHealthCheckJob { } }); - ServiceHealthCheckJob::new(*binding, info, TYPE_STRING.to_string(), job) + ServiceHealthCheckJob::new(listen_url.clone(), *binding, info, TYPE_STRING.to_string(), job) } #[cfg(test)] diff --git a/packages/axum-rest-tracker-api-server/Cargo.toml b/packages/axum-rest-tracker-api-server/Cargo.toml index 9c0d2bc2f..42fe68584 100644 --- a/packages/axum-rest-tracker-api-server/Cargo.toml +++ b/packages/axum-rest-tracker-api-server/Cargo.toml @@ -42,6 +42,7 @@ torrust-udp-tracker-server = { version = "3.0.0-develop", path = "../udp-tracker tower = { version = "0", features = ["timeout"] } tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } tracing = "0" +url = "2" [dev-dependencies] local-ip-address = "0" diff --git a/packages/axum-rest-tracker-api-server/src/server.rs b/packages/axum-rest-tracker-api-server/src/server.rs index 4d41347ab..20775dbc1 100644 --- a/packages/axum-rest-tracker-api-server/src/server.rs +++ b/packages/axum-rest-tracker-api-server/src/server.rs @@ -41,6 +41,7 @@ use torrust_server_lib::registar::{ServiceHealthCheckJob, ServiceRegistration, S use torrust_server_lib::signals::{Halted, Started}; use torrust_tracker_configuration::AccessTokens; use tracing::{instrument, Level}; +use url::Url; use super::routes::router; use crate::API_LOG_TARGET; @@ -148,7 +149,7 @@ impl ApiServer { let api_server = match rx_start.await { Ok(started) => { - form.send(ServiceRegistration::new(started.address, check_fn)) + form.send(ServiceRegistration::new(started.listen_url, started.address, check_fn)) .expect("it should be able to send service registration"); ApiServer { @@ -195,7 +196,7 @@ impl ApiServer { /// Or if there request returns an error code. #[must_use] #[instrument(skip())] -pub fn check_fn(binding: &SocketAddr) -> ServiceHealthCheckJob { +pub fn check_fn(listen_url: &Url, binding: &SocketAddr) -> ServiceHealthCheckJob { let url = format!("http://{binding}/api/health_check"); // DevSkim: ignore DS137138 let info = format!("checking api health check at: {url}"); @@ -206,7 +207,7 @@ pub fn check_fn(binding: &SocketAddr) -> ServiceHealthCheckJob { Err(err) => Err(err.to_string()), } }); - ServiceHealthCheckJob::new(*binding, info, TYPE_STRING.to_string(), job) + ServiceHealthCheckJob::new(listen_url.clone(), *binding, info, TYPE_STRING.to_string(), job) } /// A struct responsible for starting the API server. @@ -260,8 +261,10 @@ impl Launcher { let tls = self.tls.clone(); let protocol = if tls.is_some() { "https" } else { "http" }; + let listen_url = + Url::parse(&format!("{protocol}://{address}")).expect("Could not parse internal service url for tracker API."); - tracing::info!(target: API_LOG_TARGET, "Starting on {protocol}://{}", address); + tracing::info!(target: API_LOG_TARGET, "Starting on: {protocol}://{address}"); let running = Box::pin(async { match tls { @@ -282,10 +285,10 @@ impl Launcher { } }); - tracing::info!(target: API_LOG_TARGET, "{STARTED_ON} {protocol}://{}", address); + tracing::info!(target: API_LOG_TARGET, "{STARTED_ON}: {protocol}://{}", address); tx_start - .send(Started { address }) + .send(Started { listen_url, address }) .expect("the HTTP(s) Tracker API service should not be dropped"); running diff --git a/packages/server-lib/Cargo.toml b/packages/server-lib/Cargo.toml index b8514fbf4..514828953 100644 --- a/packages/server-lib/Cargo.toml +++ b/packages/server-lib/Cargo.toml @@ -18,5 +18,6 @@ derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } tracing = "0" +url = "2.5.4" [dev-dependencies] diff --git a/packages/server-lib/src/logging.rs b/packages/server-lib/src/logging.rs index c503cfd35..c63ba3caf 100644 --- a/packages/server-lib/src/logging.rs +++ b/packages/server-lib/src/logging.rs @@ -10,7 +10,7 @@ use tower_http::LatencyUnit; /// ```text /// 2024-06-25T12:36:25.025312Z INFO UDP TRACKER: Started on: udp://0.0.0.0:6969 /// 2024-06-25T12:36:25.025445Z INFO HTTP TRACKER: Started on: http://0.0.0.0:7070 -/// 2024-06-25T12:36:25.025527Z INFO API: Started on http://0.0.0.0:1212 +/// 2024-06-25T12:36:25.025527Z INFO API: Started on: http://0.0.0.0:1212 /// 2024-06-25T12:36:25.025580Z INFO HEALTH CHECK API: Started on: http://127.0.0.1:1313 /// ``` pub const STARTED_ON: &str = "Started on"; diff --git a/packages/server-lib/src/registar.rs b/packages/server-lib/src/registar.rs index 0a0e9ada0..9d36cf1fe 100644 --- a/packages/server-lib/src/registar.rs +++ b/packages/server-lib/src/registar.rs @@ -7,6 +7,7 @@ use std::sync::Arc; use derive_more::Constructor; use tokio::sync::Mutex; use tokio::task::JoinHandle; +use url::Url; /// A [`ServiceHeathCheckResult`] is returned by a completed health check. pub type ServiceHeathCheckResult = Result; @@ -16,6 +17,7 @@ pub type ServiceHeathCheckResult = Result; /// The `job` awaits a [`ServiceHeathCheckResult`]. #[derive(Debug, Constructor)] pub struct ServiceHealthCheckJob { + pub listen_url: Url, pub binding: SocketAddr, pub info: String, pub service_type: String, @@ -25,13 +27,14 @@ pub struct ServiceHealthCheckJob { /// The function specification [`FnSpawnServiceHeathCheck`]. /// /// A function fulfilling this specification will spawn a new [`ServiceHealthCheckJob`]. -pub type FnSpawnServiceHeathCheck = fn(&SocketAddr) -> ServiceHealthCheckJob; +pub type FnSpawnServiceHeathCheck = fn(&Url, &SocketAddr) -> ServiceHealthCheckJob; /// A [`ServiceRegistration`] is provided to the [`Registar`] for registration. /// /// Each registration includes a function that fulfils the [`FnSpawnServiceHeathCheck`] specification. #[derive(Clone, Debug, Constructor)] pub struct ServiceRegistration { + listen_url: Url, binding: SocketAddr, check_fn: FnSpawnServiceHeathCheck, } @@ -39,7 +42,7 @@ pub struct ServiceRegistration { impl ServiceRegistration { #[must_use] pub fn spawn_check(&self) -> ServiceHealthCheckJob { - (self.check_fn)(&self.binding) + (self.check_fn)(&self.listen_url, &self.binding) } } diff --git a/packages/server-lib/src/signals.rs b/packages/server-lib/src/signals.rs index 63f7554c8..94ee474ea 100644 --- a/packages/server-lib/src/signals.rs +++ b/packages/server-lib/src/signals.rs @@ -1,12 +1,14 @@ //! This module contains functions to handle signals. use derive_more::Display; use tracing::instrument; +use url::Url; /// This is the message that the "launcher" spawned task sends to the main /// application process to notify the service was successfully started. /// #[derive(Debug)] pub struct Started { + pub listen_url: Url, pub address: std::net::SocketAddr, } diff --git a/packages/udp-tracker-server/src/server/launcher.rs b/packages/udp-tracker-server/src/server/launcher.rs index 6473f300b..67e2ceed6 100644 --- a/packages/udp-tracker-server/src/server/launcher.rs +++ b/packages/udp-tracker-server/src/server/launcher.rs @@ -14,6 +14,7 @@ use torrust_server_lib::logging::STARTED_ON; use torrust_server_lib::registar::ServiceHealthCheckJob; use torrust_server_lib::signals::{shutdown_signal_with_message, Halted, Started}; use tracing::instrument; +use url::Url; use super::request_buffer::ActiveRequests; use crate::container::UdpTrackerServerContainer; @@ -65,6 +66,7 @@ impl Launcher { } }; + let listen_url = bound_socket.url().clone(); let address = bound_socket.address(); let local_udp_url = bound_socket.url().to_string(); @@ -89,7 +91,7 @@ impl Launcher { }; tx_start - .send(Started { address }) + .send(Started { listen_url, address }) .expect("the UDP Tracker service should not be dropped"); tracing::debug!(target: UDP_TRACKER_LOG_TARGET, local_udp_url, "Udp::run_with_graceful_shutdown (started)"); @@ -112,13 +114,13 @@ impl Launcher { #[must_use] #[instrument(skip(binding))] - pub fn check(binding: &SocketAddr) -> ServiceHealthCheckJob { + pub fn check(listen_url: &Url, binding: &SocketAddr) -> ServiceHealthCheckJob { let binding = *binding; let info = format!("checking the udp tracker health check at: {binding}"); let job = tokio::spawn(async move { check(&binding).await }); - ServiceHealthCheckJob::new(binding, info, TYPE_STRING.to_string(), job) + ServiceHealthCheckJob::new(listen_url.clone(), binding, info, TYPE_STRING.to_string(), job) } #[instrument(skip(receiver, udp_tracker_core_container, udp_tracker_server_container))] diff --git a/packages/udp-tracker-server/src/server/states.rs b/packages/udp-tracker-server/src/server/states.rs index 4d1c97167..f10a02fb7 100644 --- a/packages/udp-tracker-server/src/server/states.rs +++ b/packages/udp-tracker-server/src/server/states.rs @@ -83,9 +83,12 @@ impl Server { rx_halt, ); - let local_addr = rx_start.await.expect("it should be able to start the service").address; + let started = rx_start.await.expect("it should be able to start the service"); - form.send(ServiceRegistration::new(local_addr, Launcher::check)) + let listen_url = started.listen_url; + let local_addr = started.address; + + form.send(ServiceRegistration::new(listen_url, local_addr, Launcher::check)) .expect("it should be able to send service registration"); let running_udp_server: Server = Server { diff --git a/src/console/ci/e2e/logs_parser.rs b/src/console/ci/e2e/logs_parser.rs index c406fa7a5..e8b6b3b8f 100644 --- a/src/console/ci/e2e/logs_parser.rs +++ b/src/console/ci/e2e/logs_parser.rs @@ -31,8 +31,8 @@ impl RunningServices { /// 2024-06-10T16:07:39.990303Z INFO HTTP TRACKER: Starting on: http://0.0.0.0:7070 /// 2024-06-10T16:07:39.990439Z INFO HTTP TRACKER: Started on: http://0.0.0.0:7070 /// 2024-06-10T16:07:39.990448Z INFO torrust_tracker::bootstrap::jobs: TLS not enabled - /// 2024-06-10T16:07:39.990563Z INFO API: Starting on http://127.0.0.1:1212 - /// 2024-06-10T16:07:39.990565Z INFO API: Started on http://127.0.0.1:1212 + /// 2024-06-10T16:07:39.990563Z INFO API: Starting on: http://127.0.0.1:1212 + /// 2024-06-10T16:07:39.990565Z INFO API: Started on: http://127.0.0.1:1212 /// 2024-06-10T16:07:39.990577Z INFO HEALTH CHECK API: Starting on: http://127.0.0.1:1313 /// 2024-06-10T16:07:39.990638Z INFO HEALTH CHECK API: Started on: http://127.0.0.1:1313 /// ``` @@ -122,8 +122,8 @@ mod tests { 2024-06-10T16:07:39.990303Z INFO HTTP TRACKER: Starting on: http://0.0.0.0:7070 2024-06-10T16:07:39.990439Z INFO HTTP TRACKER: Started on: http://0.0.0.0:7070 2024-06-10T16:07:39.990448Z INFO torrust_tracker::bootstrap::jobs: TLS not enabled - 2024-06-10T16:07:39.990563Z INFO API: Starting on http://127.0.0.1:1212 - 2024-06-10T16:07:39.990565Z INFO API: Started on http://127.0.0.1:1212 + 2024-06-10T16:07:39.990563Z INFO API: Starting on: http://127.0.0.1:1212 + 2024-06-10T16:07:39.990565Z INFO API: Started on: http://127.0.0.1:1212 2024-06-10T16:07:39.990577Z INFO HEALTH CHECK API: Starting on: http://127.0.0.1:1313 2024-06-10T16:07:39.990638Z INFO HEALTH CHECK API: Started on: http://127.0.0.1:1313 ";