The code and data behind xeiaso.net
5
fork

Configure Feed

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

add API calls for my blogposts/talks

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

Xe Iaso 8b6056fc 5d7daf17

+68 -2
+33 -1
src/handlers/blog.rs
··· 3 3 use axum::{ 4 4 extract::{Extension, Path}, 5 5 response::Html, 6 + Json, 6 7 }; 7 8 use http::HeaderMap; 8 9 use lazy_static::lazy_static; ··· 13 14 lazy_static! { 14 15 static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!( 15 16 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"), 16 22 &["name"] 17 23 ) 18 24 .unwrap(); ··· 80 86 headers: HeaderMap, 81 87 ) -> Result { 82 88 let mut want: Option<Post> = None; 89 + let want_link = format!("blog/{}", name); 83 90 84 91 for post in &state.blog { 85 - if post.link == format!("blog/{}", name) { 92 + if post.link == want_link { 86 93 want = Some(post.clone()); 87 94 } 88 95 } ··· 107 114 } 108 115 } 109 116 } 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 + }
+33 -1
src/handlers/talks.rs
··· 3 3 use axum::{ 4 4 extract::{Extension, Path}, 5 5 response::Html, 6 + Json, 6 7 }; 7 8 use http::header::HeaderMap; 8 9 use lazy_static::lazy_static; ··· 13 14 lazy_static! { 14 15 static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!( 15 16 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"), 16 22 &["name"] 17 23 ) 18 24 .unwrap(); ··· 33 39 headers: HeaderMap, 34 40 ) -> Result { 35 41 let mut want: Option<Post> = None; 42 + let want_link = format!("talks/{}", name); 36 43 37 44 for post in &state.talks { 38 - if post.link == format!("talks/{}", name) { 45 + if post.link == want_link { 39 46 want = Some(post.clone()); 40 47 } 41 48 } ··· 60 67 } 61 68 } 62 69 } 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 + }
+2
src/main.rs
··· 160 160 "/api/salary_transparency.json", 161 161 get(handlers::salary_transparency_json), 162 162 ) 163 + .route("/api/blog/:name", get(handlers::blog::post_json)) 164 + .route("/api/talks/:name", get(handlers::talks::post_json)) 163 165 // static pages 164 166 .route("/", get(handlers::index)) 165 167 .route("/contact", get(handlers::contact))