aboutsummaryrefslogtreecommitdiff
path: root/src/handlers/feeds.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/handlers/feeds.rs')
-rw-r--r--src/handlers/feeds.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/handlers/feeds.rs b/src/handlers/feeds.rs
new file mode 100644
index 0000000..7d7db32
--- /dev/null
+++ b/src/handlers/feeds.rs
@@ -0,0 +1,73 @@
+use crate::app::State;
+use lazy_static::lazy_static;
+use prometheus::{opts, register_int_counter_vec, IntCounterVec};
+use std::sync::Arc;
+use warp::{http::Response, Rejection, Reply};
+
+lazy_static! {
+ static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!(
+ opts!("feed_hits", "Number of hits to various feeds"),
+ &["kind"]
+ )
+ .unwrap();
+}
+
+pub async fn jsonfeed(state: Arc<State>) -> Result<impl Reply, Rejection> {
+ HIT_COUNTER.with_label_values(&["json"]).inc();
+ let state = state.clone();
+ Ok(warp::reply::json(&state.jf))
+}
+
+#[derive(Debug)]
+pub enum RenderError {
+ WriteAtom(atom_syndication::Error),
+ WriteRss(rss::Error),
+ Build(warp::http::Error),
+}
+
+impl warp::reject::Reject for RenderError {}
+
+pub async fn atom(state: Arc<State>) -> Result<impl Reply, Rejection> {
+ HIT_COUNTER.with_label_values(&["atom"]).inc();
+ let state = state.clone();
+ let mut buf = Vec::new();
+ state
+ .af
+ .write_to(&mut buf)
+ .map_err(RenderError::WriteAtom)
+ .map_err(warp::reject::custom)?;
+ Response::builder()
+ .status(200)
+ .header("Content-Type", "application/atom+xml")
+ .body(buf)
+ .map_err(RenderError::Build)
+ .map_err(warp::reject::custom)
+}
+
+pub async fn rss(state: Arc<State>) -> Result<impl Reply, Rejection> {
+ HIT_COUNTER.with_label_values(&["rss"]).inc();
+ let state = state.clone();
+ let mut buf = Vec::new();
+ state
+ .rf
+ .write_to(&mut buf)
+ .map_err(RenderError::WriteRss)
+ .map_err(warp::reject::custom)?;
+ Response::builder()
+ .status(200)
+ .header("Content-Type", "application/rss+xml")
+ .body(buf)
+ .map_err(RenderError::Build)
+ .map_err(warp::reject::custom)
+}
+
+pub async fn sitemap(state: Arc<State>) -> Result<impl Reply, Rejection> {
+ HIT_COUNTER.with_label_values(&["sitemap"]).inc();
+ let state = state.clone();
+ Response::builder()
+ .status(200)
+ .header("Content-Type", "application/xml")
+ .body(state.sitemap.clone())
+ .map_err(RenderError::Build)
+ .map_err(warp::reject::custom)
+}