Improve documentation some more

This commit is contained in:
Aode (lion) 2021-11-23 19:28:56 -06:00
parent a209e404ea
commit 43b953d4df
8 changed files with 273 additions and 11 deletions

View file

@ -7,12 +7,12 @@ edition = "2021"
[features]
default = ["utils"]
actix-web = ["apub-actix-web"]
awc = ["apub-awc"]
background-jobs = ["apub-background-jobs"]
openssl = ["apub-openssl"]
reqwest = ["apub-reqwest"]
rustcrypto = ["apub-rustcrypto"]
with-actix-web = ["apub-actix-web"]
with-awc = ["apub-awc"]
with-background-jobs = ["apub-background-jobs"]
with-openssl = ["apub-openssl"]
with-reqwest = ["apub-reqwest"]
with-rustcrypto = ["apub-rustcrypto"]
utils = ["apub-breaker-session", "apub-deref-client"]
[dependencies]
@ -26,6 +26,15 @@ apub-openssl = { version = "0.1.0", path = "./apub-openssl/", optional = true }
apub-reqwest = { version = "0.1.0", path = "./apub-reqwest/", optional = true }
apub-rustcrypto = { version = "0.1.0", path = "./apub-rustcrypto/", optional = true }
[dev-dependencies]
dashmap = "4.0.2"
openssl = "0.10"
reqwest = "0.11"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1.14", features = ["full"] }
url = { version = "2", features = ["serde"] }
[workspace]
members = [
"apub-actix-web",

View file

@ -10,3 +10,14 @@ apub-core = { version = "0.1.0", path = "../apub-core/" }
pin-project-lite = "0.2.7"
thiserror = "1"
url = "2"
[dev-dependencies]
apub-openssl = { version = "0.1.0", path = "../apub-openssl/" }
apub-reqwest = { version = "0.1.0", path = "../apub-reqwest/" }
dashmap = "4.0.2"
openssl = "0.10"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1.14", features = ["full"] }
url = { version = "2", features = ["serde"] }

View file

@ -1,4 +1,109 @@
//! A type to combine a remote Repo with a local Repo
//!
//! ```rust
//! use apub_core::deref::{Dereference, Repo};
//! use apub_deref_client::Client;
//! use apub_openssl::OpenSsl;
//! use apub_reqwest::{ReqwestClient, SignatureConfig};
//! use dashmap::DashMap;
//! use openssl::{
//! pkey::PKey,
//! rsa::Rsa,
//! };
//! use std::{
//! future::{ready, Ready},
//! sync::Arc,
//! time::Duration,
//! };
//! use url::{Host, Url};
//!
//! #[derive(Clone, Debug, Default)]
//! pub struct MemoryRepo {
//! inner: Arc<DashMap<Url, serde_json::Value>>,
//! }
//!
//! impl<'a, Id: Dereference + 'a> Repo<'a, Id> for MemoryRepo {
//! type Error = serde_json::Error;
//! type Future = Ready<Result<Option<Id::Output>, Self::Error>>;
//!
//! fn fetch(&'a self, id: Id) -> Self::Future {
//! if let Some(value) = self.inner.get(id.url()) {
//! ready(serde_json::from_value(value.clone()).map(Some))
//! } else {
//! ready(Ok(None))
//! }
//! }
//! }
//!
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
//! #[serde(transparent)]
//! struct MyId(Url);
//!
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
//! struct MyObject {
//! id: MyId,
//! content: String,
//! }
//!
//! impl Dereference for MyId {
//! type Output = MyObject;
//!
//! fn url(&self) -> &Url {
//! &self.0
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let existing_url: Url = "http://localhost:8080/object/hi".parse()?;
//! let existing_object = serde_json::to_value(MyObject {
//! id: MyId(existing_url.clone()),
//! content: String::from("hello"),
//! })?;
//!
//! let missing_url: Url = "http://localhost:8080/object/hello".parse()?;
//! let remote_url: Url = "https://masto.asonix.dog/users/asonix/statuses/107326693283572188".parse()?;
//!
//! let local_domain = Host::Domain(String::from("localhost"));
//! let local_port = Some(8080);
//!
//! let mut local_repo = MemoryRepo::default();
//! local_repo.inner.insert(
//! existing_url.clone(),
//! existing_object,
//! );
//!
//! let signature_config = SignatureConfig::default();
//! let private_key = PKey::from_rsa(Rsa::generate(1024)?)?;
//! let crypto = OpenSsl::new("key-id".to_string(), private_key);
//! let client = reqwest::Client::new();
//! let remote_repo = ReqwestClient::new(&client, (), &signature_config, &crypto);
//!
//! let deref_client = Client::new(
//! local_domain,
//! local_port,
//! &local_repo,
//! &remote_repo,
//! );
//!
//! let opt = deref_client.fetch(MyId(existing_url)).await?;
//! assert!(opt.is_some());
//! if let Some(my_object) = opt {
//! println!("{:?}", my_object);
//! }
//!
//! let opt = deref_client.fetch(MyId(missing_url)).await?;
//! assert!(opt.is_none());
//!
//! let opt = deref_client.fetch(MyId(remote_url)).await?;
//! assert!(opt.is_some());
//! if let Some(my_object) = opt {
//! println!("{:?}", my_object)
//! }
//!
//! Ok(())
//! }
//! ```
#![deny(missing_docs)]

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
actix-web = { version = "4.0.0-beta.11", default-features = false }
apub = { version = "0.1.0", path = "../../", features = ["actix-web", "rustcrypto"] }
apub = { version = "0.1.0", path = "../../", features = ["with-actix-web", "with-rustcrypto"] }
dashmap = "4.0.2"
env_logger = "0.9.0"
example-types = { version = "0.1.0", path = "../example-types/" }

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
actix-rt = "2.4.0"
apub = { version = "0.1.0", path = "../../", features = ["awc", "rustcrypto"] }
apub = { version = "0.1.0", path = "../../", features = ["with-awc", "with-rustcrypto"] }
awc = { version = "3.0.0-beta.10", default-features = false, features = ["rustls"] }
example-types = { version = "0.1.0", path = "../example-types/" }
rand = "0.8.4"

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
actix-rt = "2.4.0"
apub = { version = "0.1.0", path = "../../", features = ["awc", "background-jobs", "rustcrypto"] }
apub = { version = "0.1.0", path = "../../", features = ["with-awc", "with-background-jobs", "with-rustcrypto"] }
anyhow = "1"
awc = { version = "3.0.0-beta.10", default-features = false, features = ["rustls"] }
background-jobs = "0.11.0"

View file

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
apub = { version = "0.1.0", path = "../../", features = ["reqwest", "openssl"] }
apub = { version = "0.1.0", path = "../../", features = ["with-reqwest", "with-openssl"] }
example-types = { version = "0.1.0", path = "../example-types/" }
openssl = "0.10.13"
reqwest = "0.11.6"

View file

@ -1,10 +1,147 @@
pub mod clients {
//! Types and traits for fetching and delivering objects
//!
//! Notable types are [`CombinedClient`] behind the `utils` feature, [`ReqwestClient`] behind
//! the `with-reqwest` feature, and [`AwcClient`] behind the `awc` feature. Each of these types
//! implements the [`Repo`] trait, which describes fetching an object from a given repository.
//! While [`ReqwestClient`] and [`AwcClient`] both describe fetching objects from activitypub
//! remotes, [`CombinedClient`] is designed to easily fetch an object from a local repository,
//! such as a database or in-memory store, and fall back to an HTTP client for requests it can't
//! satisfy itself.
//!
//! [`ReqwestClient`] and [`AwcClient`] also implement the [`Client`] trait, which describes
//! delivering objects to activitypub remotes.
//!
//! Both [`ReqwestClient`] and [`AwcClient`] are built to use a generic [`Session`]
//! implementation and a generic [`SignFactory`] impelementation to extend request behavior and
//! support HTTP Signatures and HTTP Digests
//!
//! [`Session`]: crate::session::Session
//! [`SignFactory`]: crate::crypto::SignFactory
pub use apub_core::deliver::{Activity, Client};
pub use apub_core::deref::{Dereference, Repo};
pub use apub_core::object_id::ObjectId;
#[cfg(feature = "apub-deref-client")]
pub use apub_deref_client::{Client as CombinedClient, Error as CombinedError};
/// The type that combines Local and Remote repos
///
/// when both `Local` and `Http` implement [`Repo`], so does Client<Local, Http>
///
/// ```rust
/// use apub::{
/// clients::{
/// CombinedClient,
/// Dereference,
/// Repo,
/// ReqwestClient,
/// ReqwestSignatureConfig,
/// },
/// crypto::OpenSsl,
/// };
/// use dashmap::DashMap;
/// use openssl::{
/// pkey::PKey,
/// rsa::Rsa,
/// };
/// use std::{
/// future::{ready, Ready},
/// sync::Arc,
/// time::Duration,
/// };
/// use url::{Host, Url};
///
/// #[derive(Clone, Debug, Default)]
/// pub struct MemoryRepo {
/// inner: Arc<DashMap<Url, serde_json::Value>>,
/// }
///
/// impl<'a, Id: Dereference + 'a> Repo<'a, Id> for MemoryRepo {
/// type Error = serde_json::Error;
/// type Future = Ready<Result<Option<Id::Output>, Self::Error>>;
///
/// fn fetch(&'a self, id: Id) -> Self::Future {
/// if let Some(value) = self.inner.get(id.url()) {
/// ready(serde_json::from_value(value.clone()).map(Some))
/// } else {
/// ready(Ok(None))
/// }
/// }
/// }
///
/// #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
/// #[serde(transparent)]
/// struct MyId(Url);
///
/// #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
/// struct MyObject {
/// id: MyId,
/// content: String,
/// }
///
/// impl Dereference for MyId {
/// type Output = MyObject;
///
/// fn url(&self) -> &Url {
/// &self.0
/// }
/// }
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let existing_url: Url = "http://localhost:8080/object/hi".parse()?;
/// let existing_object = serde_json::to_value(MyObject {
/// id: MyId(existing_url.clone()),
/// content: String::from("hello"),
/// })?;
///
/// let missing_url: Url = "http://localhost:8080/object/hello".parse()?;
/// let remote_url: Url = "https://masto.asonix.dog/users/asonix/statuses/107326693283572188".parse()?;
///
/// let local_domain = Host::Domain(String::from("localhost"));
/// let local_port = Some(8080);
///
/// let mut local_repo = MemoryRepo::default();
/// local_repo.inner.insert(
/// existing_url.clone(),
/// existing_object,
/// );
///
/// let signature_config = ReqwestSignatureConfig::default();
/// let private_key = PKey::from_rsa(Rsa::generate(1024)?)?;
/// let crypto = OpenSsl::new("key-id".to_string(), private_key);
/// let client = reqwest::Client::new();
/// let remote_repo = ReqwestClient::new(&client, (), &signature_config, &crypto);
///
/// let deref_client = CombinedClient::new(
/// local_domain,
/// local_port,
/// &local_repo,
/// &remote_repo,
/// );
///
/// let opt = deref_client.fetch(MyId(existing_url)).await?;
/// assert!(opt.is_some());
/// if let Some(my_object) = opt {
/// println!("{:?}", my_object);
/// }
///
/// let opt = deref_client.fetch(MyId(missing_url)).await?;
/// assert!(opt.is_none());
///
/// let opt = deref_client.fetch(MyId(remote_url)).await?;
/// assert!(opt.is_some());
/// if let Some(my_object) = opt {
/// println!("{:?}", my_object)
/// }
///
/// Ok(())
/// }
/// ```
pub use apub_deref_client::Client as CombinedClient;
#[cfg(feature = "apub-deref-client")]
pub use apub_deref_client::Error as CombinedError;
#[cfg(feature = "apub-awc")]
pub use apub_awc::{