use std::convert::Infallible; use std::{include_str, env}; use std::net::SocketAddr; use hyper::{Body, Request, Response, Server}; use hyper::service::{make_service_fn, service_fn}; use regex::Regex; use sailfish::TemplateOnce; #[derive(TemplateOnce)] #[template(path = "index.html")] struct IndexTemplate { posts: [Post; 2], } #[derive(TemplateOnce)] #[template(path = "post.html")] struct PostTemplate { content: &'static str, } struct Post( u8, &'static str, &'static str, ); const POSTS: [Post; 2] = [ Post( 0, "K8S private gitlab registry using podman", include_str!("../assets/post1.html"), ), Post( 1, "Automation part 1", include_str!("../assets/post2.html"), ), ]; fn get_path_id(path: &str) -> usize { let re = Regex::new(r"(?P\d+)").unwrap(); let caps = re.captures(path).unwrap(); let id = &caps["id"]; return id.parse::().unwrap(); } async fn index() -> Result, Infallible> { let body = IndexTemplate { posts: POSTS } .render_once() .unwrap(); let resp: Response = Response::builder() .status(200) .header("posts-type", "text/html") .body(body.into()) .unwrap(); Ok(resp) } async fn post(index: usize) -> Result, Infallible> { let body = PostTemplate { content: POSTS[index].2 } .render_once() .unwrap(); let resp: Response = Response::builder() .status(200) .header("posts-type", "text/html") .body(body.into()) .unwrap(); Ok(resp) } async fn request(req: Request) -> Result, Infallible> { let path = req.uri().path(); if path == "/favicon.ico" { return index().await } if path != "/" { let index = get_path_id(&path); return post(index).await; } return index().await; } #[tokio::main] async fn main() { let port = env::var("PORT").unwrap_or("3000".into()).parse::().unwrap_or(300); let addr = SocketAddr::from(([127, 0, 0, 1], port)); let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(request)) }); let server = Server::bind(&addr).serve(make_svc); if let Err(e) = server.await { eprintln!("server error: {}", e); } }