aboutsummaryrefslogtreecommitdiff
path: root/lib
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 /lib
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 'lib')
-rw-r--r--lib/go_vanity/Cargo.toml2
-rw-r--r--lib/go_vanity/src/lib.rs10
-rw-r--r--lib/go_vanity/templates/gitea.rs.html4
-rw-r--r--lib/go_vanity/templates/github.rs.html4
-rw-r--r--lib/jsonfeed/src/builder.rs11
-rw-r--r--lib/jsonfeed/src/errors.rs3
-rw-r--r--lib/jsonfeed/src/feed.rs36
-rw-r--r--lib/jsonfeed/src/item.rs116
-rw-r--r--lib/jsonfeed/src/lib.rs66
9 files changed, 122 insertions, 130 deletions
diff --git a/lib/go_vanity/Cargo.toml b/lib/go_vanity/Cargo.toml
index 90fa4f2..f4e5432 100644
--- a/lib/go_vanity/Cargo.toml
+++ b/lib/go_vanity/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "go_vanity"
-version = "0.1.0"
+version = "0.2.0"
authors = ["Christine Dodrill <me@christine.website>"]
edition = "2018"
build = "src/build.rs"
diff --git a/lib/go_vanity/src/lib.rs b/lib/go_vanity/src/lib.rs
index e4a11e2..756c555 100644
--- a/lib/go_vanity/src/lib.rs
+++ b/lib/go_vanity/src/lib.rs
@@ -1,12 +1,12 @@
+use crate::templates::RenderRucte;
use warp::{http::Response, Rejection, Reply};
-use crate::templates::{RenderRucte};
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
-pub async fn gitea(pkg_name: &str, git_repo: &str) -> Result<impl Reply, Rejection> {
- Response::builder().html(|o| templates::gitea_html(o, pkg_name, git_repo))
+pub async fn gitea(pkg_name: &str, git_repo: &str, branch: &str) -> Result<impl Reply, Rejection> {
+ Response::builder().html(|o| templates::gitea_html(o, pkg_name, git_repo, branch))
}
-pub async fn github(pkg_name: &str, git_repo: &str) -> Result<impl Reply, Rejection> {
- Response::builder().html(|o| templates::github_html(o, pkg_name, git_repo))
+pub async fn github(pkg_name: &str, git_repo: &str, branch: &str) -> Result<impl Reply, Rejection> {
+ Response::builder().html(|o| templates::github_html(o, pkg_name, git_repo, branch))
}
diff --git a/lib/go_vanity/templates/gitea.rs.html b/lib/go_vanity/templates/gitea.rs.html
index b20985b..f062d91 100644
--- a/lib/go_vanity/templates/gitea.rs.html
+++ b/lib/go_vanity/templates/gitea.rs.html
@@ -1,11 +1,11 @@
-@(pkg_name: &str, git_repo: &str)
+@(pkg_name: &str, git_repo: &str, branch: &str)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="@pkg_name git @git_repo">
- <meta name="go-source" content="@pkg_name @git_repo @git_repo/src/master@{/dir@} @git_repo/src/master@{/dir@}/@{file@}#L@{line@}">
+ <meta name="go-source" content="@pkg_name @git_repo @git_repo/src/@branch@{/dir@} @git_repo/src/@branch@{/dir@}/@{file@}#L@{line@}">
<meta http-equiv="refresh" content="0; url=https://godoc.org/@pkg_name">
</head>
<body>
diff --git a/lib/go_vanity/templates/github.rs.html b/lib/go_vanity/templates/github.rs.html
index 61f42e5..9782b1c 100644
--- a/lib/go_vanity/templates/github.rs.html
+++ b/lib/go_vanity/templates/github.rs.html
@@ -1,11 +1,11 @@
-@(pkg_name: &str, git_repo: &str)
+@(pkg_name: &str, git_repo: &str, branch: &str)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="@pkg_name git @git_repo">
- <meta name="go-source" content="@pkg_name @git_repo @git_repo/tree/master@{/dir@} @git_repo/blob/master@{/dir@}/@{file@}#L@{line@}">
+ <meta name="go-source" content="@pkg_name @git_repo @git_repo/tree/@branch@{/dir@} @git_repo/blob/@branch@{/dir@}/@{file@}#L@{line@}">
<meta http-equiv="refresh" content="0; url=https://godoc.org/@pkg_name">
</head>
<body>
diff --git a/lib/jsonfeed/src/builder.rs b/lib/jsonfeed/src/builder.rs
index f17740f..640a280 100644
--- a/lib/jsonfeed/src/builder.rs
+++ b/lib/jsonfeed/src/builder.rs
@@ -1,7 +1,7 @@
use std::default::Default;
use errors::*;
-use feed::{Feed, Author, Attachment};
+use feed::{Attachment, Author, Feed};
use item::{Content, Item};
/// Feed Builder
@@ -160,7 +160,7 @@ impl ItemBuilder {
match self.content {
Some(Content::Text(t)) => {
self.content = Some(Content::Both(i.into(), t));
- },
+ }
_ => {
self.content = Some(Content::Html(i.into()));
}
@@ -172,10 +172,10 @@ impl ItemBuilder {
match self.content {
Some(Content::Html(s)) => {
self.content = Some(Content::Both(s, i.into()));
- },
+ }
_ => {
self.content = Some(Content::Text(i.into()));
- },
+ }
}
self
}
@@ -197,8 +197,7 @@ impl ItemBuilder {
date_modified: self.date_modified,
author: self.author,
tags: self.tags,
- attachments: self.attachments
+ attachments: self.attachments,
})
}
}
-
diff --git a/lib/jsonfeed/src/errors.rs b/lib/jsonfeed/src/errors.rs
index 936b7ec..b94779c 100644
--- a/lib/jsonfeed/src/errors.rs
+++ b/lib/jsonfeed/src/errors.rs
@@ -1,7 +1,6 @@
use serde_json;
-error_chain!{
+error_chain! {
foreign_links {
Serde(serde_json::Error);
}
}
-
diff --git a/lib/jsonfeed/src/feed.rs b/lib/jsonfeed/src/feed.rs
index 8b5b5ce..320feb6 100644
--- a/lib/jsonfeed/src/feed.rs
+++ b/lib/jsonfeed/src/feed.rs
@@ -1,7 +1,7 @@
use std::default::Default;
-use item::Item;
use builder::Builder;
+use item::Item;
const VERSION_1: &'static str = "https://jsonfeed.org/version/1";
@@ -145,9 +145,9 @@ pub struct Hub {
#[cfg(test)]
mod tests {
+ use super::*;
use serde_json;
use std::default::Default;
- use super::*;
#[test]
fn serialize_feed() {
@@ -168,18 +168,16 @@ mod tests {
#[test]
fn deserialize_feed() {
- let json = r#"{"version":"https://jsonfeed.org/version/1","title":"some title","items":[]}"#;
+ let json =
+ r#"{"version":"https://jsonfeed.org/version/1","title":"some title","items":[]}"#;
let feed: Feed = serde_json::from_str(&json).unwrap();
let expected = Feed {
version: "https://jsonfeed.org/version/1".to_string(),
- title: "some title".to_string(),
- items: vec![],
- ..Default::default()
+ title: "some title".to_string(),
+ items: vec![],
+ ..Default::default()
};
- assert_eq!(
- feed,
- expected
- );
+ assert_eq!(feed, expected);
}
#[test]
@@ -208,10 +206,7 @@ mod tests {
size_in_bytes: Some(1),
duration_in_seconds: Some(1),
};
- assert_eq!(
- attachment,
- expected
- );
+ assert_eq!(attachment, expected);
}
#[test]
@@ -229,17 +224,15 @@ mod tests {
#[test]
fn deserialize_author() {
- let json = r#"{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"#;
+ let json =
+ r#"{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"#;
let author: Author = serde_json::from_str(&json).unwrap();
let expected = Author {
name: Some("bob jones".to_string()),
url: Some("http://example.com".to_string()),
avatar: Some("http://img.com/blah".to_string()),
};
- assert_eq!(
- author,
- expected
- );
+ assert_eq!(author, expected);
}
#[test]
@@ -262,10 +255,7 @@ mod tests {
type_: "some-type".to_string(),
url: "http://example.com".to_string(),
};
- assert_eq!(
- hub,
- expected
- );
+ assert_eq!(hub, expected);
}
#[test]
diff --git a/lib/jsonfeed/src/item.rs b/lib/jsonfeed/src/item.rs
index 605525b..0f7d6ab 100644
--- a/lib/jsonfeed/src/item.rs
+++ b/lib/jsonfeed/src/item.rs
@@ -1,11 +1,11 @@
-use std::fmt;
use std::default::Default;
+use std::fmt;
-use feed::{Author, Attachment};
use builder::ItemBuilder;
+use feed::{Attachment, Author};
-use serde::ser::{Serialize, Serializer, SerializeStruct};
-use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};
+use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
+use serde::ser::{Serialize, SerializeStruct, Serializer};
/// Represents the `content_html` and `content_text` attributes of an item
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
@@ -61,7 +61,8 @@ impl Default for Item {
impl Serialize for Item {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where S: Serializer
+ where
+ S: Serializer,
{
let mut state = serializer.serialize_struct("Item", 14)?;
state.serialize_field("id", &self.id)?;
@@ -78,15 +79,15 @@ impl Serialize for Item {
Content::Html(ref s) => {
state.serialize_field("content_html", s)?;
state.serialize_field("content_text", &None::<Option<&str>>)?;
- },
+ }
Content::Text(ref s) => {
state.serialize_field("content_html", &None::<Option<&str>>)?;
state.serialize_field("content_text", s)?;
- },
+ }
Content::Both(ref s, ref t) => {
state.serialize_field("content_html", s)?;
state.serialize_field("content_text", t)?;
- },
+ }
};
if self.summary.is_some() {
state.serialize_field("summary", &self.summary)?;
@@ -117,8 +118,9 @@ impl Serialize for Item {
}
impl<'de> Deserialize<'de> for Item {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where D: Deserializer<'de>
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
{
enum Field {
Id,
@@ -135,11 +137,12 @@ impl<'de> Deserialize<'de> for Item {
Author,
Tags,
Attachments,
- };
+ }
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where D: Deserializer<'de>
+ where
+ D: Deserializer<'de>,
{
struct FieldVisitor;
@@ -151,7 +154,8 @@ impl<'de> Deserialize<'de> for Item {
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
- where E: de::Error
+ where
+ E: de::Error,
{
match value {
"id" => Ok(Field::Id),
@@ -186,7 +190,8 @@ impl<'de> Deserialize<'de> for Item {
}
fn visit_map<V>(self, mut map: V) -> Result<Item, V::Error>
- where V: MapAccess<'de>
+ where
+ V: MapAccess<'de>,
{
let mut id = None;
let mut url = None;
@@ -210,99 +215,93 @@ impl<'de> Deserialize<'de> for Item {
return Err(de::Error::duplicate_field("id"));
}
id = Some(map.next_value()?);
- },
+ }
Field::Url => {
if url.is_some() {
return Err(de::Error::duplicate_field("url"));
}
url = map.next_value()?;
- },
+ }
Field::ExternalUrl => {
if external_url.is_some() {
return Err(de::Error::duplicate_field("external_url"));
}
external_url = map.next_value()?;
- },
+ }
Field::Title => {
if title.is_some() {
return Err(de::Error::duplicate_field("title"));
}
title = map.next_value()?;
- },
+ }
Field::ContentHtml => {
if content_html.is_some() {
return Err(de::Error::duplicate_field("content_html"));
}
content_html = map.next_value()?;
- },
+ }
Field::ContentText => {
if content_text.is_some() {
return Err(de::Error::duplicate_field("content_text"));
}
content_text = map.next_value()?;
- },
+ }
Field::Summary => {
if summary.is_some() {
return Err(de::Error::duplicate_field("summary"));
}
summary = map.next_value()?;
- },
+ }
Field::Image => {
if image.is_some() {
return Err(de::Error::duplicate_field("image"));
}
image = map.next_value()?;
- },
+ }
Field::BannerImage => {
if banner_image.is_some() {
return Err(de::Error::duplicate_field("banner_image"));
}
banner_image = map.next_value()?;
- },
+ }
Field::DatePublished => {
if date_published.is_some() {
return Err(de::Error::duplicate_field("date_published"));
}
date_published = map.next_value()?;
- },
+ }
Field::DateModified => {
if date_modified.is_some() {
return Err(de::Error::duplicate_field("date_modified"));
}
date_modified = map.next_value()?;
- },
+ }
Field::Author => {
if author.is_some() {
return Err(de::Error::duplicate_field("author"));
}
author = map.next_value()?;
- },
+ }
Field::Tags => {
if tags.is_some() {
return Err(de::Error::duplicate_field("tags"));
}
tags = map.next_value()?;
- },
+ }
Field::Attachments => {
if attachments.is_some() {
return Err(de::Error::duplicate_field("attachments"));
}
attachments = map.next_value()?;
- },
+ }
}
}
let id = id.ok_or_else(|| de::Error::missing_field("id"))?;
let content = match (content_html, content_text) {
- (Some(s), Some(t)) => {
- Content::Both(s.to_string(), t.to_string())
- },
- (Some(s), _) => {
- Content::Html(s.to_string())
- },
- (_, Some(t)) => {
- Content::Text(t.to_string())
- },
+ (Some(s), Some(t)) => Content::Both(s.to_string(), t.to_string()),
+ (Some(s), _) => Content::Html(s.to_string()),
+ (_, Some(t)) => Content::Text(t.to_string()),
_ => return Err(de::Error::missing_field("content_html or content_text")),
};
@@ -363,7 +362,12 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
@@ -387,7 +391,12 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
@@ -411,7 +420,12 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
@@ -437,7 +451,12 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
@@ -460,7 +479,12 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
@@ -483,11 +507,15 @@ mod tests {
banner_image: Some("http://img.com/blah".into()),
date_published: Some("2017-01-01 10:00:00".into()),
date_modified: Some("2017-01-01 10:00:00".into()),
- author: Some(Author::new().name("bob jones").url("http://example.com").avatar("http://img.com/blah")),
+ author: Some(
+ Author::new()
+ .name("bob jones")
+ .url("http://example.com")
+ .avatar("http://img.com/blah"),
+ ),
tags: Some(vec!["json".into(), "feed".into()]),
attachments: Some(vec![]),
};
assert_eq!(item, expected);
}
}
-
diff --git a/lib/jsonfeed/src/lib.rs b/lib/jsonfeed/src/lib.rs
index bc1d94e..812083e 100644
--- a/lib/jsonfeed/src/lib.rs
+++ b/lib/jsonfeed/src/lib.rs
@@ -2,7 +2,7 @@
//! instead of XML
//!
//! This crate can serialize and deserialize between JSON Feed strings
-//! and Rust data structures. It also allows for programmatically building
+//! and Rust data structures. It also allows for programmatically building
//! a JSON Feed
//!
//! Example:
@@ -40,18 +40,20 @@
//! ```
extern crate serde;
-#[macro_use] extern crate error_chain;
-#[macro_use] extern crate serde_derive;
+#[macro_use]
+extern crate error_chain;
+#[macro_use]
+extern crate serde_derive;
extern crate serde_json;
+mod builder;
mod errors;
-mod item;
mod feed;
-mod builder;
+mod item;
pub use errors::*;
+pub use feed::{Attachment, Author, Feed};
pub use item::*;
-pub use feed::{Feed, Author, Attachment};
use std::io::Write;
@@ -116,14 +118,16 @@ pub fn to_vec_pretty(value: &Feed) -> Result<Vec<u8>> {
/// Serialize a Feed to JSON and output to an IO stream
pub fn to_writer<W>(writer: W, value: &Feed) -> Result<()>
- where W: Write
+where
+ W: Write,
{
Ok(serde_json::to_writer(writer, value)?)
}
/// Serialize a Feed to pretty-printed JSON and output to an IO stream
pub fn to_writer_pretty<W>(writer: W, value: &Feed) -> Result<()>
- where W: Write
+where
+ W: Write,
{
Ok(serde_json::to_writer_pretty(writer, value)?)
}
@@ -137,10 +141,7 @@ mod tests {
fn from_str() {
let feed = r#"{"version": "https://jsonfeed.org/version/1","title":"","items":[]}"#;
let expected = Feed::default();
- assert_eq!(
- super::from_str(&feed).unwrap(),
- expected
- );
+ assert_eq!(super::from_str(&feed).unwrap(), expected);
}
#[test]
fn from_reader() {
@@ -148,39 +149,27 @@ mod tests {
let feed = feed.as_bytes();
let feed = Cursor::new(feed);
let expected = Feed::default();
- assert_eq!(
- super::from_reader(feed).unwrap(),
- expected
- );
+ assert_eq!(super::from_reader(feed).unwrap(), expected);
}
#[test]
fn from_slice() {
let feed = r#"{"version": "https://jsonfeed.org/version/1","title":"","items":[]}"#;
let feed = feed.as_bytes();
let expected = Feed::default();
- assert_eq!(
- super::from_slice(&feed).unwrap(),
- expected
- );
+ assert_eq!(super::from_slice(&feed).unwrap(), expected);
}
#[test]
fn from_value() {
let feed = r#"{"version": "https://jsonfeed.org/version/1","title":"","items":[]}"#;
let feed: serde_json::Value = serde_json::from_str(&feed).unwrap();
let expected = Feed::default();
- assert_eq!(
- super::from_value(feed).unwrap(),
- expected
- );
+ assert_eq!(super::from_value(feed).unwrap(), expected);
}
#[test]
fn to_string() {
let feed = Feed::default();
let expected = r#"{"version":"https://jsonfeed.org/version/1","title":"","items":[]}"#;
- assert_eq!(
- super::to_string(&feed).unwrap(),
- expected
- );
+ assert_eq!(super::to_string(&feed).unwrap(), expected);
}
#[test]
fn to_string_pretty() {
@@ -190,28 +179,19 @@ mod tests {
"title": "",
"items": []
}"#;
- assert_eq!(
- super::to_string_pretty(&feed).unwrap(),
- expected
- );
+ assert_eq!(super::to_string_pretty(&feed).unwrap(), expected);
}
#[test]
fn to_value() {
let feed = r#"{"version":"https://jsonfeed.org/version/1","title":"","items":[]}"#;
let expected: serde_json::Value = serde_json::from_str(&feed).unwrap();
- assert_eq!(
- super::to_value(Feed::default()).unwrap(),
- expected
- );
+ assert_eq!(super::to_value(Feed::default()).unwrap(), expected);
}
#[test]
fn to_vec() {
let feed = r#"{"version":"https://jsonfeed.org/version/1","title":"","items":[]}"#;
let expected = feed.as_bytes();
- assert_eq!(
- super::to_vec(&Feed::default()).unwrap(),
- expected
- );
+ assert_eq!(super::to_vec(&Feed::default()).unwrap(), expected);
}
#[test]
fn to_vec_pretty() {
@@ -221,10 +201,7 @@ mod tests {
"items": []
}"#;
let expected = feed.as_bytes();
- assert_eq!(
- super::to_vec_pretty(&Feed::default()).unwrap(),
- expected
- );
+ assert_eq!(super::to_vec_pretty(&Feed::default()).unwrap(), expected);
}
#[test]
fn to_writer() {
@@ -249,4 +226,3 @@ mod tests {
assert_eq!(result, feed);
}
}
-