webfinger_rs/lib.rs
1//! `webfinger-rs` is a Rust library for handling WebFinger protocol defined by [RFC 7033].
2//!
3//! WebFinger is is used to discover information about people or other entities on the internet.
4//! The motivation of this library is to provide a transport-agnostic implementation of the
5//! WebFinger protocol for client and server-side application which can be used with different HTTP
6//! libraries such as [Axum], and [Reqwest]. Additionally, the other available crates for WebFinger
7//! are either not actively maintained and have a license that is incompatible with incorporating
8//! the crate into other projects as a library (GPL-3.0).
9//!
10//! [RFC 7033]: https://www.rfc-editor.org/rfc/rfc7033.html
11//! [Axum]: https://crates.io/crates/axum
12//! [Reqwest]: https://crates.io/crates/reqwest
13//!
14//! # Usage
15//!
16//! To use this library, add it to your `Cargo.toml`:
17//!
18//! ```shell
19//! cargo add webfinger-rs
20//! ```
21//!
22//! The library also has a related CLI tool, [`webfinger-cli`], which can be installed with:
23//!
24//! ```shell
25//! cargo install webfinger-cli
26//! webfinger acct:carol@example.com --rel http://webfinger.net/rel/avatar
27//! ```
28#![doc = document_features::document_features!()]
29//!
30//! # Client Example
31//!
32//! The following example connects to the WebFinger server at `example.com` and requests the profile
33//! page for the user `carol@example.com`. It requires the `reqwest` feature to be enabled. This
34//! example is also available in the repository at:
35//! <https://github.com/joshka/webfinger-rs/blob/main/webfinger-rs/examples/client.rs>.
36//!
37//! ```rust,no_run
38//! use webfinger_rs::WebFingerRequest;
39//!
40//! #[tokio::main]
41//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
42//! let request = WebFingerRequest::builder("acct:carol@example.com")?
43//! .host("example.com")
44//! .rel("http://webfinger.net/rel/profile-page")
45//! .build();
46//! let response = request.execute_reqwest().await?;
47//! dbg!(response);
48//! Ok(())
49//! }
50//! ```
51//!
52//! # Server Example
53//!
54//! The following example is an Axum handler that responds to WebFinger requests. It requires the
55//! `axum` feature to be enabled. This example is also available in the repository at:
56//! <https://github.com/joshka/webfinger-rs/blob/main/webfinger-rs/examples/axum.rs>.
57//!
58//! ```rust
59//! use axum::response::Result as AxumResult;
60//! use webfinger_rs::{Link, Rel, WebFingerRequest, WebFingerResponse};
61//!
62//! async fn webfinger(request: WebFingerRequest) -> AxumResult<WebFingerResponse> {
63//! let subject = request.resource.to_string();
64//! if subject != "acct:carol@example.com" {
65//! Err((http::StatusCode::NOT_FOUND, "Not Found"))?;
66//! }
67//! let rel = Rel::new("http://webfinger.net/rel/profile-page");
68//! let response = if request.rels.is_empty() || request.rels.contains(&rel) {
69//! let link = Link::builder(rel).href(format!("https://example.com/profile/{subject}"));
70//! WebFingerResponse::builder(subject).link(link).build()
71//! } else {
72//! WebFingerResponse::builder(subject).build()
73//! };
74//! Ok(response)
75//! }
76//! ```
77//!
78//! # Running the examples
79//!
80//! To run the examples, you can use the following commands:
81//!
82//! ```shell
83//! cargo run --example actix --features actix
84//! cargo run --example axum --features axum
85//! ```
86//!
87//! This will start a server on `https://localhost:3000` that responds to WebFinger requests for a
88//! single user, `carol@localhost`. Use [`webfinger-cli`] tool to query these servers. The servers
89//! create self-signed certificates for `localhost`, which can be ignored with the `--insecure`
90//! flag.
91//!
92//! ```shell
93//! cargo install webfinger-cli
94//! webfinger acct:carol@localhost localhost:3000 --insecure --rel http://webfinger.net/rel/profile-page
95//! ```
96//!
97//! [`webfinger-cli`]: https://crates.io/crates/webfinger-cli
98//!
99//! # Features / TODO list
100//!
101//! - [x] Client side types
102//! - [x] Reqwest interaction
103//! - [x] Server side types
104//! - [x] Axum integration
105//! - [x] Actix integration
106//!
107//! # Stability
108//!
109//! This library is in early days and will have semver breaking changes in the 0.0.x releases. Once
110//! 0.1.0 is released, semver breaking changes will bump the minor version.
111//!
112//! # License
113//!
114//! Copyright (c) 2024 Josh McKinney
115//!
116//! This project is licensed under either of:
117//!
118//! - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <https://apache.org/licenses/LICENSE-2.0>)
119//! - MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>) at your
120//! option.
121#![deny(missing_docs)]
122#![cfg_attr(docsrs, feature(doc_auto_cfg))]
123
124pub use crate::error::Error;
125pub use crate::types::{
126 Link, LinkBuilder, Rel, Request as WebFingerRequest, RequestBuilder,
127 Response as WebFingerResponse, ResponseBuilder, Title,
128};
129
130#[cfg(feature = "actix")]
131mod actix;
132#[cfg(feature = "axum")]
133mod axum;
134mod error;
135mod http;
136#[cfg(feature = "reqwest")]
137mod reqwest;
138mod types;
139
140/// The well-known path for WebFinger requests (`/.well-known/webfinger`).
141///
142/// This is the path that should be used to query for WebFinger resources.
143///
144/// See [RFC 7033 Section 10.1](https://www.rfc-editor.org/rfc/rfc7033.html#section-10.1) for more
145/// information.
146pub const WELL_KNOWN_PATH: &str = "/.well-known/webfinger";