Create webfinger
crate #5
4 changed files with 165 additions and 5 deletions
|
@ -11,6 +11,7 @@ axum = { version = "0.7.7", features = ["macros"] }
|
||||||
axum-extra = { version = "0.9.4", features = ["query"] }
|
axum-extra = { version = "0.9.4", features = ["query"] }
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
micronfig = "0.3.0"
|
micronfig = "0.3.0"
|
||||||
|
minijinja = "2.5.0"
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
quick-xml = { version = "0.37.0", features = ["serialize"] }
|
quick-xml = { version = "0.37.0", features = ["serialize"] }
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use std::sync::Arc;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use axum::Extension;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod route;
|
mod route;
|
||||||
|
@ -8,10 +10,18 @@ mod route;
|
||||||
async fn main() -> anyhow::Result<std::convert::Infallible> {
|
async fn main() -> anyhow::Result<std::convert::Infallible> {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
log::debug!("Logging initialized!");
|
log::debug!("Logging initialized!");
|
||||||
|
|
||||||
|
log::trace!("Creating Minijinja environment...");
|
||||||
|
let mut mj = minijinja::Environment::<'static>::new();
|
||||||
|
|
||||||
|
log::trace!("Adding webfinger page to the Minijinja environment...");
|
||||||
|
mj.add_template("webfinger.html.j2", include_str!("webfinger.html.j2"))
|
||||||
|
.expect("webfinger.html.j2 to be a valid Minijinja template");
|
||||||
|
|
||||||
log::trace!("Creating Axum router...");
|
log::trace!("Creating Axum router...");
|
||||||
let app = axum::Router::new()
|
let app = axum::Router::new()
|
||||||
.route("/.well-known/webfinger", axum::routing::get(route::webfinger_handler));
|
.route("/.well-known/webfinger", axum::routing::get(route::webfinger_handler))
|
||||||
|
.layer(Extension(Arc::new(mj)));
|
||||||
log::trace!("Axum router created successfully!");
|
log::trace!("Axum router created successfully!");
|
||||||
|
|
||||||
log::trace!("Creating Tokio listener...");
|
log::trace!("Creating Tokio listener...");
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use axum::Extension;
|
||||||
use axum::http::{HeaderMap, Response, StatusCode};
|
use axum::http::{HeaderMap, Response, StatusCode};
|
||||||
use axum_extra::extract::Query;
|
use axum_extra::extract::Query;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -22,6 +24,7 @@ const WEBFINGER_DOC: &str = "/.well-known/webfinger";
|
||||||
pub async fn webfinger_handler(
|
pub async fn webfinger_handler(
|
||||||
Query(WebfingerQuery {resource, rel}): Query<WebfingerQuery>,
|
Query(WebfingerQuery {resource, rel}): Query<WebfingerQuery>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
|
Extension(mj): Extension<Arc<minijinja::Environment<'static>>>,
|
||||||
) -> Result<Response<String>, StatusCode> {
|
) -> Result<Response<String>, StatusCode> {
|
||||||
log::info!("Handling a WebFinger request!");
|
log::info!("Handling a WebFinger request!");
|
||||||
|
|
||||||
|
@ -142,7 +145,7 @@ pub async fn webfinger_handler(
|
||||||
body.push_str(&json);
|
body.push_str(&json);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(response)
|
return Ok(response);
|
||||||
},
|
},
|
||||||
"application/xml" | "application/xrd+xml" => {
|
"application/xml" | "application/xrd+xml" => {
|
||||||
let subject = Some(resource);
|
let subject = Some(resource);
|
||||||
|
@ -196,15 +199,63 @@ pub async fn webfinger_handler(
|
||||||
|
|
||||||
{
|
{
|
||||||
let body = response.body_mut();
|
let body = response.body_mut();
|
||||||
body.push_str("<?xml version='1.0' encoding='UTF-8'?>");
|
body.push_str(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
|
||||||
body.push_str(&xml);
|
body.push_str(&xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(response)
|
return Ok(response);
|
||||||
|
},
|
||||||
|
"text/html" => {
|
||||||
|
let aliases: Vec<String> = aliases.into_iter()
|
||||||
|
.map(|alias| alias.alias)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let properties: Vec<(String, Option<String>)> = properties.into_iter()
|
||||||
|
.map(|prop| {
|
||||||
|
(prop.rel, prop.value)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let links: Vec<(String, Option<String>, Option<String>, Option<String>, Vec<(String, Option<String>)>, Vec<(String, String)>)> = links_full
|
||||||
|
.into_iter()
|
||||||
|
.map(|(link, properties, titles)| {
|
||||||
|
(
|
||||||
|
link.rel,
|
||||||
|
link.type_,
|
||||||
|
link.href,
|
||||||
|
link.template,
|
||||||
|
properties.into_iter()
|
||||||
|
.map(|prop| (prop.rel, prop.value))
|
||||||
|
.collect::<Vec<(String, Option<String>)>>(),
|
||||||
|
titles.into_iter()
|
||||||
|
.map(|title| (title.language, title.value))
|
||||||
|
.collect::<Vec<(String, String)>>()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let html = mj.get_template("webfinger.html.j2")
|
||||||
|
.expect("webfinger.html.j2 to exist")
|
||||||
|
.render(
|
||||||
|
minijinja::context!(
|
||||||
|
subject => resource,
|
||||||
|
aliases => aliases,
|
||||||
|
properties => properties,
|
||||||
|
links => links,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let body = response.body_mut();
|
||||||
|
body.push_str(&html);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
98
acrate-webfinger/src/webfinger.html.j2
Normal file
98
acrate-webfinger/src/webfinger.html.j2
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ subject }} · Acrate Webfinger</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
Acrate Webfinger
|
||||||
|
</h1>
|
||||||
|
<h2 id="section-subject">
|
||||||
|
<span>{{ subject }}</span>
|
||||||
|
</h2>
|
||||||
|
{% if aliases %}
|
||||||
|
<section id="section-aliases">
|
||||||
|
<h3>
|
||||||
|
Aliases
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
{% for alias in aliases %}
|
||||||
|
<li><span>{{ alias }}</span></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% if properties %}
|
||||||
|
<section id="section-properties">
|
||||||
|
<h3>
|
||||||
|
Properties
|
||||||
|
</h3>
|
||||||
|
<dl>
|
||||||
|
{% for property in properties %}
|
||||||
|
<dt>
|
||||||
|
<a href="{{ property[0] }}">{{ property[0] }}</a>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<span>{{ property[1] }}</span>
|
||||||
|
</dd>
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% if links %}
|
||||||
|
<section id="section-links">
|
||||||
|
<h3>
|
||||||
|
Links
|
||||||
|
</h3>
|
||||||
|
<dl>
|
||||||
|
{% for link in links %}
|
||||||
|
<dt>
|
||||||
|
<h4>
|
||||||
|
<a href="{{ link[0] }}">{{ link[0] }}</a>{% if link[1] is not none %} <small>(<span>{{ link[1] }}</span>)</small>{% endif %}
|
||||||
|
</h4>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<h5>
|
||||||
|
Link destination
|
||||||
|
</h5>
|
||||||
|
{% if link[2] is not none %}
|
||||||
|
<a href="{{ link[2] }}">{{ link[2] }}</a>
|
||||||
|
{% elif link[3] is not none %}
|
||||||
|
<span>{{ link[3] }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if link[4] %}
|
||||||
|
<h5>
|
||||||
|
Link properties
|
||||||
|
</h5>
|
||||||
|
<dl>
|
||||||
|
{% for property in link[4] %}
|
||||||
|
<dt>
|
||||||
|
<a href="{{ property[0] }}">{{ property[0] }}</a>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<span>{{ property[1] }}</span>
|
||||||
|
</dd>
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
{% endif %}
|
||||||
|
{% if link[5] %}
|
||||||
|
<h5>
|
||||||
|
Link titles
|
||||||
|
</h5>
|
||||||
|
<dl>
|
||||||
|
{% for title in link[5] %}
|
||||||
|
<dt>
|
||||||
|
<span>{{ title[0] }}</span>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<span>{{ title[1] }}</span>
|
||||||
|
</dd>
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
</body>
|
Loading…
Reference in a new issue