aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2021-01-14 22:36:34 -0500
committerGitHub <noreply@github.com>2021-01-14 22:36:34 -0500
commitd2455aa1c1bfc599a07966a7d717c1380d41bbc0 (patch)
treec2b206aa41cd6f0e13d61b5455861f09ab5d1304 /src
parenta359f54a91f4aeb914c69f59a02afabccd72450e (diff)
downloadxesite-d2455aa1c1bfc599a07966a7d717c1380d41bbc0.tar.xz
xesite-d2455aa1c1bfc599a07966a7d717c1380d41bbc0.zip
Cache better (#296)
* Many improvements around bandwidth use - Use ETags for RSS/Atom feeds - Use cache-control headers - Update to rust nightly (for rust-analyzer and faster builds) - Limit feeds to the last 20 posts: https://twitter.com/theprincessxena/status/1349891678857998339 - Use if-none-match to limit bandwidth further Also does this: - bump go_vanity to 0.3.0 and lets users customize the branch name - fix formatting on jsonfeed - remove last vestige of kubernetes/docker support Signed-off-by: Christine Dodrill <me@christine.website> * expire cache quicker for dynamic pages Signed-off-by: Christine Dodrill <me@christine.website> * add rss ttl Signed-off-by: Christine Dodrill <me@christine.website> * add blogpost Signed-off-by: Christine Dodrill <me@christine.website>
Diffstat (limited to 'src')
-rw-r--r--src/app/mod.rs2
-rw-r--r--src/handlers/feeds.rs39
-rw-r--r--src/main.rs57
-rw-r--r--src/post/frontmatter.rs7
-rw-r--r--src/post/mod.rs1
5 files changed, 91 insertions, 15 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 7cb0044..e763792 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -86,6 +86,8 @@ pub async fn init(cfg: PathBuf) -> Result<State> {
everything.sort();
everything.reverse();
+ let everything: Vec<Post> = everything.into_iter().take(20).collect();
+
let mut jfb = jsonfeed::Feed::builder()
.title("Christine Dodrill's Blog")
.description("My blog posts and rants about various technology things.")
diff --git a/src/handlers/feeds.rs b/src/handlers/feeds.rs
index 2022393..5b5987d 100644
--- a/src/handlers/feeds.rs
+++ b/src/handlers/feeds.rs
@@ -11,10 +11,11 @@ lazy_static! {
&["kind"]
)
.unwrap();
+ pub static ref ETAG: String = format!(r#"W/"{}""#, uuid::Uuid::new_v4().to_simple());
}
#[instrument(skip(state))]
-pub async fn jsonfeed(state: Arc<State>) -> Result<impl Reply, Rejection> {
+pub async fn jsonfeed(state: Arc<State>, since: Option<String>) -> Result<impl Reply, Rejection> {
HIT_COUNTER.with_label_values(&["json"]).inc();
let state = state.clone();
Ok(warp::reply::json(&state.jf))
@@ -29,7 +30,22 @@ pub enum RenderError {
impl warp::reject::Reject for RenderError {}
#[instrument(skip(state))]
-pub async fn atom(state: Arc<State>) -> Result<impl Reply, Rejection> {
+pub async fn atom(state: Arc<State>, since: Option<String>) -> Result<impl Reply, Rejection> {
+ if let Some(etag) = since {
+ if etag == ETAG.clone() {
+ return Response::builder()
+ .status(304)
+ .header("Content-Type", "text/plain")
+ .body(
+ "You already have the newest version of this feed."
+ .to_string()
+ .into_bytes(),
+ )
+ .map_err(RenderError::Build)
+ .map_err(warp::reject::custom);
+ }
+ }
+
HIT_COUNTER.with_label_values(&["atom"]).inc();
let state = state.clone();
let mut buf = Vec::new();
@@ -39,13 +55,29 @@ pub async fn atom(state: Arc<State>) -> Result<impl Reply, Rejection> {
Response::builder()
.status(200)
.header("Content-Type", "application/atom+xml")
+ .header("ETag", ETAG.clone())
.body(buf)
.map_err(RenderError::Build)
.map_err(warp::reject::custom)
}
#[instrument(skip(state))]
-pub async fn rss(state: Arc<State>) -> Result<impl Reply, Rejection> {
+pub async fn rss(state: Arc<State>, since: Option<String>) -> Result<impl Reply, Rejection> {
+ if let Some(etag) = since {
+ if etag == ETAG.clone() {
+ return Response::builder()
+ .status(304)
+ .header("Content-Type", "text/plain")
+ .body(
+ "You already have the newest version of this feed."
+ .to_string()
+ .into_bytes(),
+ )
+ .map_err(RenderError::Build)
+ .map_err(warp::reject::custom);
+ }
+ }
+
HIT_COUNTER.with_label_values(&["rss"]).inc();
let state = state.clone();
let mut buf = Vec::new();
@@ -55,6 +87,7 @@ pub async fn rss(state: Arc<State>) -> Result<impl Reply, Rejection> {
Response::builder()
.status(200)
.header("Content-Type", "application/rss+xml")
+ .header("ETag", ETAG.clone())
.body(buf)
.map_err(RenderError::Build)
.map_err(warp::reject::custom)
diff --git a/src/main.rs b/src/main.rs
index c05ac49..285bb93 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -113,20 +113,39 @@ async fn main() -> Result<()> {
.and(with_state(state.clone()))
.and_then(handlers::patrons);
- let files = warp::path("static").and(warp::fs::dir("./static"));
- let css = warp::path("css").and(warp::fs::dir("./css"));
+ let files = warp::path("static")
+ .and(warp::fs::dir("./static"))
+ .map(|reply| {
+ warp::reply::with_header(
+ reply,
+ "Cache-Control",
+ "public, max-age=86400, stale-if-error=60",
+ )
+ });
+
+ let css = warp::path("css").and(warp::fs::dir("./css")).map(|reply| {
+ warp::reply::with_header(
+ reply,
+ "Cache-Control",
+ "public, max-age=86400, stale-if-error=60",
+ )
+ });
+
let sw = warp::path("sw.js").and(warp::fs::file("./static/js/sw.js"));
let robots = warp::path("robots.txt").and(warp::fs::file("./static/robots.txt"));
let favicon = warp::path("favicon.ico").and(warp::fs::file("./static/favicon/favicon.ico"));
let jsonfeed = warp::path("blog.json")
.and(with_state(state.clone()))
+ .and(warp::header::optional("if-none-match"))
.and_then(handlers::feeds::jsonfeed);
let atom = warp::path("blog.atom")
.and(with_state(state.clone()))
+ .and(warp::header::optional("if-none-match"))
.and_then(handlers::feeds::atom);
let rss = warp::path("blog.rss")
.and(with_state(state.clone()))
+ .and(warp::header::optional("if-none-match"))
.and_then(handlers::feeds::rss);
let sitemap = warp::path("sitemap.xml")
.and(with_state(state.clone()))
@@ -135,6 +154,7 @@ async fn main() -> Result<()> {
let go_vanity_jsonfeed = warp::path("jsonfeed")
.and(warp::any().map(move || "christine.website/jsonfeed"))
.and(warp::any().map(move || "https://tulpa.dev/Xe/jsonfeed"))
+ .and(warp::any().map(move || "master"))
.and_then(go_vanity::gitea);
let metrics_endpoint = warp::path("metrics").and(warp::path::end()).map(move || {
@@ -149,14 +169,37 @@ async fn main() -> Result<()> {
.unwrap()
});
- let site = index
- .or(contact.or(feeds).or(resume.or(signalboost)).or(patrons))
- .or(blog_index.or(series.or(series_view).or(post_view)))
+ let static_pages = index
+ .or(feeds)
+ .or(resume.or(signalboost))
+ .or(patrons)
+ .or(jsonfeed.or(atom.or(sitemap)).or(rss))
+ .or(favicon.or(robots).or(sw))
+ .or(contact)
+ .map(|reply| {
+ warp::reply::with_header(
+ reply,
+ "Cache-Control",
+ "public, max-age=86400, stale-if-error=60",
+ )
+ });
+
+ let dynamic_pages = blog_index
+ .or(series.or(series_view).or(post_view))
.or(gallery_index.or(gallery_post_view))
.or(talk_index.or(talk_post_view))
- .or(jsonfeed.or(atom).or(rss.or(sitemap)))
- .or(files.or(css).or(favicon).or(sw.or(robots)))
+ .map(|reply| {
+ warp::reply::with_header(
+ reply,
+ "Cache-Control",
+ "public, max-age=600, stale-if-error=60",
+ )
+ });
+
+ let site = static_pages
+ .or(dynamic_pages)
.or(healthcheck.or(metrics_endpoint).or(go_vanity_jsonfeed))
+ .or(files.or(css))
.map(|reply| {
warp::reply::with_header(
reply,
diff --git a/src/post/frontmatter.rs b/src/post/frontmatter.rs
index 615f2c5..f2c1587 100644
--- a/src/post/frontmatter.rs
+++ b/src/post/frontmatter.rs
@@ -1,7 +1,6 @@
/// This code was borrowed from @fasterthanlime.
-
-use color_eyre::eyre::{Result};
-use serde::{Serialize, Deserialize};
+use color_eyre::eyre::Result;
+use serde::{Deserialize, Serialize};
#[derive(Eq, PartialEq, Deserialize, Default, Debug, Serialize, Clone)]
pub struct Data {
@@ -81,7 +80,7 @@ impl Data {
};
}
}
- _ => panic!("Expected newline, got {:?}",),
+ _ => panic!("Expected newline, got {:?}", ch),
},
State::ReadingFrontMatter { buf, line_start } => match ch {
'-' if *line_start => {
diff --git a/src/post/mod.rs b/src/post/mod.rs
index 79affbc..eb8ee54 100644
--- a/src/post/mod.rs
+++ b/src/post/mod.rs
@@ -20,7 +20,6 @@ impl Into<jsonfeed::Item> for Post {
let mut result = jsonfeed::Item::builder()
.title(self.front_matter.title)
.content_html(self.body_html)
- .content_text(self.body)
.id(format!("https://christine.website/{}", self.link))
.url(format!("https://christine.website/{}", self.link))
.date_published(self.date.to_rfc3339())