diff --git a/Cargo.toml b/Cargo.toml index a4f0007..2801760 100644 --- a/Cargo.toml +++ b/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 "] 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" diff --git a/README.md b/README.md index 78056b6..97b6268 100644 --- a/README.md +++ b/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` 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> { - let sys = System::new("sir-boops"); +#[actix_rt::main] +async fn main() -> Result<(), Box> { + 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> { ```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> for MyResolver { account: &str, domain: &str, state: &Data, - ) -> Box, Error = Self::Error>> { + ) -> Pin, 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> { +#[actix_rt::main] +async fn main() -> Result<(), Box> { HttpServer::new(|| { App::new() .data(MyState { @@ -93,7 +77,8 @@ fn main() -> Result<(), Box> { .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. diff --git a/examples/fetch.rs b/examples/fetch.rs index da3f87e..792ef11 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -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> { - let sys = System::new("sir-boops"); +#[actix_rt::main] +async fn main() -> Result<(), Box> { + 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(()) } diff --git a/examples/resolver.rs b/examples/resolver.rs index a51c17d..44f4511 100644 --- a/examples/resolver.rs +++ b/examples/resolver.rs @@ -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> for MyResolver { account: &str, domain: &str, state: &Data, - ) -> Box, Error = Self::Error>> { + ) -> Pin, 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> { +#[actix_rt::main] +async fn main() -> Result<(), Box> { HttpServer::new(|| { App::new() .data(MyState { @@ -37,7 +37,8 @@ fn main() -> Result<(), Box> { .service(actix_webfinger::resource::<_, MyResolver>()) }) .bind("127.0.0.1:8000")? - .run()?; + .run() + .await?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 602931b..808be81 100644 --- a/src/lib.rs +++ b/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> { -//! let sys = System::new("asonix"); +//! #[actix_rt::main] +//! async fn main() -> Result<(), Box> { +//! 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, -//! ) -> Box, Error = Self::Error>> { +//! ) -> Pin, 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> { +//! #[actix_rt::main] +//! async fn main() -> Result<(), Box> { //! 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, Error = Self::Error>> { +/// ) -> Pin, 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> { -/// let sys = System::new("asonix"); -/// +/// #[actix_rt::main] +/// async fn main() -> Result<(), Box> { /// HttpServer::new(|| { /// App::new() /// .data(()) /// .service(resource::, MyResolver>()) /// }) /// .bind("127.0.0.1:8000")? -/// .start(); -/// -/// sys.run()?; +/// .run() +/// .await?; /// /// Ok(()) /// } /// ``` pub trait Resolver where - S: FromRequest, + S: FromRequest + 'static, { type Error: ResponseError + 'static; @@ -379,17 +357,19 @@ where account: &str, domain: &str, state: &S, - ) -> Box, Error = Self::Error>>; + ) -> Pin, Self::Error>>>>; fn endpoint( (query, state): (Query, S), - ) -> Box> { + ) -> Pin>>> { 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( - 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> - where - T: Service + Clone + 'static, - ::Response: Connection, - ::Future: 'static, - { + ) -> Result { 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::().map_err(|_| FetchError::Parse)); + .await + .map_err(|_| FetchError::Send)?; - Box::new(fut) + res.json::().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, }