Update to actix 3.0
This commit is contained in:
parent
17cc4c9f21
commit
779b26e52e
16
Cargo.toml
16
Cargo.toml
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "actix-webfinger"
|
||||
description = "Types and helpers to create and fetch Webfinger resources"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0-alpha.0"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
repository = "https://git.asonix.dog/Aardwolf/actix-webfinger"
|
||||
|
@ -9,16 +9,14 @@ readme = "README.md"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-http = "0.2.3"
|
||||
actix-service = "0.4.1"
|
||||
actix-web = "1.0.0"
|
||||
failure = "0.1"
|
||||
futures = "0.1"
|
||||
actix-http = "2.0.0-alpha.1"
|
||||
actix-web = "3.0.0-alpha.1"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
actix = "0.8"
|
||||
actix-web = { version = "1.0.0", features = ["ssl"] }
|
||||
openssl = "0.10"
|
||||
actix = "0.10.0-alpha.1"
|
||||
actix-rt = "1.0.0"
|
||||
actix-web = { version = "3.0.0-alpha.1", features = ["openssl"] }
|
||||
serde_json = "1.0"
|
||||
|
|
51
README.md
51
README.md
|
@ -3,7 +3,7 @@ A library to aid in resolving and providing webfinger objects with the Actix Web
|
|||
|
||||
- [Read the documentation on docs.rs](https://docs.rs/actix-webfinger)
|
||||
- [Find the crate on crates.io](https://crates.io/crates/actix-webfinger)
|
||||
- [Join the discussion on Matrix](https://matrix.to/#/!JjjAVnljvJsHxWlnXP:asonix.dog?via=asonix.dog)
|
||||
- [Hit me up on Mastodon](https://asonix.dog/@asonix)
|
||||
|
||||
The main functionality this crate provides is through the `Webfinger::fetch` method for Actix
|
||||
Web-based clients, and the `Resolver<S>` trait for Actix Web-based servers.
|
||||
|
@ -13,41 +13,25 @@ First, add Actix Webfinger as a dependency
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
actix = "0.8"
|
||||
actix-web = "1.0.0"
|
||||
actix-webfinger = "0.2.0"
|
||||
actix = "0.10.0-alpha.1"
|
||||
actix-web = "3.0.0-alpha.1"
|
||||
actix-webfinger = "0.3.0-alpha.0"
|
||||
```
|
||||
|
||||
Then use it in your application
|
||||
|
||||
#### Client Example
|
||||
```rust
|
||||
use actix::System;
|
||||
use actix_web::client::Connector;
|
||||
use actix_web::client::Client;
|
||||
use actix_webfinger::Webfinger;
|
||||
use futures::{future::lazy, Future};
|
||||
use openssl::ssl::{SslConnector, SslMethod};
|
||||
use std::error::Error;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let sys = System::new("sir-boops");
|
||||
#[actix_rt::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let client = Client::default();
|
||||
let wf = Webfinger::fetch(&client, "asonix@asonix.dog", "localhost:8000", false).await?;
|
||||
|
||||
let ssl_conn = SslConnector::builder(SslMethod::tls())?.build();
|
||||
let conn = Connector::new().ssl(ssl_conn).finish();
|
||||
|
||||
let fut = lazy(move || {
|
||||
Webfinger::fetch(conn, "asonix@asonix.dog", "localhost:8000", false)
|
||||
.map(move |w: Webfinger| {
|
||||
println!("asonix's webfinger:\n{:#?}", w);
|
||||
|
||||
System::current().stop();
|
||||
})
|
||||
.map_err(|e| eprintln!("Error: {}", e))
|
||||
});
|
||||
|
||||
actix::spawn(fut);
|
||||
|
||||
sys.run()?;
|
||||
println!("asonix's webfinger:\n{:#?}", wf);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
@ -56,8 +40,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
```rust
|
||||
use actix_web::{web::Data, App, HttpServer};
|
||||
use actix_webfinger::{Resolver, Webfinger};
|
||||
use futures::{future::IntoFuture, Future};
|
||||
use std::error::Error;
|
||||
use std::{error::Error, future::Future, pin::Pin};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MyState {
|
||||
|
@ -73,18 +56,19 @@ impl Resolver<Data<MyState>> for MyResolver {
|
|||
account: &str,
|
||||
domain: &str,
|
||||
state: &Data<MyState>,
|
||||
) -> Box<dyn Future<Item = Option<Webfinger>, Error = Self::Error>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> {
|
||||
let w = if domain == state.domain {
|
||||
Some(Webfinger::new(&format!("{}@{}", account, domain)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Box::new(Ok(w).into_future())
|
||||
Box::pin(async move { Ok(w) })
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
#[actix_rt::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.data(MyState {
|
||||
|
@ -93,7 +77,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
.service(actix_webfinger::resource::<_, MyResolver>())
|
||||
})
|
||||
.bind("127.0.0.1:8000")?
|
||||
.run()?;
|
||||
.run()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -104,7 +89,7 @@ Feel free to open issues for anything you find an issue with. Please note that a
|
|||
|
||||
### License
|
||||
|
||||
Copyright © 2019 Riley Trautman
|
||||
Copyright © 2020 Riley Trautman
|
||||
|
||||
Actix Webfinger is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
|
|
|
@ -1,28 +1,12 @@
|
|||
use actix::System;
|
||||
use actix_web::client::Connector;
|
||||
use actix_web::client::Client;
|
||||
use actix_webfinger::Webfinger;
|
||||
use futures::{future::lazy, Future};
|
||||
use openssl::ssl::{SslConnector, SslMethod};
|
||||
use std::error::Error;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let sys = System::new("sir-boops");
|
||||
#[actix_rt::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let client = Client::default();
|
||||
let wf = Webfinger::fetch(&client, "asonix@asonix.dog", "localhost:8000", false).await?;
|
||||
|
||||
let ssl_conn = SslConnector::builder(SslMethod::tls())?.build();
|
||||
let conn = Connector::new().ssl(ssl_conn).finish();
|
||||
|
||||
let fut = lazy(move || {
|
||||
Webfinger::fetch(conn, "asonix@asonix.dog", "localhost:8000", false)
|
||||
.map(move |w: Webfinger| {
|
||||
println!("asonix's webfinger:\n{:#?}", w);
|
||||
|
||||
System::current().stop();
|
||||
})
|
||||
.map_err(|e| eprintln!("Error: {}", e))
|
||||
});
|
||||
|
||||
actix::spawn(fut);
|
||||
|
||||
sys.run()?;
|
||||
println!("asonix's webfinger:\n{:#?}", wf);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use actix_web::{web::Data, App, HttpServer};
|
||||
use actix_webfinger::{Resolver, Webfinger};
|
||||
use futures::{future::IntoFuture, Future};
|
||||
use std::error::Error;
|
||||
use std::{error::Error, future::Future, pin::Pin};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MyState {
|
||||
|
@ -17,18 +16,19 @@ impl Resolver<Data<MyState>> for MyResolver {
|
|||
account: &str,
|
||||
domain: &str,
|
||||
state: &Data<MyState>,
|
||||
) -> Box<dyn Future<Item = Option<Webfinger>, Error = Self::Error>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> {
|
||||
let w = if domain == state.domain {
|
||||
Some(Webfinger::new(&format!("{}@{}", account, domain)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Box::new(Ok(w).into_future())
|
||||
Box::pin(async move { Ok(w) })
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
#[actix_rt::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.data(MyState {
|
||||
|
@ -37,7 +37,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
.service(actix_webfinger::resource::<_, MyResolver>())
|
||||
})
|
||||
.bind("127.0.0.1:8000")?
|
||||
.run()?;
|
||||
.run()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
127
src/lib.rs
127
src/lib.rs
|
@ -9,45 +9,29 @@
|
|||
//!
|
||||
//! - [Read the documentation on docs.rs](https://docs.rs/actix-webfinger)
|
||||
//! - [Find the crate on crates.io](https://crates.io/crates/actix-webfinger)
|
||||
//! - [Join the discussion on Matrix](https://matrix.to/#/!JjjAVnljvJsHxWlnXP:asonix.dog?via=asonix.dog)
|
||||
//! - [Hit me up on Mastodon](https://asonix.dog/@asonix)
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! actix = "0.8"
|
||||
//! actix-web = "1.0.0"
|
||||
//! actix-webfinger = "0.2.0"
|
||||
//! actix = "0.10.0-alpha.1"
|
||||
//! actix-web = "3.0.0-alpha.1"
|
||||
//! actix-webfinger = "0.3.0-alpha.0"
|
||||
//! ```
|
||||
//!
|
||||
//! Then use it in your application
|
||||
//!
|
||||
//! #### Client Example
|
||||
//! ```rust,ignore
|
||||
//! use actix::System;
|
||||
//! use actix_web::client::Connector;
|
||||
//! use actix_web::client::Client;
|
||||
//! use actix_webfinger::Webfinger;
|
||||
//! use futures::{future::lazy, Future};
|
||||
//! use openssl::ssl::{SslConnector, SslMethod};
|
||||
//! use std::error::Error;
|
||||
//!
|
||||
//! fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let sys = System::new("asonix");
|
||||
//! #[actix_rt::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let client = Client::default();
|
||||
//! let wf = Webfinger::fetch(&client, "asonix@asonix.dog", "localhost:8000", false).await?;
|
||||
//!
|
||||
//! let ssl_conn = SslConnector::builder(SslMethod::tls())?.build();
|
||||
//! let conn = Connector::new().ssl(ssl_conn).finish();
|
||||
//!
|
||||
//! let fut = lazy(move || {
|
||||
//! Webfinger::fetch(conn, "asonix@asonix.dog", "localhost:8000", false)
|
||||
//! .map(move |w: Webfinger| {
|
||||
//! println!("asonix's webfinger:\n{:#?}", w);
|
||||
//!
|
||||
//! System::current().stop();
|
||||
//! })
|
||||
//! .map_err(|e| eprintln!("Error: {}", e))
|
||||
//! });
|
||||
//!
|
||||
//! actix::spawn(fut);
|
||||
//!
|
||||
//! sys.run()?;
|
||||
//! println!("asonix's webfinger:\n{:#?}", wf);
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
|
@ -56,8 +40,7 @@
|
|||
//! ```rust,ignore
|
||||
//! use actix_web::{web::Data, App, HttpServer};
|
||||
//! use actix_webfinger::{Resolver, Webfinger};
|
||||
//! use futures::{future::IntoFuture, Future};
|
||||
//! use std::error::Error;
|
||||
//! use std::{error::Error, future::Future, pin::Pin};
|
||||
//!
|
||||
//! #[derive(Clone, Debug)]
|
||||
//! pub struct MyState {
|
||||
|
@ -73,18 +56,19 @@
|
|||
//! account: &str,
|
||||
//! domain: &str,
|
||||
//! state: &Data<MyState>,
|
||||
//! ) -> Box<dyn Future<Item = Option<Webfinger>, Error = Self::Error>> {
|
||||
//! ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> {
|
||||
//! let w = if domain == state.domain {
|
||||
//! Some(Webfinger::new(&format!("{}@{}", account, domain)))
|
||||
//! } else {
|
||||
//! None
|
||||
//! };
|
||||
//!
|
||||
//! Box::new(Ok(w).into_future())
|
||||
//! Box::pin(async move { Ok(w) })
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! #[actix_rt::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! HttpServer::new(|| {
|
||||
//! App::new()
|
||||
//! .data(MyState {
|
||||
|
@ -93,7 +77,8 @@
|
|||
//! .service(actix_webfinger::resource::<_, MyResolver>())
|
||||
//! })
|
||||
//! .bind("127.0.0.1:8000")?
|
||||
//! .run()?;
|
||||
//! .run()
|
||||
//! .await?;
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
|
@ -104,15 +89,13 @@
|
|||
//!
|
||||
//! ### License
|
||||
//!
|
||||
//! Copyright © 2019 Riley Trautman
|
||||
//! Copyright © 2020 Riley Trautman
|
||||
//!
|
||||
//! Actix Webfinger is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
//!
|
||||
//! Actix Webfinger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of Tokio ZMQ.
|
||||
//!
|
||||
//! You should have received a copy of the GNU General Public License along with Actix Webfinger. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|
||||
use actix_http::client::{Connect, ConnectError, Connection};
|
||||
use actix_service::Service;
|
||||
use actix_web::{
|
||||
client::Client,
|
||||
dev::RequestHead,
|
||||
|
@ -122,9 +105,8 @@ use actix_web::{
|
|||
web::{get, Query},
|
||||
FromRequest, HttpResponse, Resource,
|
||||
};
|
||||
use failure::Fail;
|
||||
use futures::Future;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
/// A predicate for Actix Web route filters
|
||||
///
|
||||
|
@ -239,8 +221,8 @@ where
|
|||
/// - `asonix`
|
||||
///
|
||||
/// This error type captures the invalid string for inspection
|
||||
#[derive(Clone, Debug, Fail)]
|
||||
#[fail(display = "Resource {} is invalid", _0)]
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Resource {0} is invalid")]
|
||||
pub struct InvalidResource(String);
|
||||
|
||||
/// A type representing a valid resource query
|
||||
|
@ -328,7 +310,7 @@ pub struct WebfingerQuery {
|
|||
///
|
||||
/// ```rust,ignore
|
||||
/// use actix_webfinger::{Resolver, Webfinger};
|
||||
/// use futures::{Future, future::IntoFuture};
|
||||
/// use std::{future::Future, pin::Pin};
|
||||
///
|
||||
/// struct MyResolver;
|
||||
///
|
||||
|
@ -342,36 +324,32 @@ pub struct WebfingerQuery {
|
|||
/// account: &str,
|
||||
/// domain: &str,
|
||||
/// _state: S
|
||||
/// ) -> Box<dyn Future<Item = Option<Webfinger>, Error = Self::Error>> {
|
||||
/// ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> {
|
||||
/// let webfinger = Webfinger::new(&format!("{}@{}", account, domain));
|
||||
///
|
||||
/// // do something
|
||||
///
|
||||
/// let f = Ok(Some(webfinger)).into_future();
|
||||
///
|
||||
/// Box::new(f)
|
||||
/// Box::pin(async move { Ok(Some(webfinger)) })
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let sys = System::new("asonix");
|
||||
///
|
||||
/// #[actix_rt::main]
|
||||
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// HttpServer::new(|| {
|
||||
/// App::new()
|
||||
/// .data(())
|
||||
/// .service(resource::<Data<()>, MyResolver>())
|
||||
/// })
|
||||
/// .bind("127.0.0.1:8000")?
|
||||
/// .start();
|
||||
///
|
||||
/// sys.run()?;
|
||||
/// .run()
|
||||
/// .await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub trait Resolver<S>
|
||||
where
|
||||
S: FromRequest,
|
||||
S: FromRequest + 'static,
|
||||
{
|
||||
type Error: ResponseError + 'static;
|
||||
|
||||
|
@ -379,17 +357,19 @@ where
|
|||
account: &str,
|
||||
domain: &str,
|
||||
state: &S,
|
||||
) -> Box<dyn Future<Item = Option<Webfinger>, Error = Self::Error>>;
|
||||
) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>>;
|
||||
|
||||
fn endpoint(
|
||||
(query, state): (Query<WebfingerQuery>, S),
|
||||
) -> Box<dyn Future<Item = HttpResponse, Error = Self::Error>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<HttpResponse, Self::Error>>>> {
|
||||
let WebfingerResource { account, domain } = query.into_inner().resource;
|
||||
|
||||
Box::new(Self::find(&account, &domain, &state).map(|w| match w {
|
||||
Some(w) => w.respond(),
|
||||
None => HttpResponse::NotFound().finish(),
|
||||
}))
|
||||
Box::pin(async move {
|
||||
match Self::find(&account, &domain, &state).await? {
|
||||
Some(w) => Ok(w.respond()),
|
||||
None => Ok(HttpResponse::NotFound().finish()),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,19 +580,14 @@ impl Webfinger {
|
|||
|
||||
/// Fetch a webfinger with subject `user` from a given `domain`
|
||||
///
|
||||
/// This method takes an `Service` so derivative works can provide their own SSL
|
||||
/// connector implemenation (currently with OpenSSL or Rustls)
|
||||
pub fn fetch<T>(
|
||||
conn: T,
|
||||
/// This method takes a `Client` so derivative works can provide their own configured clients
|
||||
/// rather this library generating it's own http clients.
|
||||
pub async fn fetch(
|
||||
client: &Client,
|
||||
user: &str,
|
||||
domain: &str,
|
||||
https: bool,
|
||||
) -> Box<dyn Future<Item = Self, Error = FetchError>>
|
||||
where
|
||||
T: Service<Request = Connect, Error = ConnectError> + Clone + 'static,
|
||||
<T as Service>::Response: Connection,
|
||||
<T as Service>::Future: 'static,
|
||||
{
|
||||
) -> Result<Self, FetchError> {
|
||||
let url = format!(
|
||||
"{}://{}/.well-known/webfinger?resource=acct:{}",
|
||||
if https { "https" } else { "http" },
|
||||
|
@ -620,24 +595,22 @@ impl Webfinger {
|
|||
user
|
||||
);
|
||||
|
||||
let fut = Client::build()
|
||||
.connector(conn)
|
||||
.header("Accept", "application/jrd+json")
|
||||
.finish()
|
||||
let mut res = client
|
||||
.get(url)
|
||||
.header("Accept", "application/jrd+json")
|
||||
.send()
|
||||
.map_err(|_| FetchError::Send)
|
||||
.and_then(|mut res| res.json::<Webfinger>().map_err(|_| FetchError::Parse));
|
||||
.await
|
||||
.map_err(|_| FetchError::Send)?;
|
||||
|
||||
Box::new(fut)
|
||||
res.json::<Webfinger>().await.map_err(|_| FetchError::Parse)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Fail)]
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
pub enum FetchError {
|
||||
#[fail(display = "Failed to send request")]
|
||||
#[error("Failed to send request")]
|
||||
Send,
|
||||
#[fail(display = "Failed to parse response JSON")]
|
||||
#[error("Failed to parse response JSON")]
|
||||
Parse,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue