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"] }
|
||||
log = "0.4.22"
|
||||
micronfig = "0.3.0"
|
||||
minijinja = "2.5.0"
|
||||
pretty_env_logger = "0.5.0"
|
||||
quick-xml = { version = "0.37.0", features = ["serialize"] }
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
use anyhow::Context;
|
||||
use axum::Extension;
|
||||
|
||||
mod config;
|
||||
mod route;
|
||||
|
@ -8,10 +10,18 @@ mod route;
|
|||
async fn main() -> anyhow::Result<std::convert::Infallible> {
|
||||
pretty_env_logger::init();
|
||||
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...");
|
||||
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!("Creating Tokio listener...");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
use axum::Extension;
|
||||
use axum::http::{HeaderMap, Response, StatusCode};
|
||||
use axum_extra::extract::Query;
|
||||
use serde::Deserialize;
|
||||
|
@ -22,6 +24,7 @@ const WEBFINGER_DOC: &str = "/.well-known/webfinger";
|
|||
pub async fn webfinger_handler(
|
||||
Query(WebfingerQuery {resource, rel}): Query<WebfingerQuery>,
|
||||
headers: HeaderMap,
|
||||
Extension(mj): Extension<Arc<minijinja::Environment<'static>>>,
|
||||
) -> Result<Response<String>, StatusCode> {
|
||||
log::info!("Handling a WebFinger request!");
|
||||
|
||||
|
@ -142,7 +145,7 @@ pub async fn webfinger_handler(
|
|||
body.push_str(&json);
|
||||
}
|
||||
|
||||
return Ok(response)
|
||||
return Ok(response);
|
||||
},
|
||||
"application/xml" | "application/xrd+xml" => {
|
||||
let subject = Some(resource);
|
||||
|
@ -196,15 +199,63 @@ pub async fn webfinger_handler(
|
|||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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