Skip to content

Commit 9b7c5c8

Browse files
committed
feat: [#488] panic starting the app when tracker config is invalid
For the time being, it only checks that private tracker don't use UDP.
1 parent 36e46fe commit 9b7c5c8

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

src/app.rs

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
3939

4040
logging::setup(&log_level);
4141

42+
configuration.validate().await.expect("invalid configuration");
43+
4244
let configuration = Arc::new(configuration);
4345

4446
// Get configuration settings needed to build the app dependencies and

src/config.rs

+53
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
99
use thiserror::Error;
1010
use tokio::sync::RwLock;
1111
use torrust_index_located_error::{Located, LocatedError};
12+
use url::{ParseError, Url};
1213

1314
/// Information required for loading config
1415
#[derive(Debug, Default, Clone)]
@@ -99,6 +100,17 @@ pub enum Error {
99100
Infallible,
100101
}
101102

103+
/// Errors that can occur validating the configuration.
104+
#[derive(Error, Debug)]
105+
pub enum ValidationError {
106+
/// Unable to load the configuration from the configuration file.
107+
#[error("Invalid tracker URL: {source}")]
108+
InvalidTrackerUrl { source: LocatedError<'static, ParseError> },
109+
110+
#[error("UDP private trackers are not supported. URL schemes for private tracker URLs must be HTTP ot HTTPS")]
111+
UdpTrackersInPrivateModeNotSupported,
112+
}
113+
102114
impl From<ConfigError> for Error {
103115
#[track_caller]
104116
fn from(err: ConfigError) -> Self {
@@ -149,6 +161,11 @@ impl TrackerMode {
149161
pub fn is_open(&self) -> bool {
150162
matches!(self, TrackerMode::Public | TrackerMode::Whitelisted)
151163
}
164+
165+
#[must_use]
166+
pub fn is_close(&self) -> bool {
167+
!self.is_open()
168+
}
152169
}
153170

154171
/// Configuration for the associated tracker.
@@ -550,6 +567,42 @@ impl Configuration {
550567

551568
settings_lock.net.base_url.clone()
552569
}
570+
571+
/// # Errors
572+
///
573+
/// Will return an error if the configuration is invalid.
574+
pub async fn validate(&self) -> Result<(), ValidationError> {
575+
self.validate_tracker_config().await
576+
}
577+
578+
/// # Errors
579+
///
580+
/// Will return an error if the `tracker` configuration section is invalid.
581+
pub async fn validate_tracker_config(&self) -> Result<(), ValidationError> {
582+
let settings_lock = self.settings.read().await;
583+
584+
let tracker_mode = settings_lock.tracker.mode.clone();
585+
let tracker_url = settings_lock.tracker.url.clone();
586+
587+
let tracker_url = match parse_url(&tracker_url) {
588+
Ok(url) => url,
589+
Err(err) => {
590+
return Err(ValidationError::InvalidTrackerUrl {
591+
source: Located(err).into(),
592+
})
593+
}
594+
};
595+
596+
if tracker_mode.is_close() && (tracker_url.scheme() != "http" && tracker_url.scheme() != "https") {
597+
return Err(ValidationError::UdpTrackersInPrivateModeNotSupported);
598+
}
599+
600+
Ok(())
601+
}
602+
}
603+
604+
fn parse_url(url_str: &str) -> Result<Url, url::ParseError> {
605+
Url::parse(url_str)
553606
}
554607

555608
/// The public index configuration.

0 commit comments

Comments
 (0)