Allow instance URI to be onion, i2p or yggdrasil address

This commit is contained in:
silverpill 2022-10-18 09:52:32 +00:00
parent eef20f6b7c
commit f0dace197b
3 changed files with 53 additions and 9 deletions

View file

@ -10,6 +10,7 @@ use crate::activitypub::constants::AP_MEDIA_TYPE;
use crate::config::Instance; use crate::config::Instance;
use crate::http_signatures::create::{create_http_signature, SignatureError}; use crate::http_signatures::create::{create_http_signature, SignatureError};
use crate::utils::files::save_file; use crate::utils::files::save_file;
use crate::utils::urls::guess_protocol;
use crate::webfinger::types::JsonResourceDescriptor; use crate::webfinger::types::JsonResourceDescriptor;
const FETCHER_CONNECTION_TIMEOUT: u64 = 30; const FETCHER_CONNECTION_TIMEOUT: u64 = 30;
@ -105,9 +106,9 @@ pub async fn perform_webfinger_query(
actor_address: &ActorAddress, actor_address: &ActorAddress,
) -> Result<String, FetchError> { ) -> Result<String, FetchError> {
let webfinger_account_uri = format!("acct:{}", actor_address); let webfinger_account_uri = format!("acct:{}", actor_address);
// TOOD: support http
let webfinger_url = format!( let webfinger_url = format!(
"https://{}/.well-known/webfinger", "{}://{}/.well-known/webfinger",
guess_protocol(&actor_address.hostname),
actor_address.hostname, actor_address.hostname,
); );
let client = build_client()?; let client = build_client()?;

View file

@ -16,6 +16,7 @@ use crate::utils::crypto::{
serialize_private_key, serialize_private_key,
}; };
use crate::utils::files::{set_file_permissions, write_file}; use crate::utils::files::{set_file_permissions, write_file};
use crate::utils::urls::guess_protocol;
use super::blockchain::BlockchainConfig; use super::blockchain::BlockchainConfig;
use super::environment::Environment; use super::environment::Environment;
@ -113,10 +114,9 @@ pub struct Config {
impl Config { impl Config {
fn try_instance_url(&self) -> Result<Url, ConversionError> { fn try_instance_url(&self) -> Result<Url, ConversionError> {
// TODO: allow http in production
let scheme = match self.environment { let scheme = match self.environment {
Environment::Development => "http", Environment::Development => "http",
Environment::Production => "https", Environment::Production => guess_protocol(&self.instance_uri),
}; };
let url_str = format!("{}://{}", scheme, self.instance_uri); let url_str = format!("{}://{}", scheme, self.instance_uri);
let url = Url::parse(&url_str).map_err(|_| ConversionError)?; let url = Url::parse(&url_str).map_err(|_| ConversionError)?;

View file

@ -1,13 +1,36 @@
use url::{Url, ParseError}; use std::net::Ipv6Addr;
use url::{Host, ParseError, Url};
pub fn get_hostname(url: &str) -> Result<String, ParseError> { pub fn get_hostname(url: &str) -> Result<String, ParseError> {
let hostname = Url::parse(url)? let hostname = match Url::parse(url)?
.host_str() .host()
.ok_or(ParseError::EmptyHost)? .ok_or(ParseError::EmptyHost)?
.to_owned(); {
Host::Domain(domain) => domain.to_string(),
Host::Ipv4(addr) => addr.to_string(),
Host::Ipv6(addr) => addr.to_string(),
};
Ok(hostname) Ok(hostname)
} }
pub fn guess_protocol(hostname: &str) -> &'static str {
let maybe_ipv6_address = hostname.parse::<Ipv6Addr>();
if let Ok(ipv6_address) = maybe_ipv6_address {
let prefix = ipv6_address.segments()[0];
if prefix >= 0x0200 && prefix <= 0x03ff {
// Yggdrasil
return "http";
};
};
if hostname.ends_with(".onion") || hostname.ends_with(".i2p") {
// Tor / I2P
"http"
} else {
// Use HTTPS by default
"https"
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -29,7 +52,7 @@ mod tests {
fn test_get_hostname_yggdrasil() { fn test_get_hostname_yggdrasil() {
let url = "http://[319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be]/objects/1"; let url = "http://[319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be]/objects/1";
let hostname = get_hostname(url).unwrap(); let hostname = get_hostname(url).unwrap();
assert_eq!(hostname, "[319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be]"); assert_eq!(hostname, "319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be");
} }
#[test] #[test]
@ -38,4 +61,24 @@ mod tests {
let result = get_hostname(url); let result = get_hostname(url);
assert_eq!(result.is_err(), true); assert_eq!(result.is_err(), true);
} }
#[test]
fn test_guess_protocol() {
assert_eq!(
guess_protocol("example.org"),
"https",
);
assert_eq!(
guess_protocol("2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"),
"http",
);
assert_eq!(
guess_protocol("zzz.i2p"),
"http",
);
assert_eq!(
guess_protocol("319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be"),
"http",
);
}
} }