The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

consolidate API routes

Signed-off-by: Xe Iaso <me@christine.website>

Xe Iaso b32f5a25 18ae8a01

+85 -82
+78
src/handlers/api.rs
··· 1 + use crate::{ 2 + app::{config::Job, State}, 3 + handlers::Result, 4 + post::Post, 5 + }; 6 + use axum::extract::{Extension, Json, Path}; 7 + use lazy_static::lazy_static; 8 + use prometheus::{opts, register_int_counter_vec, IntCounterVec}; 9 + use std::sync::Arc; 10 + 11 + lazy_static! { 12 + static ref BLOG: IntCounterVec = register_int_counter_vec!( 13 + opts!("blogpost_json_hits", "Number of hits to blogposts"), 14 + &["name"] 15 + ) 16 + .unwrap(); 17 + static ref TALK: IntCounterVec = register_int_counter_vec!( 18 + opts!("talks_json_hits", "Number of hits to talks images"), 19 + &["name"] 20 + ) 21 + .unwrap(); 22 + } 23 + 24 + #[axum_macros::debug_handler] 25 + #[instrument(skip(state))] 26 + pub async fn salary_transparency(Extension(state): Extension<Arc<State>>) -> Json<Vec<Job>> { 27 + super::HIT_COUNTER 28 + .with_label_values(&["salary_transparency_json"]) 29 + .inc(); 30 + 31 + Json(state.clone().cfg.clone().job_history.clone()) 32 + } 33 + 34 + #[instrument(skip(state))] 35 + pub async fn blog( 36 + Path(name): Path<String>, 37 + Extension(state): Extension<Arc<State>>, 38 + ) -> Result<Json<xe_jsonfeed::Item>> { 39 + let mut want: Option<Post> = None; 40 + let want_link = format!("blog/{}", name); 41 + 42 + for post in &state.blog { 43 + if post.link == want_link { 44 + want = Some(post.clone()); 45 + } 46 + } 47 + 48 + match want { 49 + None => Err(super::Error::PostNotFound(name)), 50 + Some(post) => { 51 + BLOG.with_label_values(&[name.clone().as_str()]).inc(); 52 + Ok(Json(post.into())) 53 + } 54 + } 55 + } 56 + 57 + #[instrument(skip(state))] 58 + pub async fn talk( 59 + Path(name): Path<String>, 60 + Extension(state): Extension<Arc<State>>, 61 + ) -> Result<Json<xe_jsonfeed::Item>> { 62 + let mut want: Option<Post> = None; 63 + let want_link = format!("talks/{}", name); 64 + 65 + for post in &state.talks { 66 + if post.link == want_link { 67 + want = Some(post.clone()); 68 + } 69 + } 70 + 71 + match want { 72 + None => Err(super::Error::PostNotFound(name)), 73 + Some(post) => { 74 + TALK.with_label_values(&[name.clone().as_str()]).inc(); 75 + Ok(Json(post.into())) 76 + } 77 + } 78 + }
-31
src/handlers/blog.rs
··· 3 3 use axum::{ 4 4 extract::{Extension, Path}, 5 5 response::Html, 6 - Json, 7 6 }; 8 7 use http::HeaderMap; 9 8 use lazy_static::lazy_static; ··· 14 13 lazy_static! { 15 14 static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!( 16 15 opts!("blogpost_hits", "Number of hits to blogposts"), 17 - &["name"] 18 - ) 19 - .unwrap(); 20 - static ref HIT_COUNTER_JSON: IntCounterVec = register_int_counter_vec!( 21 - opts!("blogpost_json_hits", "Number of hits to blogposts"), 22 16 &["name"] 23 17 ) 24 18 .unwrap(); ··· 114 108 } 115 109 } 116 110 } 117 - 118 - #[instrument(skip(state))] 119 - pub async fn post_json( 120 - Path(name): Path<String>, 121 - Extension(state): Extension<Arc<State>>, 122 - ) -> Result<Json<xe_jsonfeed::Item>> { 123 - let mut want: Option<Post> = None; 124 - let want_link = format!("blog/{}", name); 125 - 126 - for post in &state.blog { 127 - if post.link == want_link { 128 - want = Some(post.clone()); 129 - } 130 - } 131 - 132 - match want { 133 - None => Err(super::Error::PostNotFound(name)), 134 - Some(post) => { 135 - HIT_COUNTER_JSON 136 - .with_label_values(&[name.clone().as_str()]) 137 - .inc(); 138 - Ok(Json(post.into())) 139 - } 140 - } 141 - }
+3 -16
src/handlers/mod.rs
··· 1 - use crate::{ 2 - app::{Job, State}, 3 - templates, 4 - }; 1 + use crate::{app::State, templates}; 5 2 use axum::{ 6 3 body, 7 4 extract::Extension, 8 5 http::StatusCode, 9 6 response::{Html, IntoResponse, Response}, 10 - Json, 11 7 }; 12 8 use chrono::{Datelike, Timelike, Utc, Weekday}; 13 9 use lazy_static::lazy_static; ··· 15 11 use std::sync::Arc; 16 12 use tracing::instrument; 17 13 14 + pub mod api; 18 15 pub mod blog; 19 16 pub mod feeds; 20 17 pub mod gallery; ··· 52 49 } 53 50 54 51 lazy_static! { 55 - static ref HIT_COUNTER: IntCounterVec = 52 + pub static ref HIT_COUNTER: IntCounterVec = 56 53 register_int_counter_vec!(opts!("hits", "Number of hits to various pages"), &["page"]) 57 54 .unwrap(); 58 55 pub static ref LAST_MODIFIED: String = { ··· 104 101 let mut result: Vec<u8> = vec![]; 105 102 templates::salary_transparency(&mut result, state.cfg.clone())?; 106 103 Ok(Html(result)) 107 - } 108 - 109 - #[axum_macros::debug_handler] 110 - #[instrument(skip(state))] 111 - pub async fn salary_transparency_json(Extension(state): Extension<Arc<State>>) -> Json<Vec<Job>> { 112 - HIT_COUNTER 113 - .with_label_values(&["salary_transparency_json"]) 114 - .inc(); 115 - 116 - Json(state.clone().cfg.clone().job_history.clone()) 117 104 } 118 105 119 106 #[axum_macros::debug_handler]
-31
src/handlers/talks.rs
··· 3 3 use axum::{ 4 4 extract::{Extension, Path}, 5 5 response::Html, 6 - Json, 7 6 }; 8 7 use http::header::HeaderMap; 9 8 use lazy_static::lazy_static; ··· 14 13 lazy_static! { 15 14 static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!( 16 15 opts!("talks_hits", "Number of hits to talks images"), 17 - &["name"] 18 - ) 19 - .unwrap(); 20 - static ref HIT_COUNTER_JSON: IntCounterVec = register_int_counter_vec!( 21 - opts!("talks_json_hits", "Number of hits to talks images"), 22 16 &["name"] 23 17 ) 24 18 .unwrap(); ··· 67 61 } 68 62 } 69 63 } 70 - 71 - #[instrument(skip(state))] 72 - pub async fn post_json( 73 - Path(name): Path<String>, 74 - Extension(state): Extension<Arc<State>>, 75 - ) -> Result<Json<xe_jsonfeed::Item>> { 76 - let mut want: Option<Post> = None; 77 - let want_link = format!("talks/{}", name); 78 - 79 - for post in &state.talks { 80 - if post.link == want_link { 81 - want = Some(post.clone()); 82 - } 83 - } 84 - 85 - match want { 86 - None => Err(super::Error::PostNotFound(name)), 87 - Some(post) => { 88 - HIT_COUNTER_JSON 89 - .with_label_values(&[name.clone().as_str()]) 90 - .inc(); 91 - Ok(Json(post.into())) 92 - } 93 - } 94 - }
+4 -3
src/main.rs
··· 156 156 ), 157 157 ) 158 158 // api 159 + .route("/api/new_post", get(handlers::feeds::new_post)) 159 160 .route( 160 161 "/api/salary_transparency.json", 161 - get(handlers::salary_transparency_json), 162 + get(handlers::api::salary_transparency), 162 163 ) 163 - .route("/api/blog/:name", get(handlers::blog::post_json)) 164 - .route("/api/talks/:name", get(handlers::talks::post_json)) 164 + .route("/api/blog/:name", get(handlers::api::blog)) 165 + .route("/api/talks/:name", get(handlers::api::talk)) 165 166 // static pages 166 167 .route("/", get(handlers::index)) 167 168 .route("/contact", get(handlers::contact))
-1
templates/talkpost.rs.html
··· 1 1 @use super::{header_html, footer_html}; 2 2 @use crate::{post::Post, tmpl::nag}; 3 - @use chrono::prelude::*; 4 3 5 4 @(post: Post, body: impl ToHtml, referer: Option<String>) 6 5