implement an Atom RSS feed

This commit is contained in:
2023-11-29 13:30:51 -05:00
parent 5e5be16ee0
commit 9d497f0aaf
3 changed files with 58 additions and 7 deletions

2
Cargo.lock generated
View File

@@ -184,7 +184,9 @@ version = "0.1.0"
dependencies = [
"atom_syndication",
"axum",
"bytes",
"error-stack",
"mime",
"redb",
"serde",
"thiserror",

View File

@@ -4,9 +4,11 @@ version = "0.1.0"
edition = "2021"
[dependencies]
atom_syndication = "0.12.2"
axum = { version = "0.7.1", default-features = false, features = ["json", "tokio", "http2"] }
atom_syndication = { version = "0.12.2" }
axum = { version = "0.7.1", default-features = false, features = ["json", "tokio", "http2", "http1"] }
bytes = "1.5.0"
error-stack = "0.4.1"
mime = "0.3.17"
redb = "1.4.0"
serde = { version = "1.0.193", features = ["derive"] }
thiserror = "1.0.50"

View File

@@ -1,13 +1,60 @@
use axum::{extract::State, response::IntoResponse, Router};
use atom_syndication::{Feed, FeedBuilder};
use axum::{
extract::State,
http::{header, HeaderValue, StatusCode},
response::{IntoResponse, Response},
Router,
};
use bytes::{BufMut, BytesMut};
use crate::AppState;
#[tracing::instrument(level = "trace")]
async fn get(state: State<AppState>) -> impl IntoResponse {
"Hi, getter!"
#[derive(Debug)]
struct Atom(Feed);
impl IntoResponse for Atom {
fn into_response(self) -> Response {
let buf = BytesMut::with_capacity(128).writer();
match self.0.write_to(buf) {
Ok(buf) => (
[(
header::CONTENT_TYPE,
HeaderValue::from_static("application/xml"),
)],
buf.into_inner().freeze(),
)
.into_response(),
Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR,
[(
header::CONTENT_TYPE,
HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
)],
err.to_string(),
)
.into_response(),
}
}
}
#[tracing::instrument(level = "trace")]
impl From<Feed> for Atom {
fn from(inner: Feed) -> Self {
Self(inner)
}
}
#[tracing::instrument(level = "trace", ret)]
async fn get(state: State<AppState>) -> impl IntoResponse {
let feed = FeedBuilder::default()
.title("My Notifications")
.subtitle(Some("Originally from my smartphone".into()))
.icon(Some("https://katniss.top/favicon.png".into()))
.build();
Atom(feed)
}
#[tracing::instrument(level = "trace", ret)]
async fn post(state: State<AppState>) -> impl IntoResponse {
"Hi, poster!"
}