1
0
Fork 0

Compare commits

...

2 commits

Author SHA1 Message Date
Adrian Hedqvist 7f62395071 cargo fix 2023-04-10 00:47:29 +02:00
Adrian Hedqvist 5c64da7975 make use of the base_url in appstate 2023-04-10 00:46:58 +02:00
9 changed files with 204 additions and 81 deletions

144
Cargo.lock generated
View file

@ -353,9 +353,9 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cpufeatures"
@ -377,9 +377,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
version = "0.5.7"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
@ -514,13 +514,13 @@ dependencies = [
[[package]]
name = "errno"
version = "0.2.8"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
"windows-sys 0.48.0",
]
[[package]]
@ -674,9 +674,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
@ -856,9 +856,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.54"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d"
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@ -928,13 +928,13 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
dependencies = [
"hermit-abi 0.3.1",
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -979,9 +979,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.140"
version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libm"
@ -1078,7 +1078,7 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -1213,7 +1213,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -1360,9 +1360,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.55"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d0dd4be24fcdcfeaa12a432d588dc59bbad6cad3510c67e74a2b6b2fc950564"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
@ -1497,16 +1497,16 @@ checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
[[package]]
name = "rustix"
version = "0.36.11"
version = "0.36.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
checksum = "e0af200a3324fa5bcd922e84e9b55a298ea9f431a489f01961acdebc6e908f25"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -1794,7 +1794,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
"windows-sys 0.45.0",
]
[[package]]
@ -2119,9 +2119,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "uuid"
version = "1.3.0"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
dependencies = [
"getrandom",
]
@ -2285,11 +2285,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.46.0"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets",
"windows-targets 0.48.0",
]
[[package]]
@ -2298,7 +2298,16 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
@ -2307,13 +2316,28 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
@ -2322,42 +2346,84 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.4.1"
@ -2388,9 +2454,9 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "2.0.7+zstd.1.5.4"
version = "2.0.8+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5"
checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
dependencies = [
"cc",
"libc",

View file

@ -1,45 +1,64 @@
use color_eyre::Result;
use serde_derive::Serialize;
use tera::Tera;
use tracing::instrument;
use crate::{post::Post, tag::Tag};
use crate::{post::Post, tag::Tag, AppState};
#[derive(Serialize)]
struct FeedContext<'a> {
feed_url: &'a str,
base_url: &'a str,
last_updated: &'a str,
tag: Option<&'a Tag>,
posts: &'a [&'a Post],
}
#[instrument(skip(posts, tera))]
pub fn render_atom_feed(posts: &[&Post], tera: &Tera) -> Result<String> {
#[instrument(skip(state))]
pub fn render_atom_feed(state: &AppState) -> Result<String> {
let mut posts: Vec<_> = state.posts.values().filter(|p| p.is_published()).collect();
posts.sort_by_key(|p| &p.date);
posts.reverse();
posts.truncate(10);
let updated = posts.iter().map(|p| p.updated.or(p.date)).max().flatten();
let feed = FeedContext {
feed_url: "https://tollyx.net/atom.xml",
feed_url: &format!("{}/atom.xml", state.base_url),
base_url: &state.base_url,
last_updated: &updated.map_or_else(String::default, |d| d.to_rfc3339()),
tag: None,
posts,
posts: &posts,
};
let ctx = tera::Context::from_serialize(&feed)?;
Ok(tera.render("atom.xml", &ctx)?)
Ok(state.tera.render("atom.xml", &ctx)?)
}
#[instrument(skip(tag, posts, tera))]
pub fn render_atom_tag_feed(tag: &Tag, posts: &[&Post], tera: &Tera) -> Result<String> {
#[instrument(skip(tag, state))]
pub fn render_atom_tag_feed(tag: &Tag, state: &AppState) -> Result<String> {
let mut posts: Vec<_> = state
.posts
.values()
.filter(|p| p.is_published() && p.tags.contains(&tag.slug))
.collect();
posts.sort_by_key(|p| &p.date);
posts.reverse();
posts.truncate(10);
let updated = posts.iter().map(|p| p.updated.or(p.date)).max().flatten();
let slug = &tag.slug;
let feed = FeedContext {
feed_url: &format!("https://tollyx.net/tags/{slug}/atom.xml"),
feed_url: &format!("{}/tags/{}/atom.xml", state.base_url, slug),
base_url: &state.base_url,
last_updated: &updated.map_or_else(String::default, |d| d.to_rfc3339()),
tag: Some(tag),
posts,
posts: &posts,
};
let ctx = tera::Context::from_serialize(&feed)?;
Ok(tera.render("atom.xml", &ctx)?)
Ok(state.tera.render("atom.xml", &ctx)?)
}

View file

@ -92,6 +92,10 @@ pub async fn metrics_middleware<B>(request: Request<B>, next: Next<B>) -> Respon
HIT_COUNTER
.with_label_values(&[&path, &method, response.status().as_str()])
.inc();
} else if response.status() == StatusCode::NOT_FOUND {
HIT_COUNTER
.with_label_values(&["not found", &method, response.status().as_str()])
.inc();
}
response
@ -105,7 +109,11 @@ impl IntoResponse for WebsiteError {
(StatusCode::NOT_FOUND, ()).into_response()
}
WebsiteError::InternalError(e) => {
error!("internal error: {e}");
if let Some(s) = e.source() {
error!("internal error: {}: {}", e, s);
} else {
error!("internal error: {}", e);
}
(StatusCode::INTERNAL_SERVER_ERROR, ()).into_response()
}
}

View file

@ -60,6 +60,7 @@ pub async fn index(State(state): State<Arc<AppState>>) -> Result<Html<String>, W
let mut c = tera::Context::new();
c.insert("page", &ctx);
c.insert("posts", &posts);
c.insert("base_url", &state.base_url);
let res = state.tera.render("posts_index.html", &c)?;
@ -77,7 +78,7 @@ pub async fn view(
return Err(WebsiteError::NotFound);
}
let res = render_post(&state.tera, post).await?;
let res = render_post(&state, post).await?;
Ok(Html(res))
}
@ -92,7 +93,7 @@ pub async fn feed(State(state): State<Arc<AppState>>) -> Result<impl IntoRespons
Ok((
StatusCode::OK,
[(CONTENT_TYPE, "application/atom+xml")],
crate::feed::render_atom_feed(&posts, &state.tera)?,
crate::feed::render_atom_feed(&state)?,
))
}
@ -122,6 +123,7 @@ mod tests {
Post {
title: "test".into(),
slug: "test".into(),
tags: vec!["abc".into(), "def".into()],
date: Some(DateTime::parse_from_rfc3339("2023-03-26T13:04:01+02:00").unwrap()),
..Default::default()
},

View file

@ -87,7 +87,7 @@ pub async fn feed(
Ok((
StatusCode::OK,
[(CONTENT_TYPE, "application/atom+xml")],
crate::feed::render_atom_tag_feed(tag, &posts, &state.tera)?,
crate::feed::render_atom_tag_feed(tag, &state)?,
))
}

View file

@ -1,4 +1,4 @@
use std::{collections::HashMap, sync::Arc, time::Duration};
use std::{collections::HashMap, fmt::Display, sync::Arc, time::Duration};
use axum::extract::MatchedPath;
use color_eyre::eyre::{Error, Result};
@ -17,6 +17,7 @@ mod handlers;
mod post;
mod tag;
#[derive(Default)]
pub struct AppState {
base_url: String,
posts: HashMap<String, Post>,
@ -52,9 +53,9 @@ async fn main() -> Result<()> {
.make_span_with(make_span)
.on_response(on_response),
)
.with_state(state);
.with_state(state.clone());
info!("Now listening at http://localhost:8180");
info!("Now listening at {}", state.base_url);
axum::Server::bind(&"0.0.0.0:8180".parse().unwrap())
.serve(app.into_make_service())
@ -107,11 +108,32 @@ pub enum WebsiteError {
InternalError(Error),
}
impl<E> From<E> for WebsiteError
where
E: Into<Error>,
{
fn from(value: E) -> Self {
impl std::error::Error for WebsiteError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
WebsiteError::NotFound => None,
WebsiteError::InternalError(e) => Some(e.as_ref()),
}
}
}
impl Display for WebsiteError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
WebsiteError::NotFound => write!(f, "Not found"),
_ => write!(f, "Internal error"),
}
}
}
impl From<tera::Error> for WebsiteError {
fn from(value: tera::Error) -> Self {
WebsiteError::InternalError(value.into())
}
}
impl From<color_eyre::Report> for WebsiteError {
fn from(value: color_eyre::Report) -> Self {
WebsiteError::InternalError(value)
}
}

View file

@ -11,7 +11,7 @@ use tokio::fs;
use tracing::{instrument, log::*};
use crate::WebsiteError;
use crate::{AppState, WebsiteError};
#[derive(Deserialize, Debug, Default)]
pub struct TomlFrontMatter {
@ -138,25 +138,31 @@ fn parse_frontmatter(
})
}
#[instrument(skip(tera, post))]
pub async fn render_post(tera: &tera::Tera, post: &Post) -> Result<String, WebsiteError> {
#[instrument(skip(state, post))]
pub async fn render_post(state: &AppState, post: &Post) -> Result<String, WebsiteError> {
let mut ctx = tera::Context::new();
ctx.insert("page", &post);
ctx.insert("base_url", &state.base_url);
tera.render("post.html", &ctx).map_err(|e| e.into())
state.tera.render("post.html", &ctx).map_err(|e| e.into())
}
#[cfg(test)]
mod tests {
use tera::Tera;
use crate::AppState;
#[tokio::test]
async fn render_all_posts() {
let tera = Tera::new("templates/**/*").unwrap();
let posts = super::load_all().await.unwrap();
for (_slug, post) in posts {
super::render_post(&tera, &post).await.unwrap();
let state = AppState {
base_url: "localhost:8180".into(),
posts: super::load_all().await.unwrap(),
tera: Tera::new("templates/**/*").unwrap(),
..Default::default()
};
for post in state.posts.values() {
super::render_post(&state, post).await.unwrap();
}
}
}

View file

@ -6,11 +6,11 @@
<subtitle>tollyx's corner of the web</subtitle>
<link href="{{ feed_url | safe }}" rel="self" type="application/atom+xml"/>
{% if tag -%}
<link href="https://tollyx.net/tags/{{ tag.slug }}/"/>
<link href="{{ base_url | safe }}/tags/{{ tag.slug }}/"/>
{%- else -%}
<link href="https://tollyx.net"/>
<link href="{{ base_url | safe }}"/>
{%- endif %}
<generator uri="https://tollyx.net">tollyx-website</generator>
<generator uri="{{ base_url | safe }}">tollyx-website</generator>
<updated>{{ last_updated | date(format="%+") }}</updated>
<id>{{ feed_url | safe }}</id>
{%- for post in posts %}
@ -21,7 +21,7 @@
<author>
<name>tollyx</name>
</author>
<link rel="alternate" href="https://tollyx.net{{ post.absolute_path | safe }}" type="text/html"/>
<link rel="alternate" href="{{ base_url | safe }}{{ post.absolute_path | safe }}" type="text/html"/>
<id>{{ post.slug | safe }}</id>
<content type="html">{{ post.content }}</content>
</entry>

View file

@ -2,9 +2,9 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="alternate" type="application/rss+xml" href="https://tollyx.net/atom.xml" title="tollyx.net">
<link rel="alternate" type="application/rss+xml" href="/atom.xml" title="tollyx.net">
{% if tag_slug -%}
<link rel="alternate" type="application/rss+xml" href="https://tollyx.net/tags/{{ tag_slug }}/atom.xml" title="tollyx.net: Posts tagged #{{ tag_slug }}">
<link rel="alternate" type="application/rss+xml" href="/tags/{{ tag_slug }}/atom.xml" title="tollyx.net: Posts tagged #{{ tag_slug }}">
{%- endif %}
<link rel="stylesheet" href="/static/site.css">
<link rel="icon" type="image/png" href="/static/avatar.png" />
@ -17,14 +17,14 @@
{%- else -%}
<meta property="og:title" content="tollyx.net" />
{%- endif %}
<meta property="og:image" content="https://tollyx.net/avatar.png" />
<meta property="og:image" content="/avatar.png" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@tollyx" />
<meta name="twitter:creator" content="@tollyx" />
<meta name="twitter:dnt" content="on">
{% if page.title -%}
<title>{{ page.title }} | tollyx.net</title>
<title>{{ page.title }} | tollyx.net</title>
{%- else -%}
<title>tollyx.net</title>
<title>tollyx.net</title>
{%- endif %}
</head>