webfinger-rs 0.0.26

WebFinger request and response types for Rust, with first-party Reqwest, Axum, and Actix Web integrations.
Documentation

Webfinger-rs

Crates.io badge License badge Docs.rs badge Deps.rs badge

webfinger-rs is a Rust library for building and serving WebFinger requests and responses with RFC 7033-shaped types and first-party integrations for Reqwest, Axum, and Actix Web.

Use it when you want one WebFinger implementation across clients, servers, and tests instead of recreating the protocol details in each framework.

The full guide and API reference live on docs.rs.

Why webfinger-rs

  • Model WebFinger requests and JRD responses with reusable library types.
  • Execute client requests with Reqwest.
  • Expose WebFinger endpoints in Axum or Actix Web with the same request and response types.
  • Stay close to RFC 7033 without pulling in a larger identity stack.

Supported integrations

Feature What it enables
none Core request and response types, builders, and URL conversion support
reqwest Client execution helpers and Reqwest request/response conversions
axum Axum extractor and responder integration
actix Actix Web extractor and responder integration

Current integration targets:

  • Reqwest 0.13
  • Axum 0.8
  • Actix Web 4

Install

Add the crate with the feature set you need:

cargo add webfinger-rs
cargo add webfinger-rs --features reqwest
cargo add webfinger-rs --features axum
cargo add webfinger-rs --features actix

The companion CLI is useful for trying servers by hand:

cargo install webfinger-cli
webfinger acct:carol@example.com --rel http://webfinger.net/rel/avatar

Client quickstart

Enable reqwest to execute a request directly from WebFingerRequest:

use webfinger_rs::WebFingerRequest;

async fn example() -> Result<(), Box<dyn std::error::Error>> {
    let request = WebFingerRequest::builder("acct:carol@example.com")?
        .host("example.com")
        .rel("http://webfinger.net/rel/profile-page")
        .build();

    let response = request.execute_reqwest().await?;
    println!("{response:#?}");
    Ok(())
}

Server quickstart

Enable axum to extract WebFingerRequest and return WebFingerResponse from a handler mounted at /.well-known/webfinger:

use axum::{http::StatusCode, routing::get, Router};
use webfinger_rs::{Link, Rel, WELL_KNOWN_PATH, WebFingerRequest, WebFingerResponse};

async fn webfinger(request: WebFingerRequest) -> axum::response::Result<WebFingerResponse> {
    let subject = request.resource.to_string();
    if subject != "acct:carol@example.com" {
        return Err((StatusCode::NOT_FOUND, "not found").into());
    }

    let rel = Rel::new("http://webfinger.net/rel/profile-page");
    let response = if request.rels.is_empty() || request.rels.contains(&rel) {
        let link = Link::builder(rel).href("https://example.com/users/carol");
        WebFingerResponse::builder(subject).link(link).build()
    } else {
        WebFingerResponse::builder(subject).build()
    };
    Ok(response)
}

Router::new().route(WELL_KNOWN_PATH, get(webfinger))

Enable actix to use the same types in Actix Web:

use actix_web::{get, App};
use webfinger_rs::{Link, Rel, WebFingerRequest, WebFingerResponse};

#[get("/.well-known/webfinger")]
async fn webfinger(request: WebFingerRequest) -> actix_web::Result<WebFingerResponse> {
    let subject = request.resource.to_string();
    if subject != "acct:carol@example.com" {
        return Err(actix_web::error::ErrorNotFound("not found"));
    }

    let rel = Rel::new("http://webfinger.net/rel/profile-page");
    let response = if request.rels.is_empty() || request.rels.contains(&rel) {
        let link = Link::builder(rel).href("https://example.com/users/carol");
        WebFingerResponse::builder(subject).link(link).build()
    } else {
        WebFingerResponse::builder(subject).build()
    };
    Ok(response)
}

App::new().service(webfinger)

Learn more

  • API docs and deeper usage guide: docs.rs/webfinger-rs
  • Runnable examples: cargo run -p webfinger-rs --example client --features reqwest cargo run -p webfinger-rs --example axum --features axum cargo run -p webfinger-rs --example actix --features actix
  • CLI crate: webfinger-cli

The example servers listen on https://localhost:3000 and can be queried with:

webfinger acct:carol@localhost localhost:3000 --insecure \
  --rel http://webfinger.net/rel/profile-page

License

Copyright (c) Josh McKinney

This project is licensed under either of:

MSRV

This library is tested on the latest stable release of Rust. The minimum supported version is the previous stable release. The library may work on older versions, but that is not guaranteed.

Contributing

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

See CONTRIBUTING.md.