An ATProtocol powered blogging engine.

feature: sitemap handler

Signed-off-by: Nick Gerakines <nick.gerakines@gmail.com>

Changed files
+39 -1
src
templates
+28 -1
src/http.rs
··· 9 Router, 10 body::Body, 11 extract::{Path, State}, 12 - http::{StatusCode, header}, 13 response::{IntoResponse, Response}, 14 routing::get, 15 }; ··· 83 title: String, 84 created_at: String, 85 created_at_date: String, 86 aturi: String, 87 } 88 ··· 96 title: post.title, 97 created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(), 98 created_at_date: post.created_at.format("%Y-%m-%d").to_string(), 99 }) 100 } 101 } ··· 104 pub fn create_router(state: AppState) -> Router { 105 Router::new() 106 .route("/", get(handle_index)) 107 .route("/posts/{full_slug}", get(handle_post)) 108 .route( 109 "/posts/{full_slug}/{collection}", ··· 112 .route("/content/{cid}", get(handle_content)) 113 .nest_service("/static", ServeDir::new(&state.config.http.static_path)) 114 .with_state(state) 115 } 116 117 /// GET / - Handle the index page (home page).
··· 9 Router, 10 body::Body, 11 extract::{Path, State}, 12 + http::{HeaderMap, HeaderValue, StatusCode, header}, 13 response::{IntoResponse, Response}, 14 routing::get, 15 }; ··· 83 title: String, 84 created_at: String, 85 created_at_date: String, 86 + updated_at_date: String, 87 aturi: String, 88 } 89 ··· 97 title: post.title, 98 created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(), 99 created_at_date: post.created_at.format("%Y-%m-%d").to_string(), 100 + updated_at_date: post.updated_at.format("%Y-%m-%d").to_string(), 101 }) 102 } 103 } ··· 106 pub fn create_router(state: AppState) -> Router { 107 Router::new() 108 .route("/", get(handle_index)) 109 + .route("/sitemap.xml", get(hande_sitemap)) 110 .route("/posts/{full_slug}", get(handle_post)) 111 .route( 112 "/posts/{full_slug}/{collection}", ··· 115 .route("/content/{cid}", get(handle_content)) 116 .nest_service("/static", ServeDir::new(&state.config.http.static_path)) 117 .with_state(state) 118 + } 119 + 120 + async fn hande_sitemap(State(state): State<AppState>) -> Result<impl IntoResponse> { 121 + match get_all_posts(&state).await { 122 + Ok(posts) => { 123 + let mut headers = HeaderMap::new(); 124 + headers.insert( 125 + "Content-Type", 126 + HeaderValue::from_static("application/xml; charset=utf-8"), 127 + ); 128 + 129 + Ok(( 130 + headers, 131 + RenderHtml( 132 + "sitemap.xml", 133 + state.template_env.clone(), 134 + context! { 135 + posts => posts, 136 + }, 137 + ), 138 + )) 139 + } 140 + Err(_) => Err(BlahgError::HttpInternalServerError), 141 + } 142 } 143 144 /// GET / - Handle the index page (home page).
+11
templates/sitemap.xml
···
··· 1 + <?xml version='1.0' encoding='UTF-8'?> 2 + <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 + xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" 4 + xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 5 + {% for post in posts %} 6 + <url> 7 + <loc>{{ external_base }}/posts/{{ post.slug }}</loc> 8 + <lastmod>{{ post.updated_at_date }}</lastmod> 9 + </url> 10 + {% endfor %} 11 + </urlset>