mirror of
https://github.com/aljazceru/pubky-core.git
synced 2025-12-31 04:44:37 +01:00
feat(homeserver,js): connect to testnet from js
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -1921,7 +1921,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
[[package]]
|
||||
name = "pkarr"
|
||||
version = "3.0.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#95f106e5a8a1d6275738aabf25c32c7cc7932a50"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#aac62e74f3ab5d94b1a52cd00ff355d8d50e29e1"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"byteorder",
|
||||
@@ -1952,13 +1952,14 @@ dependencies = [
|
||||
"thiserror 2.0.6",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkarr-relay"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#95f106e5a8a1d6275738aabf25c32c7cc7932a50"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#aac62e74f3ab5d94b1a52cd00ff355d8d50e29e1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
||||
@@ -33,6 +33,8 @@ struct ConfigToml {
|
||||
/// Server configuration
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Config {
|
||||
/// Run in [testnet](crate::Homeserver::start_testnet) mode.
|
||||
pub testnet: bool,
|
||||
/// The configured port for this server.
|
||||
pub port: u16,
|
||||
/// Bootstrapping DHT nodes.
|
||||
@@ -99,6 +101,7 @@ impl Config {
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
testnet: false,
|
||||
port: 0,
|
||||
bootstrap: None,
|
||||
domain: None,
|
||||
@@ -138,6 +141,7 @@ impl TryFrom<ConfigToml> for Config {
|
||||
};
|
||||
|
||||
Ok(Config {
|
||||
testnet: false,
|
||||
port: value.port.unwrap_or(0),
|
||||
bootstrap: value.bootstrap,
|
||||
domain: value.domain,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use ::pkarr::{Keypair, PublicKey};
|
||||
use anyhow::Result;
|
||||
use http::HttpServers;
|
||||
@@ -13,6 +15,12 @@ mod pkarr;
|
||||
pub struct HomeserverBuilder(Config);
|
||||
|
||||
impl HomeserverBuilder {
|
||||
pub fn testnet(mut self) -> Self {
|
||||
self.0.testnet = true;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Configure the Homeserver's keypair
|
||||
pub fn keypair(mut self, keypair: Keypair) -> Self {
|
||||
self.0.keypair = keypair;
|
||||
@@ -27,6 +35,13 @@ impl HomeserverBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configure the storage path of the Homeserver
|
||||
pub fn storage(mut self, storage: PathBuf) -> Self {
|
||||
self.0.storage = storage;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Start running a Homeserver
|
||||
///
|
||||
/// # Safety
|
||||
@@ -68,7 +83,14 @@ impl Homeserver {
|
||||
|
||||
info!("Publishing Pkarr packet..");
|
||||
|
||||
let pkarr_server = PkarrServer::new(config, http_servers.https_address().await?.port())?;
|
||||
let pkarr_server = PkarrServer::new(
|
||||
&config,
|
||||
if config.testnet {
|
||||
http_servers.http_address().await?.port()
|
||||
} else {
|
||||
http_servers.https_address().await?.port()
|
||||
},
|
||||
)?;
|
||||
pkarr_server.publish_server_packet().await?;
|
||||
|
||||
info!("Homeserver listening on https://{}", core.public_key());
|
||||
@@ -78,20 +100,27 @@ impl Homeserver {
|
||||
|
||||
/// Start a homeserver in a Testnet mode.
|
||||
///
|
||||
/// - Homeserver address is hardcoded to ``
|
||||
/// - Homeserver address is hardcoded to `8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo`
|
||||
/// - Run a pkarr Relay on port `15411`
|
||||
/// - Use a temporary storage for the both homeserver and relay
|
||||
/// - Only publish http port (ignore https port or domain configurations)
|
||||
///
|
||||
/// # Safety
|
||||
/// See [Self::start]
|
||||
pub async unsafe fn start_testnet() -> Result<Self> {
|
||||
let testnet = ::pkarr::mainline::Testnet::new(10)?;
|
||||
|
||||
let storage =
|
||||
std::env::temp_dir().join(pubky_common::timestamp::Timestamp::now().to_string());
|
||||
|
||||
let relay = unsafe {
|
||||
let mut config = pkarr_relay::Config {
|
||||
http_port: 15411,
|
||||
cache_path: Some(storage.join("pkarr-relay")),
|
||||
..Default::default()
|
||||
};
|
||||
config.pkarr_config.dht_config.bootstrap = testnet.bootstrap.clone();
|
||||
config.pkarr_config.resolvers = Some(vec![]);
|
||||
|
||||
pkarr_relay::Relay::start(config).await?
|
||||
};
|
||||
@@ -100,14 +129,16 @@ impl Homeserver {
|
||||
|
||||
unsafe {
|
||||
Homeserver::builder()
|
||||
.testnet()
|
||||
.keypair(Keypair::from_secret_key(&[0; 32]))
|
||||
.bootstrap(testnet.bootstrap)
|
||||
.storage(storage.join("pubky-homeserver"))
|
||||
.build()
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
/// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage.
|
||||
/// Unit tests version of [Homeserver::start], using mainline Testnet, and a temporary storage.
|
||||
pub async fn start_test(testnet: &::pkarr::mainline::Testnet) -> Result<Self> {
|
||||
unsafe { Homeserver::start(Config::test(testnet)).await }
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pub struct PkarrServer {
|
||||
}
|
||||
|
||||
impl PkarrServer {
|
||||
pub fn new(config: Config, port: u16) -> Result<Self> {
|
||||
pub fn new(config: &Config, port: u16) -> Result<Self> {
|
||||
let mut dht_config = pkarr::mainline::Config::default();
|
||||
|
||||
if let Some(bootstrap) = config.bootstrap.clone() {
|
||||
@@ -41,7 +41,7 @@ impl PkarrServer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_signed_packet(config: Config, port: u16) -> Result<SignedPacket> {
|
||||
pub fn create_signed_packet(config: &Config, port: u16) -> Result<SignedPacket> {
|
||||
// TODO: Try to resolve first before publishing.
|
||||
|
||||
let default = ".".to_string();
|
||||
|
||||
@@ -11,7 +11,6 @@ test.only("basic fetch", async (t) => {
|
||||
|
||||
// Normal TLD
|
||||
{
|
||||
|
||||
let response = await client.fetch(`http://relay.pkarr.org/`);
|
||||
|
||||
t.equal(response.status, 200);
|
||||
|
||||
@@ -13,7 +13,7 @@ impl Default for Client {
|
||||
}
|
||||
}
|
||||
|
||||
static TESTNET_RELAYS: [&str; 1] = ["http://localhost:15411/pkarr"];
|
||||
static TESTNET_RELAYS: [&str; 1] = ["http://localhost:15411/"];
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Client {
|
||||
@@ -27,13 +27,18 @@ impl Client {
|
||||
}
|
||||
|
||||
/// Create a client with with configurations appropriate for local testing:
|
||||
/// - set Pkarr relays to `["http://localhost:15411/pkarr"]` instead of default relay.
|
||||
/// - set Pkarr relays to `["http://localhost:15411"]` instead of default relay.
|
||||
#[wasm_bindgen]
|
||||
pub fn testnet() -> Self {
|
||||
Self {
|
||||
http: reqwest::Client::builder().build().unwrap(),
|
||||
pkarr: pkarr::Client::builder()
|
||||
.relays(TESTNET_RELAYS.into_iter().map(|s| s.to_string()).collect())
|
||||
.relays(
|
||||
TESTNET_RELAYS
|
||||
.into_iter()
|
||||
.map(|s| url::Url::parse(s).expect("TESTNET_RELAYS should be valid urls"))
|
||||
.collect(),
|
||||
)
|
||||
.build()
|
||||
.unwrap(),
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ impl Client {
|
||||
JsValue::from_str(&format!("pubky::Client::fetch(): Invalid `url`; {:?}", err))
|
||||
})?;
|
||||
|
||||
self.transform_url(&mut url).await;
|
||||
|
||||
let js_req =
|
||||
web_sys::Request::new_with_str_and_init(url.as_str(), init).map_err(|err| {
|
||||
JsValue::from_str(&format!(
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
use reqwest::{IntoUrl, Method, RequestBuilder};
|
||||
use url::Url;
|
||||
|
||||
use futures_lite::{pin, Stream, StreamExt};
|
||||
use futures_lite::StreamExt;
|
||||
|
||||
use pkarr::extra::endpoints::EndpointsResolver;
|
||||
use pkarr::extra::endpoints::{Endpoint, EndpointsResolver};
|
||||
use pkarr::PublicKey;
|
||||
|
||||
use crate::{error::Result, Client};
|
||||
use crate::Client;
|
||||
|
||||
impl Client {
|
||||
/// A wrapper around [reqwest::Client::request], with the same signature between native and wasm.
|
||||
@@ -17,37 +17,45 @@ impl Client {
|
||||
let original_url = url.as_str();
|
||||
let mut url = Url::parse(original_url).expect("Invalid url in inner_request");
|
||||
|
||||
self.transform_url(&mut url).await;
|
||||
|
||||
self.http.request(method, url).fetch_credentials_include()
|
||||
}
|
||||
|
||||
pub(super) async fn transform_url(&self, url: &mut Url) {
|
||||
if url.scheme() == "pubky" {
|
||||
url.set_scheme("https");
|
||||
// TODO: use https for anything other than testnet
|
||||
url.set_scheme("http")
|
||||
.expect("couldn't replace pubky:// with http://");
|
||||
url.set_host(Some(&format!("_pubky.{}", url.host_str().unwrap_or(""))))
|
||||
.expect("couldn't map pubk://<pubky> to https://_pubky.<pubky>");
|
||||
}
|
||||
|
||||
if PublicKey::try_from(original_url).is_ok() {
|
||||
let stream = self
|
||||
.pkarr
|
||||
.resolve_https_endpoints(url.host_str().unwrap_or(""));
|
||||
let qname = url.host_str().unwrap_or("").to_string();
|
||||
|
||||
let mut so_far = None;
|
||||
if PublicKey::try_from(qname.to_string()).is_ok() {
|
||||
let mut stream = self.pkarr.resolve_https_endpoints(&qname);
|
||||
|
||||
while let Some(endpoint) = stream.next().await {
|
||||
if let Some(e) = so_far {
|
||||
if e.domain() == "." && endpoint.domain() != "." {
|
||||
let mut so_far: Option<Endpoint> = None;
|
||||
|
||||
// TODO: currently we return the first thing we can see,
|
||||
// in the future we might want to failover to other endpoints
|
||||
while so_far.is_none() {
|
||||
while let Some(endpoint) = stream.next().await {
|
||||
if endpoint.domain() != "." {
|
||||
so_far = Some(endpoint);
|
||||
}
|
||||
} else {
|
||||
so_far = Some(endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(e) = so_far {
|
||||
url.set_host(Some(e.domain()));
|
||||
url.set_port(Some(e.port()));
|
||||
|
||||
return self.http.request(method, url).fetch_credentials_include();
|
||||
url.set_host(Some(e.domain()))
|
||||
.expect("coultdn't use the resolved endpoint's domain");
|
||||
url.set_port(Some(e.port()))
|
||||
.expect("coultdn't use the resolved endpoint's port");
|
||||
} else {
|
||||
// TODO: didn't find any domain, what to do?
|
||||
}
|
||||
}
|
||||
|
||||
self.http.request(method, url).fetch_credentials_include()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user