magnetar/ext_host_meta/src/lib.rs

98 lines
2.9 KiB
Rust

use magnetar_core::web_model::{content_type::ContentXrdXml, rel::RelLrdd, Rel};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum XrdXml {
#[serde(rename = "XRD")]
Xrd(Xrd),
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Xrd {
#[serde(rename = "@xmlns")]
xmlns: String,
#[serde(rename = "Link")]
links: Vec<Link>,
}
impl Xrd {
pub fn default_host_meta(protocol: &str, domain: &str) -> Xrd {
Xrd {
xmlns: r#"http://docs.oasis-open.org/ns/xri/xrd-1.0"#.to_string(),
links: vec![Link {
rel: Some(RelLrdd.rel().to_string()),
r#type: Some(ContentXrdXml.as_ref().to_string()),
href: None,
template: Some(format!(
"{}://{}/.well-known/webfinger?resource={{uri}}",
protocol, domain
)),
}],
}
}
pub fn get_webfinger_template(&self) -> Option<&str> {
self.links
.iter()
.find(|l| {
l.r#type.as_deref() == Some(ContentXrdXml.as_ref())
&& l.rel.as_deref() == Some(RelLrdd.as_ref())
})
.and_then(|l| l.template.as_deref())
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename = "Link")]
pub struct Link {
#[serde(rename = "@rel")]
#[serde(skip_serializing_if = "Option::is_none")]
rel: Option<String>,
#[serde(rename = "@type")]
#[serde(skip_serializing_if = "Option::is_none")]
r#type: Option<String>,
#[serde(rename = "@href")]
#[serde(skip_serializing_if = "Option::is_none")]
href: Option<String>,
#[serde(rename = "@template")]
#[serde(skip_serializing_if = "Option::is_none")]
template: Option<String>,
}
#[cfg(test)]
mod test {
use std::error::Error;
use crate::{Xrd, XrdXml};
#[test]
fn should_parse_host_meta() -> Result<(), Box<dyn Error>> {
let xml = r#"
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://example.org/.well-known/webfinger?resource={uri}"/>
</XRD>
"#;
let XrdXml::Xrd(xrd) = quick_xml::de::from_str::<XrdXml>(xml)?;
assert_eq!(xrd, Xrd::default_host_meta("https", "example.org"));
Ok(())
}
#[test]
fn should_fail_on_invalid_root_tag() {
let xml = r#"
<?xml version="1.0" encoding="UTF-8"?>
<ABC xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" type="application/xrd+xml" template="https://example.org/.well-known/webfinger?resource={uri}"/>
</ABC>
"#;
let xrd = quick_xml::de::from_str::<XrdXml>(xml);
assert!(xrd.is_err());
}
}