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

View file

@ -16,6 +16,7 @@ use crate::utils::crypto::{
serialize_private_key,
};
use crate::utils::files::{set_file_permissions, write_file};
use crate::utils::urls::guess_protocol;
use super::blockchain::BlockchainConfig;
use super::environment::Environment;
@ -113,10 +114,9 @@ pub struct Config {
impl Config {
fn try_instance_url(&self) -> Result<Url, ConversionError> {
// TODO: allow http in production
let scheme = match self.environment {
Environment::Development => "http",
Environment::Production => "https",
Environment::Production => guess_protocol(&self.instance_uri),
};
let url_str = format!("{}://{}", scheme, self.instance_uri);
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> {
let hostname = Url::parse(url)?
.host_str()
let hostname = match Url::parse(url)?
.host()
.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)
}
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)]
mod tests {
use super::*;
@ -29,7 +52,7 @@ mod tests {
fn test_get_hostname_yggdrasil() {
let url = "http://[319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be]/objects/1";
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]
@ -38,4 +61,24 @@ mod tests {
let result = get_hostname(url);
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",
);
}
}