diff options
| author | Christine Dodrill <me@christine.website> | 2020-07-16 15:32:30 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-16 15:32:30 -0400 |
| commit | 385d25c9f96c0acd5d932488e3bd0ed36ceb4dd7 (patch) | |
| tree | af789f7250519b23038a7e5ea0ae7f4f4c1ffdfc /src/main.rs | |
| parent | 449e934246c82d90dd0aac2644d67f928befeeb4 (diff) | |
| download | xesite-385d25c9f96c0acd5d932488e3bd0ed36ceb4dd7.tar.xz xesite-385d25c9f96c0acd5d932488e3bd0ed36ceb4dd7.zip | |
Rewrite site backend in Rust (#178)
* add shell.nix changes for Rust #176
* set up base crate layout
* add first set of dependencies
* start adding basic app modules
* start html templates
* serve index page
* add contact and feeds pages
* add resume rendering support
* resume cleanups
* get signalboost page working
* rewrite config to be in dhall
* more work
* basic generic post loading
* more tests
* initial blog index support
* fix routing?
* render blogposts
* X-Clacks-Overhead
* split blog handlers into blog.rs
* gallery index
* gallery posts
* fix hashtags
* remove instantpage (it messes up the metrics)
* talk support + prometheus
* Create rust.yml
* Update rust.yml
* Update codeql-analysis.yml
* add jsonfeed library
* jsonfeed support
* rss/atom
* go mod tidy
* atom: add posted date
* rss: add publishing date
* nix: build rust program
* rip out go code
* rip out go templates
* prepare for serving in docker
* create kubernetes deployment
* create automagic deployment
* build docker images on non-master
* more fixes
* fix timestamps
* fix RSS/Atom/JSONFeed validation errors
* add go vanity import redirecting
* templates/header: remove this
* atom feed: fixes
* fix?
* fix??
* fix rust tests
* Update rust.yml
* automatically show snow during the winter
* fix dates
* show commit link in footer
* sitemap support
* fix compiler warning
* start basic patreon client
* integrate kankyo
* fix patreon client
* add patrons page
* remove this
* handle patron errors better
* fix build
* clean up deploy
* sort envvars for deploy
* remove deps.nix
* shell.nix: remove go
* update README
* fix envvars for tests
* nice
* blog: add rewrite in rust post
* blog/site-update: more words
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..aa5400e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,154 @@ +use anyhow::Result; +use hyper::{header::CONTENT_TYPE, Body, Response}; +use prometheus::{Encoder, TextEncoder}; +use std::sync::Arc; +use warp::{path, Filter}; + +pub mod app; +pub mod handlers; +pub mod post; +pub mod signalboost; + +use app::State; + +const APPLICATION_NAME: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); + +fn with_state( + state: Arc<State>, +) -> impl Filter<Extract = (Arc<State>,), Error = std::convert::Infallible> + Clone { + warp::any().map(move || state.clone()) +} + +#[tokio::main] +async fn main() -> Result<()> { + let _ = kankyo::init(); + pretty_env_logger::init(); + log::info!("starting up commit {}", env!("GITHUB_SHA")); + + let state = Arc::new(app::init( + std::env::var("CONFIG_FNAME") + .unwrap_or("./config.dhall".into()) + .as_str() + .into(), + ).await?); + + let healthcheck = warp::get().and(warp::path(".within").and(warp::path("health")).map(|| "OK")); + + let base = warp::path!("blog" / ..); + let blog_index = base + .and(warp::path::end()) + .and(with_state(state.clone())) + .and_then(handlers::blog::index); + let series = base + .and(warp::path!("series").and(with_state(state.clone()).and_then(handlers::blog::series))); + let series_view = base.and( + warp::path!("series" / String) + .and(with_state(state.clone())) + .and(warp::get()) + .and_then(handlers::blog::series_view), + ); + let post_view = base.and( + warp::path!(String) + .and(with_state(state.clone())) + .and(warp::get()) + .and_then(handlers::blog::post_view), + ); + + let gallery_base = warp::path!("gallery" / ..); + let gallery_index = gallery_base + .and(warp::path::end()) + .and(with_state(state.clone())) + .and_then(handlers::gallery::index); + let gallery_post_view = gallery_base.and( + warp::path!(String) + .and(with_state(state.clone())) + .and(warp::get()) + .and_then(handlers::gallery::post_view), + ); + + let talk_base = warp::path!("talks" / ..); + let talk_index = talk_base + .and(warp::path::end()) + .and(with_state(state.clone())) + .and_then(handlers::talks::index); + let talk_post_view = talk_base.and( + warp::path!(String) + .and(with_state(state.clone())) + .and(warp::get()) + .and_then(handlers::talks::post_view), + ); + + let index = warp::get().and(path::end().and_then(handlers::index)); + let contact = warp::path!("contact").and_then(handlers::contact); + let feeds = warp::path!("feeds").and_then(handlers::feeds); + let resume = warp::path!("resume") + .and(with_state(state.clone())) + .and_then(handlers::resume); + let signalboost = warp::path!("signalboost") + .and(with_state(state.clone())) + .and_then(handlers::signalboost); + let patrons = warp::path!("patrons") + .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 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_then(handlers::feeds::jsonfeed); + let atom = warp::path("blog.atom") + .and(with_state(state.clone())) + .and_then(handlers::feeds::atom); + let rss = warp::path("blog.rss") + .and(with_state(state.clone())) + .and_then(handlers::feeds::rss); + let sitemap = warp::path("sitemap.xml") + .and(with_state(state.clone())) + .and_then(handlers::feeds::sitemap); + + 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_then(go_vanity::gitea); + + let metrics_endpoint = warp::path("metrics").and(warp::path::end()).map(move || { + let encoder = TextEncoder::new(); + let metric_families = prometheus::gather(); + let mut buffer = vec![]; + encoder.encode(&metric_families, &mut buffer).unwrap(); + Response::builder() + .status(200) + .header(CONTENT_TYPE, encoder.format_type()) + .body(Body::from(buffer)) + .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))) + .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))) + .or(healthcheck.or(metrics_endpoint).or(go_vanity_jsonfeed)) + .map(|reply| { + warp::reply::with_header( + reply, + "X-Hacker", + "If you are reading this, check out /signalboost to find people for your team", + ) + }) + .map(|reply| warp::reply::with_header(reply, "X-Clacks-Overhead", "GNU Ashlynn")) + .with(warp::log(APPLICATION_NAME)) + .recover(handlers::rejection); + + warp::serve(site).run(([0, 0, 0, 0], 3030)).await; + + Ok(()) +} + +include!(concat!(env!("OUT_DIR"), "/templates.rs")); |
