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]
name = "actix-webfinger"
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"
authors = ["asonix <asonix@asonix.dog>"]
repository = "https://git.asonix.dog/Aardwolf/actix-webfinger"
@ -19,4 +19,5 @@ thiserror = "1.0"
actix = "0.10.0-alpha.1"
actix-rt = "1.0.0"
actix-web = { version = "3.0.0-alpha.1", features = ["openssl"] }
pretty_env_logger = "0.4"
serde_json = "1.0"

View File

@ -15,7 +15,7 @@ First, add Actix Webfinger as a dependency
[dependencies]
actix = "0.10.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
@ -49,7 +49,8 @@ pub struct MyState {
pub struct MyResolver;
impl Resolver<Data<MyState>> for MyResolver {
impl Resolver for MyResolver {
type State = Data<MyState>;
type Error = actix_web::error::JsonPayloadError;
fn find(

View File

@ -5,7 +5,7 @@ use std::error::Error;
#[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 wf = Webfinger::fetch(&client, "asonix@localhost:8000", "localhost:8000", false).await?;
println!("asonix's webfinger:\n{:#?}", wf);
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 std::{error::Error, future::Future, pin::Pin};
@ -9,7 +9,8 @@ pub struct MyState {
pub struct MyResolver;
impl Resolver<Data<MyState>> for MyResolver {
impl Resolver for MyResolver {
type State = Data<MyState>;
type Error = actix_web::error::JsonPayloadError;
fn find(
@ -29,12 +30,15 @@ impl Resolver<Data<MyState>> for MyResolver {
#[actix_rt::main]
async fn main() -> Result<(), Box<dyn Error>> {
std::env::set_var("RUST_LOG", "info");
pretty_env_logger::init();
HttpServer::new(|| {
App::new()
.data(MyState {
domain: "localhost:8000".to_owned(),
})
.service(actix_webfinger::resource::<_, MyResolver>())
.wrap(Logger::default())
.service(actix_webfinger::resource::<MyResolver>())
})
.bind("127.0.0.1:8000")?
.run()

View File

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