mirror of
https://github.com/aljazceru/pubky-core.git
synced 2026-01-08 08:44:24 +01:00
feat(homeserver): add http relay in homeserver testnet for js testing
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1247,6 +1247,7 @@ dependencies = [
|
||||
"axum-server",
|
||||
"futures-util",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -1944,7 +1945,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
[[package]]
|
||||
name = "pkarr"
|
||||
version = "3.0.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#aac62e74f3ab5d94b1a52cd00ff355d8d50e29e1"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#492639796bac0fedf42de7bbd3c069506b77fd19"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"byteorder",
|
||||
@@ -1982,7 +1983,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "pkarr-relay"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#aac62e74f3ab5d94b1a52cd00ff355d8d50e29e1"
|
||||
source = "git+https://github.com/Pubky/pkarr?branch=v3#492639796bac0fedf42de7bbd3c069506b77fd19"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -2147,6 +2148,7 @@ dependencies = [
|
||||
"futures-util",
|
||||
"heed 0.21.0",
|
||||
"hex",
|
||||
"http-relay",
|
||||
"httpdate",
|
||||
"page_size",
|
||||
"pkarr",
|
||||
|
||||
@@ -9,4 +9,5 @@ axum = "0.7.9"
|
||||
axum-server = "0.7.1"
|
||||
futures-util = "0.3.31"
|
||||
tokio = { version = "1.42.0", features = ["full"] }
|
||||
tracing = "0.1.41"
|
||||
url = "2.5.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::SocketAddr,
|
||||
net::{SocketAddr, TcpListener},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
@@ -16,18 +16,45 @@ use axum::{
|
||||
use axum_server::Handle;
|
||||
use tokio::sync::Notify;
|
||||
|
||||
use futures_util::stream::StreamExt;
|
||||
use futures_util::{stream::StreamExt, TryFutureExt};
|
||||
use url::Url;
|
||||
|
||||
// Shared state to store GET requests and their notifications
|
||||
type SharedState = Arc<Mutex<HashMap<String, (Vec<u8>, Arc<Notify>)>>>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Config {
|
||||
pub http_port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct HttpRelayBuilder(Config);
|
||||
|
||||
impl HttpRelayBuilder {
|
||||
/// Configure the port used for HTTP server.
|
||||
pub fn http_port(mut self, port: u16) -> Self {
|
||||
self.0.http_port = port;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn build(self) -> Result<HttpRelay> {
|
||||
HttpRelay::start(self.0).await
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HttpRelay {
|
||||
pub(crate) http_handle: Handle,
|
||||
|
||||
http_address: SocketAddr,
|
||||
}
|
||||
|
||||
impl HttpRelay {
|
||||
pub async fn start() -> Result<Self> {
|
||||
pub fn builder() -> HttpRelayBuilder {
|
||||
HttpRelayBuilder::default()
|
||||
}
|
||||
|
||||
pub async fn start(config: Config) -> Result<Self> {
|
||||
let shared_state: SharedState = Arc::new(Mutex::new(HashMap::new()));
|
||||
|
||||
let app = Router::new()
|
||||
@@ -36,36 +63,35 @@ impl HttpRelay {
|
||||
|
||||
let http_handle = Handle::new();
|
||||
|
||||
let cloned = http_handle.clone();
|
||||
tokio::spawn(async {
|
||||
axum_server::bind(SocketAddr::from(([127, 0, 0, 1], 0)))
|
||||
.handle(cloned)
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
let http_listener = TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], config.http_port)))?;
|
||||
let http_address = http_listener.local_addr()?;
|
||||
|
||||
Ok(Self { http_handle })
|
||||
tokio::spawn(
|
||||
axum_server::from_tcp(http_listener)
|
||||
.handle(http_handle.clone())
|
||||
.serve(app.into_make_service())
|
||||
.map_err(|error| tracing::error!(?error, "HttpRelay http server error")),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
http_handle,
|
||||
http_address,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn http_address(&self) -> Result<SocketAddr> {
|
||||
match self.http_handle.listening().await {
|
||||
Some(addr) => Ok(addr),
|
||||
None => Err(anyhow::anyhow!("Failed to bind to http port")),
|
||||
}
|
||||
pub fn http_address(&self) -> SocketAddr {
|
||||
self.http_address
|
||||
}
|
||||
|
||||
/// Returns the localhost Url of this server.
|
||||
pub async fn local_url(&self) -> Result<Url> {
|
||||
match self.http_handle.listening().await {
|
||||
Some(addr) => Ok(Url::parse(&format!("http://localhost:{}", addr.port()))?),
|
||||
None => Err(anyhow::anyhow!("Failed to bind to http port")),
|
||||
}
|
||||
pub fn local_url(&self) -> Url {
|
||||
Url::parse(&format!("http://localhost:{}", self.http_address.port()))
|
||||
.expect("local_url should be formatted fine")
|
||||
}
|
||||
|
||||
/// Returns the localhost URL of Link endpoints
|
||||
pub async fn local_link_url(&self) -> Result<Url> {
|
||||
let mut url = self.local_url().await?;
|
||||
pub fn local_link_url(&self) -> Url {
|
||||
let mut url = self.local_url();
|
||||
|
||||
let mut segments = url
|
||||
.path_segments_mut()
|
||||
@@ -75,7 +101,7 @@ impl HttpRelay {
|
||||
|
||||
drop(segments);
|
||||
|
||||
Ok(url)
|
||||
url
|
||||
}
|
||||
|
||||
pub fn shutdown(&self) {
|
||||
|
||||
@@ -32,3 +32,4 @@ tower = "0.5.1"
|
||||
page_size = "0.6.0"
|
||||
|
||||
pkarr-relay = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr-relay" }
|
||||
http-relay = { version = "0.1.0", path = "../http-relay" }
|
||||
|
||||
@@ -20,6 +20,9 @@ pub struct HttpServers {
|
||||
pub(crate) http_handle: Handle,
|
||||
/// Handle for the HTTPS server using Pkarr TLS
|
||||
pub(crate) https_handle: Handle,
|
||||
|
||||
http_address: SocketAddr,
|
||||
https_address: SocketAddr,
|
||||
}
|
||||
|
||||
impl HttpServers {
|
||||
@@ -27,6 +30,7 @@ impl HttpServers {
|
||||
let http_listener =
|
||||
// TODO: add config to http port
|
||||
TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], 0)))?;
|
||||
let http_address = http_listener.local_addr()?;
|
||||
|
||||
let http_handle = Handle::new();
|
||||
|
||||
@@ -43,6 +47,7 @@ impl HttpServers {
|
||||
|
||||
let https_listener =
|
||||
TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], core.config().port)))?;
|
||||
let https_address = https_listener.local_addr()?;
|
||||
|
||||
let https_handle = Handle::new();
|
||||
|
||||
@@ -63,21 +68,18 @@ impl HttpServers {
|
||||
Ok(Self {
|
||||
http_handle,
|
||||
https_handle,
|
||||
|
||||
http_address,
|
||||
https_address,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn http_address(&self) -> Result<SocketAddr> {
|
||||
match self.http_handle.listening().await {
|
||||
Some(addr) => Ok(addr),
|
||||
None => Err(anyhow::anyhow!("Failed to bind to http port")),
|
||||
}
|
||||
pub fn http_address(&self) -> SocketAddr {
|
||||
self.http_address
|
||||
}
|
||||
|
||||
pub async fn https_address(&self) -> Result<SocketAddr> {
|
||||
match self.https_handle.listening().await {
|
||||
Some(addr) => Ok(addr),
|
||||
None => Err(anyhow::anyhow!("Failed to bind to https port")),
|
||||
}
|
||||
pub fn https_address(&self) -> SocketAddr {
|
||||
self.https_address
|
||||
}
|
||||
|
||||
/// Shutdown all HTTP servers.
|
||||
|
||||
@@ -78,7 +78,7 @@ impl Homeserver {
|
||||
|
||||
info!(
|
||||
"Homeserver listening on http://localhost:{}",
|
||||
http_servers.http_address().await?.port()
|
||||
http_servers.http_address().port()
|
||||
);
|
||||
|
||||
info!("Publishing Pkarr packet..");
|
||||
@@ -86,9 +86,9 @@ impl Homeserver {
|
||||
let pkarr_server = PkarrServer::new(
|
||||
&config,
|
||||
if config.testnet {
|
||||
http_servers.http_address().await?.port()
|
||||
http_servers.http_address().port()
|
||||
} else {
|
||||
http_servers.https_address().await?.port()
|
||||
http_servers.https_address().port()
|
||||
},
|
||||
)?;
|
||||
pkarr_server.publish_server_packet().await?;
|
||||
@@ -104,6 +104,7 @@ impl Homeserver {
|
||||
/// - 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)
|
||||
/// - Run an HTTP relay on port `15412`
|
||||
///
|
||||
/// # Safety
|
||||
/// See [Self::start]
|
||||
@@ -113,19 +114,27 @@ impl Homeserver {
|
||||
let storage =
|
||||
std::env::temp_dir().join(pubky_common::timestamp::Timestamp::now().to_string());
|
||||
|
||||
let relay = unsafe {
|
||||
let pkarr_relay = unsafe {
|
||||
let mut config = pkarr_relay::Config {
|
||||
http_port: 15411,
|
||||
cache_path: Some(storage.join("pkarr-relay")),
|
||||
rate_limiter: None,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
config.pkarr_config.dht_config.bootstrap = testnet.bootstrap.clone();
|
||||
config.pkarr_config.resolvers = Some(vec![]);
|
||||
|
||||
pkarr_relay::Relay::start(config).await?
|
||||
};
|
||||
|
||||
tracing::info!(relay_address=?relay.relay_address(), bootstrap=?relay.resolver_address(),"Running in Testnet mode");
|
||||
let http_relay = http_relay::HttpRelay::builder()
|
||||
.http_port(15412)
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
tracing::info!(http_relay=?http_relay.local_link_url().as_str(), "Running http relay in Testnet mode");
|
||||
tracing::info!(relay_address=?pkarr_relay.relay_address(), bootstrap=?pkarr_relay.resolver_address(),"Running pkarr relay in Testnet mode");
|
||||
|
||||
unsafe {
|
||||
Homeserver::builder()
|
||||
|
||||
@@ -2,7 +2,8 @@ import test from 'tape'
|
||||
|
||||
import { Client, Keypair, PublicKey } from '../index.cjs'
|
||||
|
||||
const Homeserver = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo')
|
||||
const HOMESERVER_PUBLICKEY = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo')
|
||||
const TESTNET_HTTP_RELAY = "http://localhost:15412/link";
|
||||
|
||||
// TODO: test multiple users in wasm
|
||||
|
||||
@@ -12,7 +13,7 @@ test('auth', async (t) => {
|
||||
const keypair = Keypair.random()
|
||||
const publicKey = keypair.publicKey()
|
||||
|
||||
await client.signup(keypair, Homeserver)
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY )
|
||||
|
||||
const session = await client.session(publicKey)
|
||||
t.ok(session, "signup")
|
||||
@@ -32,7 +33,7 @@ test('auth', async (t) => {
|
||||
}
|
||||
})
|
||||
|
||||
test.skip("3rd party signin", async (t) => {
|
||||
test("3rd party signin", async (t) => {
|
||||
let keypair = Keypair.random();
|
||||
let pubky = keypair.publicKey().z32();
|
||||
|
||||
@@ -40,7 +41,7 @@ test.skip("3rd party signin", async (t) => {
|
||||
let capabilities = "/pub/pubky.app/:rw,/pub/foo.bar/file:r";
|
||||
let client = Client.testnet();
|
||||
let [pubkyauth_url, pubkyauthResponse] = client
|
||||
.authRequest("https://demo.httprelay.io/link", capabilities);
|
||||
.authRequest(TESTNET_HTTP_RELAY, capabilities);
|
||||
|
||||
if (globalThis.document) {
|
||||
// Skip `sendAuthToken` in browser
|
||||
@@ -53,7 +54,7 @@ test.skip("3rd party signin", async (t) => {
|
||||
{
|
||||
let client = Client.testnet();
|
||||
|
||||
await client.signup(keypair, Homeserver);
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY);
|
||||
|
||||
await client.sendAuthToken(keypair, pubkyauth_url)
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ import test from 'tape'
|
||||
|
||||
import { Client, Keypair, PublicKey } from '../index.cjs'
|
||||
|
||||
const Homeserver = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo');
|
||||
const HOMESERVER_PUBLICKEY = PublicKey.from('8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo')
|
||||
|
||||
test.skip('public: put/get', async (t) => {
|
||||
const client = Client.testnet();
|
||||
|
||||
const keypair = Keypair.random();
|
||||
|
||||
await client.signup(keypair, Homeserver);
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY);
|
||||
|
||||
const publicKey = keypair.publicKey();
|
||||
|
||||
@@ -47,7 +47,7 @@ test.skip("not found", async (t) => {
|
||||
|
||||
const keypair = Keypair.random();
|
||||
|
||||
await client.signup(keypair, Homeserver);
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY);
|
||||
|
||||
const publicKey = keypair.publicKey();
|
||||
|
||||
@@ -64,7 +64,7 @@ test.skip("unauthorized", async (t) => {
|
||||
const keypair = Keypair.random()
|
||||
const publicKey = keypair.publicKey()
|
||||
|
||||
await client.signup(keypair, Homeserver)
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY)
|
||||
|
||||
const session = await client.session(publicKey)
|
||||
t.ok(session, "signup")
|
||||
@@ -91,7 +91,7 @@ test.skip("forbidden", async (t) => {
|
||||
const keypair = Keypair.random()
|
||||
const publicKey = keypair.publicKey()
|
||||
|
||||
await client.signup(keypair, Homeserver)
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY)
|
||||
|
||||
const session = await client.session(publicKey)
|
||||
t.ok(session, "signup")
|
||||
@@ -117,7 +117,7 @@ test.skip("list", async (t) => {
|
||||
const publicKey = keypair.publicKey()
|
||||
const pubky = publicKey.z32()
|
||||
|
||||
await client.signup(keypair, Homeserver)
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY)
|
||||
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ test.skip('list shallow', async (t) => {
|
||||
const publicKey = keypair.publicKey()
|
||||
const pubky = publicKey.z32()
|
||||
|
||||
await client.signup(keypair, Homeserver)
|
||||
await client.signup(keypair, HOMESERVER_PUBLICKEY)
|
||||
|
||||
let urls = [
|
||||
`pubky://${pubky}/pub/a.com/a.txt`,
|
||||
|
||||
@@ -271,8 +271,8 @@ mod tests {
|
||||
let testnet = Testnet::new(10).unwrap();
|
||||
let server = Homeserver::start_test(&testnet).await.unwrap();
|
||||
|
||||
let http_relay = HttpRelay::start().await.unwrap();
|
||||
let http_relay_url = http_relay.local_link_url().await.unwrap();
|
||||
let http_relay = HttpRelay::builder().build().await.unwrap();
|
||||
let http_relay_url = http_relay.local_link_url();
|
||||
|
||||
let keypair = Keypair::random();
|
||||
let pubky = keypair.public_key();
|
||||
|
||||
Reference in New Issue
Block a user