Use associated type for resolver state

This commit is contained in:
asonix 2020-04-21 14:08:59 -05:00
parent 5e48aa725d
commit 33fd061a8a
5 changed files with 46 additions and 45 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "actix-webfinger" name = "actix-webfinger"
description = "Types and helpers to create and fetch Webfinger resources" description = "Types and helpers to create and fetch Webfinger resources"
version = "0.3.0-alpha.4" version = "0.3.0-alpha.5"
license = "GPL-3.0" license = "GPL-3.0"
authors = ["asonix <asonix@asonix.dog>"] authors = ["asonix <asonix@asonix.dog>"]
repository = "https://git.asonix.dog/Aardwolf/actix-webfinger" repository = "https://git.asonix.dog/Aardwolf/actix-webfinger"
@ -19,4 +19,5 @@ thiserror = "1.0"
actix = "0.10.0-alpha.1" actix = "0.10.0-alpha.1"
actix-rt = "1.0.0" actix-rt = "1.0.0"
actix-web = { version = "3.0.0-alpha.1", features = ["openssl"] } actix-web = { version = "3.0.0-alpha.1", features = ["openssl"] }
pretty_env_logger = "0.4"
serde_json = "1.0" serde_json = "1.0"

View file

@ -15,7 +15,7 @@ First, add Actix Webfinger as a dependency
[dependencies] [dependencies]
actix = "0.10.0-alpha.1" actix = "0.10.0-alpha.1"
actix-web = "3.0.0-alpha.1" actix-web = "3.0.0-alpha.1"
actix-webfinger = "0.3.0-alpha.4" actix-webfinger = "0.3.0-alpha.5"
``` ```
Then use it in your application Then use it in your application
@ -49,7 +49,8 @@ pub struct MyState {
pub struct MyResolver; pub struct MyResolver;
impl Resolver<Data<MyState>> for MyResolver { impl Resolver for MyResolver {
type State = Data<MyState>;
type Error = actix_web::error::JsonPayloadError; type Error = actix_web::error::JsonPayloadError;
fn find( fn find(

View file

@ -5,7 +5,7 @@ use std::error::Error;
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
let client = Client::default(); let client = Client::default();
let wf = Webfinger::fetch(&client, "asonix@asonix.dog", "localhost:8000", false).await?; let wf = Webfinger::fetch(&client, "asonix@localhost:8000", "localhost:8000", false).await?;
println!("asonix's webfinger:\n{:#?}", wf); println!("asonix's webfinger:\n{:#?}", wf);
Ok(()) Ok(())

View file

@ -1,4 +1,4 @@
use actix_web::{web::Data, App, HttpServer}; use actix_web::{middleware::Logger, web::Data, App, HttpServer};
use actix_webfinger::{Resolver, Webfinger}; use actix_webfinger::{Resolver, Webfinger};
use std::{error::Error, future::Future, pin::Pin}; use std::{error::Error, future::Future, pin::Pin};
@ -9,7 +9,8 @@ pub struct MyState {
pub struct MyResolver; pub struct MyResolver;
impl Resolver<Data<MyState>> for MyResolver { impl Resolver for MyResolver {
type State = Data<MyState>;
type Error = actix_web::error::JsonPayloadError; type Error = actix_web::error::JsonPayloadError;
fn find( fn find(
@ -29,12 +30,15 @@ impl Resolver<Data<MyState>> for MyResolver {
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
std::env::set_var("RUST_LOG", "info");
pretty_env_logger::init();
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
.data(MyState { .data(MyState {
domain: "localhost:8000".to_owned(), domain: "localhost:8000".to_owned(),
}) })
.service(actix_webfinger::resource::<_, MyResolver>()) .wrap(Logger::default())
.service(actix_webfinger::resource::<MyResolver>())
}) })
.bind("127.0.0.1:8000")? .bind("127.0.0.1:8000")?
.run() .run()

View file

@ -2,7 +2,7 @@
//! A library to aid in resolving and providing webfinger objects with the Actix Web web framework. //! A library to aid in resolving and providing webfinger objects with the Actix Web web framework.
//! //!
//! The main functionality this crate provides is through the `Webfinger::fetch` method for Actix //! 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. //! Web-based clients, and the `Resolver` trait for Actix Web-based servers.
//! //!
//! ### Usage //! ### Usage
//! First, add Actix Webfinger as a dependency //! First, add Actix Webfinger as a dependency
@ -49,7 +49,8 @@
//! //!
//! pub struct MyResolver; //! pub struct MyResolver;
//! //!
//! impl Resolver<Data<MyState>> for MyResolver { //! impl Resolver for MyResolver {
//! type State = Data<MyState>;
//! type Error = actix_web::error::JsonPayloadError; //! type Error = actix_web::error::JsonPayloadError;
//! //!
//! fn find( //! fn find(
@ -74,7 +75,7 @@
//! .data(MyState { //! .data(MyState {
//! domain: "asonix.dog".to_owned(), //! domain: "asonix.dog".to_owned(),
//! }) //! })
//! .service(actix_webfinger::resource::<_, MyResolver>()) //! .service(actix_webfinger::resource::<MyResolver>())
//! }) //! })
//! .bind("127.0.0.1:8000")? //! .bind("127.0.0.1:8000")?
//! .run() //! .run()
@ -171,19 +172,18 @@ impl Guard for WebfingerGuard {
/// ///
/// HttpServer::new(|| { /// HttpServer::new(|| {
/// App::new() /// App::new()
/// .service(actix_webfinger::resource::<_, MyResolver>()) /// .service(actix_webfinger::resource::<MyResolver>())
/// }) /// })
/// .bind("127.0.0.1:8000")? /// .bind("127.0.0.1:8000")?
/// .start(); /// .start();
/// ``` /// ```
pub fn resource<S, R>() -> Resource pub fn resource<R>() -> Resource
where where
R: Resolver<S> + 'static, R: Resolver + 'static,
S: FromRequest + 'static,
{ {
actix_web::web::resource("/.well-known/webfinger") actix_web::web::resource("/.well-known/webfinger")
.guard(WebfingerGuard) .guard(WebfingerGuard)
.route(get().to(R::endpoint)) .route(get().to(endpoint::<R>))
} }
/// A simple way to mount the webfinger service inside the /.well-known scope /// A simple way to mount the webfinger service inside the /.well-known scope
@ -197,20 +197,19 @@ where
/// .data(()) /// .data(())
/// .service( /// .service(
/// scope("/") /// scope("/")
/// .service(resource::<(), MyResolver>()) /// .service(resource::<MyResolver>())
/// ) /// )
/// }) /// })
/// .bind("127.0.0.1:8000") /// .bind("127.0.0.1:8000")
/// .start(); /// .start();
/// ``` /// ```
pub fn scoped<S, R>() -> Resource pub fn scoped<R>() -> Resource
where where
R: Resolver<S> + 'static, R: Resolver + 'static,
S: FromRequest + 'static,
{ {
actix_web::web::resource("/webfinger") actix_web::web::resource("/webfinger")
.guard(WebfingerGuard) .guard(WebfingerGuard)
.route(get().to(R::endpoint)) .route(get().to(endpoint::<R>))
} }
/// The error created if the webfinger resource query is malformed /// The error created if the webfinger resource query is malformed
@ -312,25 +311,20 @@ pub struct WebfingerQuery {
/// A trait to ease the implementation of Webfinger Resolvers /// A trait to ease the implementation of Webfinger Resolvers
/// ///
/// This trait can be implemented, and the provided `endpoint` method used to serve requests to an
/// Actix Web server.
///
/// ```rust,ignore /// ```rust,ignore
/// use actix_webfinger::{Resolver, Webfinger}; /// use actix_webfinger::{Resolver, Webfinger};
/// use std::{future::Future, pin::Pin}; /// use std::{future::Future, pin::Pin};
/// ///
/// struct MyResolver; /// struct MyResolver;
/// ///
/// impl<S> Resolver<S> for MyResolver /// impl Resolver for MyResolver {
/// where /// type State = ();
/// S: FromRequest,
/// {
/// type Error = CustomError; /// type Error = CustomError;
/// ///
/// fn find( /// fn find(
/// account: &str, /// account: &str,
/// domain: &str, /// domain: &str,
/// _state: S /// _state: Self::State,
/// ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> { /// ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>> {
/// let webfinger = Webfinger::new(&format!("{}@{}", account, domain)); /// let webfinger = Webfinger::new(&format!("{}@{}", account, domain));
/// ///
@ -345,7 +339,7 @@ pub struct WebfingerQuery {
/// HttpServer::new(|| { /// HttpServer::new(|| {
/// App::new() /// App::new()
/// .data(()) /// .data(())
/// .service(resource::<Data<()>, MyResolver>()) /// .service(resource::<MyResolver>())
/// }) /// })
/// .bind("127.0.0.1:8000")? /// .bind("127.0.0.1:8000")?
/// .run() /// .run()
@ -354,30 +348,31 @@ pub struct WebfingerQuery {
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
pub trait Resolver<S> pub trait Resolver {
where type State: FromRequest + 'static;
S: FromRequest + 'static,
{
type Error: ResponseError + 'static; type Error: ResponseError + 'static;
fn find( fn find(
account: &str, account: &str,
domain: &str, domain: &str,
state: S, state: Self::State,
) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>>; ) -> Pin<Box<dyn Future<Output = Result<Option<Webfinger>, Self::Error>>>>;
}
fn endpoint( pub fn endpoint<R>(
(query, state): (Query<WebfingerQuery>, S), (query, state): (Query<WebfingerQuery>, R::State),
) -> Pin<Box<dyn Future<Output = Result<HttpResponse, Self::Error>>>> { ) -> Pin<Box<dyn Future<Output = Result<HttpResponse, R::Error>>>>
let WebfingerResource { account, domain } = query.into_inner().resource; where
R: Resolver,
{
let WebfingerResource { account, domain } = query.into_inner().resource;
Box::pin(async move { Box::pin(async move {
match Self::find(&account, &domain, state).await? { match R::find(&account, &domain, state).await? {
Some(w) => Ok(w.respond()), Some(w) => Ok(w.respond()),
None => Ok(HttpResponse::NotFound().finish()), None => Ok(HttpResponse::NotFound().finish()),
} }
}) })
}
} }
/// The webfinger Link type /// The webfinger Link type