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]
|
||||
|
||||
### Changed
|
||||
|
||||
- Allow `instance_uri` configuration value to contain URI scheme.
|
||||
|
||||
## [1.13.1] - 2023-02-09
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -5,7 +5,8 @@ web_client_dir: null
|
|||
http_host: '127.0.0.1'
|
||||
http_port: 8380
|
||||
|
||||
instance_uri: 127.0.0.1:8380
|
||||
instance_uri: http://127.0.0.1:8380
|
||||
|
||||
instance_title: Mitra
|
||||
instance_short_description: My instance
|
||||
instance_description: My instance
|
||||
|
|
|
@ -12,7 +12,8 @@ http_port: 8383
|
|||
#log_level: info
|
||||
|
||||
# Domain name
|
||||
instance_uri: example.tld
|
||||
instance_uri: https://example.tld
|
||||
|
||||
instance_title: example
|
||||
instance_short_description: my instance
|
||||
# Long description can contain markdown syntax
|
||||
|
|
|
@ -9,7 +9,7 @@ use serde::{
|
|||
};
|
||||
use url::Url;
|
||||
|
||||
use crate::utils::urls::guess_protocol;
|
||||
use crate::utils::urls::normalize_url;
|
||||
|
||||
use super::blockchain::BlockchainConfig;
|
||||
use super::environment::Environment;
|
||||
|
@ -78,7 +78,9 @@ pub struct Config {
|
|||
pub log_level: LogLevel,
|
||||
|
||||
// Domain name or <IP address>:<port>
|
||||
// URI scheme is optional
|
||||
instance_uri: String,
|
||||
|
||||
pub instance_title: String,
|
||||
pub instance_short_description: String,
|
||||
pub instance_description: String,
|
||||
|
@ -121,14 +123,7 @@ pub struct Config {
|
|||
|
||||
impl Config {
|
||||
pub(super) fn try_instance_url(&self) -> Result<Url, url::ParseError> {
|
||||
let scheme = match self.environment {
|
||||
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)
|
||||
normalize_url(&self.instance_uri)
|
||||
}
|
||||
|
||||
pub fn instance(&self) -> Instance {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::net::Ipv6Addr;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use url::{Host, ParseError, Url};
|
||||
|
||||
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 {
|
||||
let maybe_ipv4_address = hostname.parse::<Ipv4Addr>();
|
||||
if let Ok(_ipv4_address) = maybe_ipv4_address {
|
||||
return "http";
|
||||
};
|
||||
let maybe_ipv6_address = hostname.parse::<Ipv6Addr>();
|
||||
if let Ok(ipv6_address) = maybe_ipv6_address {
|
||||
let prefix = ipv6_address.segments()[0];
|
||||
if (0x0200..=0x03ff).contains(&prefix) {
|
||||
// Yggdrasil
|
||||
return "http";
|
||||
};
|
||||
if let Ok(_ipv6_address) = maybe_ipv6_address {
|
||||
return "http";
|
||||
};
|
||||
if hostname.ends_with(".onion") || hostname.ends_with(".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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_hostname() {
|
||||
let url = "https://example.org/objects/1";
|
||||
|
@ -41,6 +68,13 @@ mod tests {
|
|||
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]
|
||||
fn test_get_hostname_tor() {
|
||||
let url = "http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion/objects/1";
|
||||
|
@ -76,9 +110,25 @@ mod tests {
|
|||
guess_protocol("zzz.i2p"),
|
||||
"http",
|
||||
);
|
||||
// Yggdrasil
|
||||
assert_eq!(
|
||||
guess_protocol("319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be"),
|
||||
"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