Allow instance_uri configuration value to contain URI scheme
This commit is contained in:
parent
4ab95055d6
commit
0b8553d0c2
5 changed files with 69 additions and 18 deletions
|
@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Allow `instance_uri` configuration value to contain URI scheme.
|
||||||
|
|
||||||
## [1.13.1] - 2023-02-09
|
## [1.13.1] - 2023-02-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -5,7 +5,8 @@ web_client_dir: null
|
||||||
http_host: '127.0.0.1'
|
http_host: '127.0.0.1'
|
||||||
http_port: 8380
|
http_port: 8380
|
||||||
|
|
||||||
instance_uri: 127.0.0.1:8380
|
instance_uri: http://127.0.0.1:8380
|
||||||
|
|
||||||
instance_title: Mitra
|
instance_title: Mitra
|
||||||
instance_short_description: My instance
|
instance_short_description: My instance
|
||||||
instance_description: My instance
|
instance_description: My instance
|
||||||
|
|
|
@ -12,7 +12,8 @@ http_port: 8383
|
||||||
#log_level: info
|
#log_level: info
|
||||||
|
|
||||||
# Domain name
|
# Domain name
|
||||||
instance_uri: example.tld
|
instance_uri: https://example.tld
|
||||||
|
|
||||||
instance_title: example
|
instance_title: example
|
||||||
instance_short_description: my instance
|
instance_short_description: my instance
|
||||||
# Long description can contain markdown syntax
|
# Long description can contain markdown syntax
|
||||||
|
|
|
@ -9,7 +9,7 @@ use serde::{
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::utils::urls::guess_protocol;
|
use crate::utils::urls::normalize_url;
|
||||||
|
|
||||||
use super::blockchain::BlockchainConfig;
|
use super::blockchain::BlockchainConfig;
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
|
@ -78,7 +78,9 @@ pub struct Config {
|
||||||
pub log_level: LogLevel,
|
pub log_level: LogLevel,
|
||||||
|
|
||||||
// Domain name or <IP address>:<port>
|
// Domain name or <IP address>:<port>
|
||||||
|
// URI scheme is optional
|
||||||
instance_uri: String,
|
instance_uri: String,
|
||||||
|
|
||||||
pub instance_title: String,
|
pub instance_title: String,
|
||||||
pub instance_short_description: String,
|
pub instance_short_description: String,
|
||||||
pub instance_description: String,
|
pub instance_description: String,
|
||||||
|
@ -121,14 +123,7 @@ pub struct Config {
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub(super) fn try_instance_url(&self) -> Result<Url, url::ParseError> {
|
pub(super) fn try_instance_url(&self) -> Result<Url, url::ParseError> {
|
||||||
let scheme = match self.environment {
|
normalize_url(&self.instance_uri)
|
||||||
Environment::Development => "http",
|
|
||||||
Environment::Production => guess_protocol(&self.instance_uri),
|
|
||||||
};
|
|
||||||
let url_str = format!("{}://{}", scheme, self.instance_uri);
|
|
||||||
let url = Url::parse(&url_str)?;
|
|
||||||
url.host().ok_or(url::ParseError::EmptyHost)?; // validates URL
|
|
||||||
Ok(url)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instance(&self) -> Instance {
|
pub fn instance(&self) -> Instance {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::net::Ipv6Addr;
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use url::{Host, ParseError, Url};
|
use url::{Host, ParseError, Url};
|
||||||
|
|
||||||
pub fn get_hostname(url: &str) -> Result<String, ParseError> {
|
pub fn get_hostname(url: &str) -> Result<String, ParseError> {
|
||||||
|
@ -14,13 +14,13 @@ pub fn get_hostname(url: &str) -> Result<String, ParseError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guess_protocol(hostname: &str) -> &'static str {
|
pub fn guess_protocol(hostname: &str) -> &'static str {
|
||||||
let maybe_ipv6_address = hostname.parse::<Ipv6Addr>();
|
let maybe_ipv4_address = hostname.parse::<Ipv4Addr>();
|
||||||
if let Ok(ipv6_address) = maybe_ipv6_address {
|
if let Ok(_ipv4_address) = maybe_ipv4_address {
|
||||||
let prefix = ipv6_address.segments()[0];
|
|
||||||
if (0x0200..=0x03ff).contains(&prefix) {
|
|
||||||
// Yggdrasil
|
|
||||||
return "http";
|
return "http";
|
||||||
};
|
};
|
||||||
|
let maybe_ipv6_address = hostname.parse::<Ipv6Addr>();
|
||||||
|
if let Ok(_ipv6_address) = maybe_ipv6_address {
|
||||||
|
return "http";
|
||||||
};
|
};
|
||||||
if hostname.ends_with(".onion") || hostname.ends_with(".i2p") {
|
if hostname.ends_with(".onion") || hostname.ends_with(".i2p") {
|
||||||
// Tor / I2P
|
// Tor / I2P
|
||||||
|
@ -31,9 +31,36 @@ pub fn guess_protocol(hostname: &str) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn normalize_url(url: &str) -> Result<Url, url::ParseError> {
|
||||||
|
let normalized_url = if
|
||||||
|
url.starts_with("http://") ||
|
||||||
|
url.starts_with("https://")
|
||||||
|
{
|
||||||
|
url.to_string()
|
||||||
|
} else {
|
||||||
|
// Add scheme
|
||||||
|
// Doesn't work for IPv6
|
||||||
|
let hostname = if let Some((hostname, _port)) = url.split_once(':') {
|
||||||
|
hostname
|
||||||
|
} else {
|
||||||
|
url
|
||||||
|
};
|
||||||
|
let url_scheme = guess_protocol(hostname);
|
||||||
|
format!(
|
||||||
|
"{}://{}",
|
||||||
|
url_scheme,
|
||||||
|
url,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let url = Url::parse(&normalized_url)?;
|
||||||
|
url.host().ok_or(ParseError::EmptyHost)?; // validates URL
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_hostname() {
|
fn test_get_hostname() {
|
||||||
let url = "https://example.org/objects/1";
|
let url = "https://example.org/objects/1";
|
||||||
|
@ -41,6 +68,13 @@ mod tests {
|
||||||
assert_eq!(hostname, "example.org");
|
assert_eq!(hostname, "example.org");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_hostname_if_port_number() {
|
||||||
|
let url = "http://127.0.0.1:8380/objects/1";
|
||||||
|
let hostname = get_hostname(url).unwrap();
|
||||||
|
assert_eq!(hostname, "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_hostname_tor() {
|
fn test_get_hostname_tor() {
|
||||||
let url = "http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/objects/1";
|
let url = "http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/objects/1";
|
||||||
|
@ -76,9 +110,25 @@ mod tests {
|
||||||
guess_protocol("zzz.i2p"),
|
guess_protocol("zzz.i2p"),
|
||||||
"http",
|
"http",
|
||||||
);
|
);
|
||||||
|
// Yggdrasil
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
guess_protocol("319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be"),
|
guess_protocol("319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be"),
|
||||||
"http",
|
"http",
|
||||||
);
|
);
|
||||||
|
// localhost
|
||||||
|
assert_eq!(
|
||||||
|
guess_protocol("127.0.0.1"),
|
||||||
|
"http",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_normalize_url() {
|
||||||
|
let result = normalize_url("https://test.net").unwrap();
|
||||||
|
assert_eq!(result.to_string(), "https://test.net/");
|
||||||
|
let result = normalize_url("example.com").unwrap();
|
||||||
|
assert_eq!(result.to_string(), "https://example.com/");
|
||||||
|
let result = normalize_url("127.0.0.1:8380").unwrap();
|
||||||
|
assert_eq!(result.to_string(), "http://127.0.0.1:8380/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue