mirror of
https://github.com/aljazceru/pubky-core.git
synced 2026-01-17 21:24:19 +01:00
wip(js): migrate wasm bindings to support pubky in host
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1914,6 +1914,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"cookie",
|
||||
"cookie_store",
|
||||
"futures-lite",
|
||||
"js-sys",
|
||||
"pkarr",
|
||||
"pubky-common",
|
||||
|
||||
@@ -31,7 +31,7 @@ tokio = { version = "1.37.0", features = ["full"] }
|
||||
# Wasm dependencies
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
reqwest = { version = "0.12.5", default-features = false }
|
||||
|
||||
futures-lite = { version = "2.5.0", default-features = false }
|
||||
wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.42"
|
||||
|
||||
@@ -43,8 +43,6 @@ anyhow = "1.0.93"
|
||||
pubky-homeserver = { path = "../pubky-homeserver" }
|
||||
tokio = "1.37.0"
|
||||
|
||||
[features]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
|
||||
@@ -22,12 +22,14 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
PublicKeyError(#[from] pkarr::errors::PublicKeyError),
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[error(transparent)]
|
||||
PkarrPublishError(#[from] pkarr::errors::PublishError),
|
||||
|
||||
#[error(transparent)]
|
||||
SignedPacketError(#[from] pkarr::errors::SignedPacketError),
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[error(transparent)]
|
||||
PkarrClientWasShutdown(#[from] pkarr::errors::ClientWasShutdown),
|
||||
|
||||
|
||||
@@ -23,11 +23,13 @@ pub use crate::shared::list_builder::ListBuilder;
|
||||
#[derive(Clone)]
|
||||
#[wasm_bindgen]
|
||||
pub struct Client {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) cookie_store: Arc<native::CookieJar>,
|
||||
http: reqwest::Client,
|
||||
pkarr: pkarr::Client,
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
cookie_store: Arc<native::CookieJar>,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
icann_http: reqwest::Client,
|
||||
pub(crate) pkarr: pkarr::Client,
|
||||
}
|
||||
|
||||
impl Debug for Client {
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::Client;
|
||||
mod api;
|
||||
mod cookies;
|
||||
mod http;
|
||||
mod internal;
|
||||
|
||||
pub(crate) use cookies::CookieJar;
|
||||
|
||||
|
||||
12
pubky/src/native/internal.rs
Normal file
12
pubky/src/native/internal.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
//! Native specific implementation of methods used in the shared module
|
||||
//!
|
||||
|
||||
use reqwest::{IntoUrl, Method, RequestBuilder};
|
||||
|
||||
use crate::Client;
|
||||
|
||||
impl Client {
|
||||
pub(crate) async fn inner_request<T: IntoUrl>(&self, method: Method, url: T) -> RequestBuilder {
|
||||
self.request(method, url)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use base64::{alphabet::URL_SAFE, engine::general_purpose::NO_PAD, Engine};
|
||||
use reqwest::StatusCode;
|
||||
use reqwest::{Method, StatusCode};
|
||||
use url::Url;
|
||||
|
||||
use pkarr::{Keypair, PublicKey};
|
||||
@@ -28,7 +28,8 @@ impl Client {
|
||||
homeserver: &PublicKey,
|
||||
) -> Result<Session> {
|
||||
let response = self
|
||||
.post(format!("https://{}/signup", homeserver))
|
||||
.inner_request(Method::POST, format!("https://{}/signup", homeserver))
|
||||
.await
|
||||
.body(AuthToken::sign(keypair, vec![Capability::root()]).serialize())
|
||||
.send()
|
||||
.await?
|
||||
@@ -38,6 +39,7 @@ impl Client {
|
||||
.await?;
|
||||
|
||||
// Store the cookie to the correct URL.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
self.cookie_store
|
||||
.store_session_after_signup(&response, &keypair.public_key());
|
||||
|
||||
@@ -52,7 +54,8 @@ impl Client {
|
||||
/// if the response has any other `>=404` status code.
|
||||
pub(crate) async fn inner_session(&self, pubky: &PublicKey) -> Result<Option<Session>> {
|
||||
let res = self
|
||||
.get(format!("pubky://{}/session", pubky))
|
||||
.inner_request(Method::GET, format!("pubky://{}/session", pubky))
|
||||
.await
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
@@ -71,7 +74,8 @@ impl Client {
|
||||
|
||||
/// Signout from a homeserver.
|
||||
pub(crate) async fn inner_signout(&self, pubky: &PublicKey) -> Result<()> {
|
||||
self.delete(format!("pubky://{}/session", pubky))
|
||||
self.inner_request(Method::DELETE, format!("pubky://{}/session", pubky))
|
||||
.await
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
@@ -135,7 +139,8 @@ impl Client {
|
||||
path_segments.push(&channel_id);
|
||||
drop(path_segments);
|
||||
|
||||
self.post(callback)
|
||||
self.inner_request(Method::POST, callback)
|
||||
.await
|
||||
.body(encrypted_token)
|
||||
.send()
|
||||
.await?
|
||||
@@ -146,7 +151,8 @@ impl Client {
|
||||
|
||||
pub(crate) async fn signin_with_authtoken(&self, token: &AuthToken) -> Result<Session> {
|
||||
let response = self
|
||||
.post(format!("pubky://{}/session", token.pubky()))
|
||||
.inner_request(Method::POST, format!("pubky://{}/session", token.pubky()))
|
||||
.await
|
||||
.body(token.serialize())
|
||||
.send()
|
||||
.await?
|
||||
|
||||
@@ -90,7 +90,12 @@ impl<'a> ListBuilder<'a> {
|
||||
|
||||
drop(query);
|
||||
|
||||
let response = self.client.request(Method::GET, url).send().await?;
|
||||
let response = self
|
||||
.client
|
||||
.inner_request(Method::GET, url)
|
||||
.await
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
response.error_for_status_ref()?;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use wasm_bindgen::prelude::*;
|
||||
use crate::Client;
|
||||
|
||||
mod api;
|
||||
mod http;
|
||||
mod internals;
|
||||
mod wrappers;
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
//! Wasm bindings for the Auth api
|
||||
|
||||
use url::Url;
|
||||
|
||||
use pubky_common::capabilities::Capabilities;
|
||||
|
||||
use crate::Client;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
use crate::wasm::wrappers::keys::{Keypair, PublicKey};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod http;
|
||||
pub mod recovery_file;
|
||||
|
||||
// TODO: put the Homeserver API behind a feature flag
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
//! Wasm bindings for the /pub/ api
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use reqwest::{Method, StatusCode};
|
||||
|
||||
use js_sys::{Array, Uint8Array};
|
||||
|
||||
use crate::Client;
|
||||
@@ -24,7 +28,11 @@ impl Client {
|
||||
/// Delete a file at a path relative to a pubky author.
|
||||
#[wasm_bindgen]
|
||||
pub async fn delete(&self, url: &str) -> Result<(), JsValue> {
|
||||
self.inner_delete(url).await.map_err(|e| e.into())
|
||||
self.inner_request(Method::DELETE, url)
|
||||
.await
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
/// Returns a list of Pubky urls (as strings).
|
||||
|
||||
@@ -7,8 +7,6 @@ use reqwest::Url;
|
||||
|
||||
use crate::Client;
|
||||
|
||||
use super::super::internals::resolve;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Client {
|
||||
#[wasm_bindgen]
|
||||
@@ -21,10 +19,6 @@ impl Client {
|
||||
JsValue::from_str(&format!("pubky::Client::fetch(): Invalid `url`; {:?}", err))
|
||||
})?;
|
||||
|
||||
resolve(&self.pkarr, &mut url)
|
||||
.await
|
||||
.map_err(|err| JsValue::from_str(&format!("pubky::Client::fetch(): {:?}", err)))?;
|
||||
|
||||
let js_req =
|
||||
web_sys::Request::new_with_str_and_init(url.as_str(), init).map_err(|err| {
|
||||
JsValue::from_str(&format!(
|
||||
@@ -1,33 +1,53 @@
|
||||
use reqwest::{Method, RequestBuilder};
|
||||
//! Wasm specific implementation of methods used in the shared module
|
||||
//!
|
||||
|
||||
use reqwest::{IntoUrl, Method, RequestBuilder};
|
||||
use url::Url;
|
||||
|
||||
use futures_lite::{pin, Stream, StreamExt};
|
||||
|
||||
use pkarr::extra::endpoints::EndpointsResolver;
|
||||
use pkarr::PublicKey;
|
||||
|
||||
use crate::{error::Result, Client};
|
||||
|
||||
// TODO: remove expect
|
||||
pub async fn resolve(pkarr: &pkarr::Client, url: &mut Url) -> Result<()> {
|
||||
let qname = url.host_str().expect("URL TO HAVE A HOST!").to_string();
|
||||
|
||||
// If http and has a Pubky TLD, switch to socket addresses.
|
||||
if url.scheme() == "http" && PublicKey::try_from(qname.as_str()).is_ok() {
|
||||
let endpoint = pkarr.resolve_endpoint(&qname).await?;
|
||||
|
||||
if let Some(socket_address) = endpoint.to_socket_addrs().into_iter().next() {
|
||||
url.set_host(Some(&socket_address.to_string()))?;
|
||||
let _ = url.set_port(Some(socket_address.port()));
|
||||
} else if let Some(port) = endpoint.port() {
|
||||
url.set_host(Some(endpoint.target()))?;
|
||||
let _ = url.set_port(Some(port));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// A wrapper around [reqwest::Client::request], with the same signature between native and wasm.
|
||||
pub(crate) async fn inner_request(&self, method: Method, url: Url) -> RequestBuilder {
|
||||
pub(crate) async fn inner_request<T: IntoUrl>(&self, method: Method, url: T) -> RequestBuilder {
|
||||
let original_url = url.as_str();
|
||||
let mut url = Url::parse(original_url).expect("Invalid url in inner_request");
|
||||
|
||||
if url.scheme() == "pubky" {
|
||||
url.set_scheme("https");
|
||||
}
|
||||
|
||||
if PublicKey::try_from(original_url).is_ok() {
|
||||
let stream = self
|
||||
.pkarr
|
||||
.resolve_https_endpoints(url.host_str().unwrap_or(""));
|
||||
|
||||
let mut so_far = None;
|
||||
|
||||
while let Some(endpoint) = stream.next().await {
|
||||
if let Some(e) = so_far {
|
||||
if e.domain() == "." && 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();
|
||||
} else {
|
||||
// TODO: didn't find any domain, what to do?
|
||||
}
|
||||
}
|
||||
|
||||
self.http.request(method, url).fetch_credentials_include()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ impl PublicKey {
|
||||
.ok_or("Couldn't create a PublicKey from this type of value")?;
|
||||
|
||||
Ok(PublicKey(
|
||||
pkarr::PublicKey::try_from(string).map_err(Error::Pkarr)?,
|
||||
pkarr::PublicKey::try_from(string).map_err(Error::PublicKeyError)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user