1
0
Fork 0

Compare commits

...

2 commits

Author SHA1 Message Date
Adrian Hedqvist ff8f38c563 polish 2023-03-26 12:40:25 +02:00
Adrian Hedqvist 0d9115749b hide posts with future dates 2023-03-26 12:01:59 +02:00
8 changed files with 67 additions and 41 deletions

7
Cargo.lock generated
View file

@ -50,12 +50,6 @@ dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "async-compression"
version = "0.3.15"
@ -2085,7 +2079,6 @@ checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
name = "website"
version = "0.1.0"
dependencies = [
"anyhow",
"axum",
"cached",
"chrono",

View file

@ -6,13 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.70"
axum = { version = "0.6.12", features = ["http2"] }
cached = "0.42.0"
chrono = { version = "0.4.24", features = ["serde"] }
color-eyre = "0.6.1"
glob = "0.3.0"
#grass = { version = "0.12.3", features = ["random"] } # not really needed yet
hyper = { version = "0.14.19", features = ["full"] }
lazy_static = "1.4.0"
prometheus = { version = "0.13.3", features = ["process"] }

View file

@ -1,12 +1,15 @@
FROM rust:slim AS chef
RUN cargo install cargo-chef
WORKDIR app
WORKDIR /app
####################################################################################################
## Planner
####################################################################################################
FROM chef AS planner
COPY . .
WORKDIR /app
COPY ./Cargo.lock ./
COPY ./Cargo.toml ./
COPY ./src ./src
RUN cargo chef prepare --recipe-path recipe.json
####################################################################################################
@ -33,10 +36,14 @@ RUN adduser \
WORKDIR /app
COPY --from=planner /app/recipe.json .
COPY --from=planner /app/recipe.json ./
RUN cargo chef cook --target x86_64-unknown-linux-musl --release --recipe-path recipe.json
COPY . .
COPY ./Cargo.lock ./
COPY ./Cargo.toml ./
COPY ./src ./src
RUN cargo build --target x86_64-unknown-linux-musl --release
@ -53,9 +60,9 @@ WORKDIR /app
# Copy our build
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/website ./
COPY --from=builder /app/posts ./posts
COPY --from=builder /app/static ./static
COPY --from=builder /app/templates ./templates
COPY ./static ./static
COPY ./templates ./templates
COPY ./posts ./posts
EXPOSE 8180

View file

@ -1,10 +1,13 @@
+++
title="TOML metadata test"
date=2023-03-25T14:50:25+01:00
date=2023-03-26T11:57:00+02:00
+++
hope it works yay
here have a squid miku to test relative paths:
here have a squid kid miku to test relative paths:
![Squid kid miku](FbHSmoeUUAA2x-m.png)
modified post test, see if docker skips build using
its cache if only a post has changed.

View file

@ -13,8 +13,11 @@ use crate::{State, WebsiteError};
pub mod posts;
lazy_static! {
pub static ref HIT_COUNTER: IntCounterVec =
prometheus::register_int_counter_vec!(opts!("page_hits", "Number of hits to various pages"), &["page"]).unwrap();
pub static ref HIT_COUNTER: IntCounterVec = prometheus::register_int_counter_vec!(
opts!("page_hits", "Number of hits to various pages"),
&["page"]
)
.unwrap();
}
#[instrument(skip(state))]
@ -30,6 +33,10 @@ pub async fn index(
Ok(Html(res.into()))
}
pub async fn not_found() -> Response {
(StatusCode::NOT_FOUND, ()).into_response()
}
impl IntoResponse for WebsiteError {
fn into_response(self) -> Response {
match self {

View file

@ -15,23 +15,10 @@ pub fn router() -> Router {
Router::new()
.route("/", get(index))
.route("/:slug/", get(view))
.route("/:slug/index.md", get(super::not_found))
.fallback_service(tower_http::services::ServeDir::new("./posts"))
}
#[instrument(skip(state))]
pub async fn view(
Path(slug): Path<String>,
Extension(state): Extension<Arc<State>>,
) -> Result<Html<String>, WebsiteError> {
debug!("viewing post: {slug}");
let post = state.posts.get(&slug).ok_or(WebsiteError::NotFound)?;
let res = render_post(&state.tera, post).await?;
HIT_COUNTER.with_label_values(&[&format!("/posts/{}/", slug)]).inc();
Ok(Html(res))
}
#[derive(Serialize)]
struct IndexContext<'a> {
title: &'a str,
@ -40,7 +27,11 @@ struct IndexContext<'a> {
#[instrument(skip(state))]
pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Html<String>, WebsiteError> {
let mut posts = state.posts.values().collect::<Vec<&Post>>();
let mut posts = state
.posts
.values()
.filter(|p| p.is_published())
.collect::<Vec<&Post>>();
posts.sort_by_key(|p| &p.date);
posts.reverse();
@ -64,3 +55,22 @@ pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Html<Strin
HIT_COUNTER.with_label_values(&["/posts/"]).inc();
Ok(Html(res))
}
#[instrument(skip(state))]
pub async fn view(
Path(slug): Path<String>,
Extension(state): Extension<Arc<State>>,
) -> Result<Html<String>, WebsiteError> {
let post = state.posts.get(&slug).ok_or(WebsiteError::NotFound)?;
if !post.is_published() {
warn!("attempted to view post before it has been published!");
return Err(WebsiteError::NotFound);
}
let res = render_post(&state.tera, post).await?;
HIT_COUNTER
.with_label_values(&[&format!("/posts/{slug}/")])
.inc();
Ok(Html(res))
}

View file

@ -1,10 +1,10 @@
use std::{collections::HashMap, sync::Arc};
use axum::{routing::get, Extension, Router, response::Response, body};
use color_eyre::eyre::Result;
use axum::{body, response::Response, routing::get, Extension, Router};
use color_eyre::eyre::{Result, Error};
use hyper::header::CONTENT_TYPE;
use post::Post;
use prometheus::{TextEncoder, Encoder};
use prometheus::{Encoder, TextEncoder};
use tera::Tera;
use tower_http::{compression::CompressionLayer, trace::TraceLayer};
use tracing::{instrument, log::*};
@ -50,7 +50,7 @@ pub async fn init_app() -> Result<Router> {
.route("/", get(handlers::index))
.nest("/posts", handlers::posts::router())
.nest_service("/static", tower_http::services::ServeDir::new("./static"))
.route("/.healthcheck", get(healthcheck))
.route("/healthcheck", get(healthcheck))
.route("/metrics", get(metrics))
.layer(middleware);
@ -76,12 +76,12 @@ async fn metrics() -> Response {
#[derive(Debug)]
pub enum WebsiteError {
NotFound,
InternalError(anyhow::Error),
InternalError(Error),
}
impl<E> From<E> for WebsiteError
where
E: Into<anyhow::Error>,
E: Into<Error>,
{
fn from(value: E) -> Self {
WebsiteError::InternalError(value.into())

View file

@ -47,6 +47,14 @@ impl Post {
tags: fm.tags.unwrap_or_default(),
}
}
pub fn is_published(&self) -> bool {
let now = chrono::offset::Local::now();
if let Some(date) = self.date {
return date.timestamp() - now.timestamp() <= 0;
}
true
}
}
#[instrument]