pub struct Link {
pub rel: Rel,
pub type: Option<String>,
pub href: Option<JrdUri>,
pub template: Option<String>,
pub titles: Option<BTreeMap<String, String>>,
pub properties: Option<BTreeMap<JrdUri, Option<String>>>,
}Expand description
A link in the WebFinger response.
Link objects describe related resources for the JRD subject. RFC 7033 gives each link a
required rel member and optional type, href, titles, and properties
members. Some WebFinger profiles also use the JRD template member from RFC 6415 link
templates.
The Rust fields mirror the JRD JSON shape:
relis aRelso the required relation string is validated as one relation type.hrefis aJrdUribecause RFC 7033 defines it as a URI string.templateis a URI template string.titlesis a language-keyed object, matching the RFC JSON form.propertiesusesJrdUrikeys andOption<String>values so JSONnullis representable.
Use Link::builder for ordinary construction from string literals or application values. Use
Link::new when you already have a validated Rel.
§Examples
use webfinger_rs::Link;
let link = Link::builder("http://webfinger.net/rel/profile-page")
.href("https://example.com/profile/carol")
.r#type("text/html")
.title("en-us", "Carol's profile")
.property("https://example.com/ns/verified", "true")
.null_property("https://example.com/ns/old-profile")
.build();
assert_eq!(link.rel.as_ref(), "http://webfinger.net/rel/profile-page");Fields§
§rel: RelThe relation type of the link.
This member is required by RFC 7033 section 4.4.4.1. It uses Rel instead of String
so deserialization and builder construction both reject empty or malformed relation
values.
type: Option<String>The media type of the link.
RFC 7033 leaves this as a media type string. The crate stores it as String because it is
advisory metadata for the linked representation, not one of the WebFinger URI-valued
fields.
href: Option<JrdUri>The target URI of the link.
RFC 7033 defines href as a URI string. The field uses JrdUri rather than String so
relative references are rejected when links are deserialized or built through the builder.
template: Option<String>A URI template for the link.
RFC 6415 defines template as an optional JRD link member for link templates. The crate
stores it as a string because WebFinger servers do not need to parse or expand the template
expression before serializing it.
See RFC 6415 appendix A.
titles: Option<BTreeMap<String, String>>The titles of the link.
RFC 7033 models titles as a JSON object whose keys are language tags and whose values are
title strings. The crate uses a BTreeMap so direct struct construction preserves that JSON
object shape and gets deterministic ordering for comparisons, hashing, and rendered output.
Use LinkBuilder::title for one title at a time or LinkBuilder::titles to set a full
language map.
properties: Option<BTreeMap<JrdUri, Option<String>>>The properties of the link.
Link properties are a JSON object whose property identifiers are URI strings. Values may be
strings or JSON null, so the Rust value type is Option<String>. None serializes as a
property value of null; it does not omit the property from the map.
Use LinkBuilder::property for string-valued properties and
LinkBuilder::null_property for JSON null values.
Implementations§
Source§impl Link
impl Link
Sourcepub fn new(rel: Rel) -> Self
pub fn new(rel: Rel) -> Self
Creates a link from an already validated relation type.
The returned link has no optional members set. This is useful when relation validation
happens separately, for example when reusing a Rel from a request filter. Use
Link::builder when constructing a link directly from strings.
Sourcepub fn builder<R: AsRef<str>>(rel: R) -> LinkBuilder
pub fn builder<R: AsRef<str>>(rel: R) -> LinkBuilder
Creates a LinkBuilder with the given relation type.
The builder accepts a string-like value for the common case and validates it into Rel.
Invalid values panic through Rel::new; use Rel::try_new and Link::new when the
relation comes from untrusted input.
Examples found in repository?
68async fn webfinger(request: WebFingerRequest) -> actix_web::Result<WebFingerResponse> {
69 info!("fetching webfinger resource: {:?}", request);
70 let subject = request.resource.to_string();
71 if subject != SUBJECT {
72 let message = format!("{subject} does not exist");
73 return Err(actix_web::error::ErrorNotFound(message))?;
74 }
75 let mut links = Vec::new();
76
77 let profile_rel = Rel::new(PROFILE_PAGE_REL);
78 if request.rels.is_empty() || request.rels.contains(&profile_rel) {
79 links.push(
80 Link::builder(profile_rel)
81 .href(PROFILE_HREF)
82 .title("en", "Carol's profile")
83 .build(),
84 );
85 }
86
87 let avatar_rel = Rel::new(AVATAR_REL);
88 if request.rels.is_empty() || request.rels.contains(&avatar_rel) {
89 links.push(
90 Link::builder(avatar_rel)
91 .href(AVATAR_HREF)
92 .r#type("image/png")
93 .build(),
94 );
95 }
96
97 let response = WebFingerResponse::builder(subject)
98 .alias(PROFILE_HREF)
99 .property(ROLE_PROPERTY, "maintainer")
100 .links(links)
101 .build();
102 Ok(response)
103}More examples
71async fn webfinger(request: WebFingerRequest) -> axum::response::Result<WebFingerResponse> {
72 info!("fetching webfinger resource: {:?}", request);
73 let subject = request.resource.to_string();
74 if subject != SUBJECT {
75 let message = format!("{subject} does not exist");
76 return Err((StatusCode::NOT_FOUND, message).into());
77 }
78 let mut links = Vec::new();
79
80 let profile_rel = Rel::new(PROFILE_PAGE_REL);
81 if request.rels.is_empty() || request.rels.contains(&profile_rel) {
82 links.push(
83 Link::builder(profile_rel)
84 .href(PROFILE_HREF)
85 .title("en", "Carol's profile")
86 .build(),
87 );
88 }
89
90 let avatar_rel = Rel::new(AVATAR_REL);
91 if request.rels.is_empty() || request.rels.contains(&avatar_rel) {
92 links.push(
93 Link::builder(avatar_rel)
94 .href(AVATAR_HREF)
95 .r#type("image/png")
96 .build(),
97 );
98 }
99
100 let response = WebFingerResponse::builder(subject)
101 .alias(PROFILE_HREF)
102 .property(ROLE_PROPERTY, "maintainer")
103 .links(links)
104 .build();
105 Ok(response)
106}Trait Implementations§
Source§impl<'de> Deserialize<'de> for Link
impl<'de> Deserialize<'de> for Link
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Link
Source§impl From<LinkBuilder> for Link
impl From<LinkBuilder> for Link
Source§fn from(builder: LinkBuilder) -> Self
fn from(builder: LinkBuilder) -> Self
Source§impl Ord for Link
impl Ord for Link
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for Link
impl PartialOrd for Link
impl StructuralPartialEq for Link
Auto Trait Implementations§
impl Freeze for Link
impl RefUnwindSafe for Link
impl Send for Link
impl Sync for Link
impl Unpin for Link
impl UnsafeUnpin for Link
impl UnwindSafe for Link
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.