Atom feed, GUID for RSS feed

This commit is contained in:
Pantonshire committed 2022-05-25 20:52:23 +01:00
1 parent aa06d2c5ef
commit 1b4be0862c
13 files changed
+276 -60

No files matched your search

+82
View File
@@ -0,0 +1,82 @@
use std::sync::Arc;
use atom_syndication as atom;
use axum::{
body::Bytes,
extract::Extension,
};
use super::response::Atom;
use crate::{
Config,
posts_store::ConcurrentPostsStore,
time::unix_epoch,
};
pub async fn handle(
Extension(config): Extension<Arc<Config>>,
Extension(posts): Extension<ConcurrentPostsStore>,
) -> Atom<Bytes> {
let (atom_entries, updated) = {
let guard = posts.read().await;
let atom_entries = guard.iter_by_created()
.take(config.atom.num_posts)
.map(|post| {
atom::EntryBuilder::default()
.id(format!("urn:uuid:{}", post.uuid()))
.title(post.title().to_owned())
.updated(post.updated())
.links(vec![
atom::LinkBuilder::default()
.href(format!(
"{}://{}/articles/{}",
config.self_ref.protocol,
config.self_ref.domain,
post.id()
))
.rel("alternate".to_owned())
.mime_type(Some("text/html".to_owned()))
.build()
])
.author(atom::PersonBuilder::default()
.name(post.author().to_owned())
.build())
.build()
})
.collect::<Vec<atom::Entry>>();
let updated = guard.last_updated()
.unwrap_or_else(unix_epoch);
(atom_entries, updated)
};
Atom(atom::FeedBuilder::default()
.id(format!("urn:uuid:{}", *config.namespace_uuid))
.title(config.atom.title.clone())
.updated(updated)
.links(vec![
atom::LinkBuilder::default()
.href(format!(
"{}://{}/atom.xml",
config.self_ref.protocol,
config.self_ref.domain
))
.rel("self".to_owned())
.build(),
atom::LinkBuilder::default()
.href(format!(
"{}://{}/articles/",
config.self_ref.protocol,
config.self_ref.domain
))
.rel("alternate".to_owned())
.mime_type(Some("text/html".to_owned()))
.build()
])
.entries(atom_entries)
.build()
.to_string()
.into())
}
+1 -1
View File
@@ -43,7 +43,7 @@ pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> Html {
ul {
@for post in posts.read().await.iter_by_created().rev().take(5) {
li {
a href={"/articles/" (post.id_str())} { (post.title()) }
a href={"/articles/" (post.id())} { (post.title()) }
}
}
}
+1
View File
@@ -1,3 +1,4 @@
mod atom;
mod contact;
mod index;
mod post;
+1 -1
View File
@@ -23,7 +23,7 @@ pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> Html {
ul {
@for post in posts.read().await.iter_by_created().rev() {
li {
a href={"/articles/" (post.id_str())} { (post.title()) }
a href={"/articles/" (post.id())} { (post.title()) }
span class="quiet" {
" — " (post.created().format("%Y/%m/%d"))
}
+35 -19
View File
@@ -6,37 +6,53 @@ use axum::{
};
use super::response::Rss;
use crate::{posts_store::ConcurrentPostsStore, Config};
use crate::{
Config,
posts_store::ConcurrentPostsStore,
time::unix_epoch,
};
pub async fn handle(
Extension(config): Extension<Arc<Config>>,
Extension(posts): Extension<ConcurrentPostsStore>,
) -> Rss<Bytes> {
let rss_items = posts.read()
.await
.iter_by_created()
.take(config.rss.num_posts)
.map(|post| {
rss::ItemBuilder::default()
.title(Some(post.title().to_owned()))
.link(Some(format!(
"{}://{}/articles/{}",
config.rss.protocol,
config.rss.domain,
post.id()
)))
.pub_date(Some(post.created().to_rfc2822()))
.build()
})
.collect::<Vec<rss::Item>>();
let (rss_items, updated) = {
let guard = posts.read().await;
let rss_items = guard.iter_by_created()
.take(config.rss.num_posts)
.map(|post| {
rss::ItemBuilder::default()
.title(Some(post.title().to_owned()))
.guid(Some(rss::GuidBuilder::default()
.value(post.uuid().to_string())
.permalink(false)
.build()))
.link(Some(format!(
"{}://{}/articles/{}",
config.self_ref.protocol,
config.self_ref.domain,
post.id()
)))
.pub_date(Some(post.created().to_rfc2822()))
.build()
})
.collect::<Vec<rss::Item>>();
let updated = guard.last_updated()
.unwrap_or_else(unix_epoch);
(rss_items, updated)
};
Rss(rss::ChannelBuilder::default()
.title(config.rss.title.clone())
.link(format!(
"{}://{}",
config.rss.protocol, config.rss.domain
config.self_ref.protocol, config.self_ref.domain
))
.ttl(Some(config.rss.ttl.to_string()))
.last_build_date(Some(updated.to_rfc2822()))
.items(rss_items)
.build()
.to_string()
+4 -2
View File
@@ -16,6 +16,7 @@ use crate::{
posts_store::ConcurrentPostsStore
};
use super::{
atom,
contact,
index,
post,
@@ -26,13 +27,14 @@ use super::{
};
pub fn service(
config: Config,
config: Arc<Config>,
posts_store: ConcurrentPostsStore,
) -> Router
{
Router::new()
.route("/", get(index::handle))
.route("/rss.xml", get(rss::handle))
.route("/atom.xml", get(atom::handle))
.route("/contact", get(contact::handle))
.route("/articles", get(posts_list::handle))
.route("/articles/:post_id", get(post::handle))
@@ -40,7 +42,7 @@ pub fn service(
.fallback(handle_fallback.into_service())
.layer(ConcurrencyLimitLayer::new(config.concurrency_limit))
.layer(TraceLayer::new_for_http())
.layer(Extension(Arc::new(config)))
.layer(Extension(config))
.layer(Extension(posts_store))
}