webfinger_rs/
lib.rs

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

pub use crate::{
    error::Error,
    types::{
        Link, LinkBuilder, Rel, Request as WebFingerRequest, RequestBuilder,
        Response as WebFingerResponse, ResponseBuilder, Title,
    },
};

#[cfg(feature = "actix")]
mod actix;
#[cfg(feature = "axum")]
mod axum;
mod error;
mod http;
#[cfg(feature = "reqwest")]
mod reqwest;
mod types;

/// The well-known path for WebFinger requests (`/.well-known/webfinger`).
///
/// This is the path that should be used to query for WebFinger resources.
///
/// See [RFC 7033 Section 10.1](https://www.rfc-editor.org/rfc/rfc7033.html#section-10.1) for more
/// information.
pub const WELL_KNOWN_PATH: &str = "/.well-known/webfinger";