Skip to main content

actpub_nodeinfo/
lib.rs

1//! `NodeInfo` server metadata protocol for the Fediverse.
2//!
3//! Implements `NodeInfo` [2.0] / [2.1] and [FEP-0151] (`NodeInfo` 2025 edition),
4//! providing both discovery (`/.well-known/nodeinfo`) and schema documents.
5//!
6//! # Example (server)
7//!
8//! ```
9//! use actpub_nodeinfo::{NodeInfo, Software, Usage, UserCount, Protocol, Version};
10//!
11//! let info = NodeInfo::builder(Version::V2_1, Software::new("my-server", "1.0.0"))
12//!     .protocol(Protocol::ActivityPub)
13//!     .open_registrations(true)
14//!     .usage(Usage::new(UserCount::default().with_total(42)))
15//!     .build();
16//!
17//! let json = serde_json::to_string(&info).unwrap();
18//! assert!(json.contains(r#""version":"2.1""#));
19//! ```
20//!
21//! [2.0]: http://nodeinfo.diaspora.software/ns/schema/2.0
22//! [2.1]: http://nodeinfo.diaspora.software/ns/schema/2.1
23//! [FEP-0151]: https://codeberg.org/fediverse/fep/src/branch/main/fep/0151/fep-0151.md
24#![cfg_attr(docsrs, feature(doc_cfg))]
25#![allow(
26    clippy::error_impl_error,
27    reason = "`Error` is the idiomatic name for the crate's top-level error enum, matching the `thiserror` convention used pervasively in the Rust ecosystem"
28)]
29#![allow(
30    clippy::result_large_err,
31    reason = "The `CrossOriginHref` variant carries two `Url`s (discovery + attacker-supplied) so operators can triage SSRF-pivot attempts from logs; boxing the whole enum would complicate every happy path for no measurable cost on the always-cold error path"
32)]
33#![cfg_attr(
34    test,
35    allow(
36        clippy::indexing_slicing,
37        reason = "JSON field indexing via `Value[\"key\"]` is ergonomic inside tests and its panic-on-missing behaviour is the desired failure mode when fixtures are wrong"
38    )
39)]
40
41#[cfg(feature = "client")]
42#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
43mod client;
44mod discovery;
45mod error;
46mod schema;
47
48#[cfg(feature = "client")]
49#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
50pub use self::client::{
51    DEFAULT_MAX_BODY_BYTES, fetch, fetch_discovery, fetch_discovery_with_limit, fetch_with_limit,
52    recommended_client,
53};
54pub use self::discovery::{Discovery, DiscoveryLink, SCHEMA_REL_PREFIX};
55pub use self::error::Error;
56pub use self::schema::{
57    InboundService, NodeInfo, NodeInfoBuilder, OutboundService, Protocol, Services, Software,
58    Usage, UserCount, Version,
59};
60
61/// Crate [`Result`] alias with the default error type set to [`Error`].
62pub type Result<T, E = Error> = core::result::Result<T, E>;
63
64/// The well-known URI path for the `NodeInfo` discovery document.
65pub const WELL_KNOWN_PATH: &str = "/.well-known/nodeinfo";