diff options
| author | Christine Dodrill <me@christine.website> | 2021-01-14 22:36:34 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-14 22:36:34 -0500 |
| commit | d2455aa1c1bfc599a07966a7d717c1380d41bbc0 (patch) | |
| tree | c2b206aa41cd6f0e13d61b5455861f09ab5d1304 /src | |
| parent | a359f54a91f4aeb914c69f59a02afabccd72450e (diff) | |
| download | xesite-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.rs | 2 | ||||
| -rw-r--r-- | src/handlers/feeds.rs | 39 | ||||
| -rw-r--r-- | src/main.rs | 57 | ||||
| -rw-r--r-- | src/post/frontmatter.rs | 7 | ||||
| -rw-r--r-- | src/post/mod.rs | 1 |
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()) |
