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 = [ dependencies = [
"atom_syndication", "atom_syndication",
"axum", "axum",
"bytes",
"error-stack", "error-stack",
"mime",
"redb", "redb",
"serde", "serde",
"thiserror", "thiserror",

View File

@@ -4,9 +4,11 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
atom_syndication = "0.12.2" atom_syndication = { version = "0.12.2" }
axum = { version = "0.7.1", default-features = false, features = ["json", "tokio", "http2"] } axum = { version = "0.7.1", default-features = false, features = ["json", "tokio", "http2", "http1"] }
bytes = "1.5.0"
error-stack = "0.4.1" error-stack = "0.4.1"
mime = "0.3.17"
redb = "1.4.0" redb = "1.4.0"
serde = { version = "1.0.193", features = ["derive"] } serde = { version = "1.0.193", features = ["derive"] }
thiserror = "1.0.50" 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; use crate::AppState;
#[tracing::instrument(level = "trace")] #[derive(Debug)]
async fn get(state: State<AppState>) -> impl IntoResponse { struct Atom(Feed);
"Hi, getter!"
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 { async fn post(state: State<AppState>) -> impl IntoResponse {
"Hi, poster!" "Hi, poster!"
} }