macroblog.rs @ cc9fada4aa00b219c962ebb9b86437c7b6ca0c38

  1use std::convert::Infallible;
  2use std::{include_str, env};
  3use std::net::SocketAddr;
  4use hyper::{Body, Request, Response, Server};
  5use hyper::service::{make_service_fn, service_fn};
  6use regex::Regex;
  7use sailfish::TemplateOnce;
  8
  9
 10#[derive(TemplateOnce)]
 11#[template(path = "index.html")]
 12struct IndexTemplate {
 13    posts: [Post; 2],
 14}
 15
 16#[derive(TemplateOnce)]
 17#[template(path = "post.html")]
 18struct PostTemplate {
 19    content: &'static str,
 20}
 21
 22
 23struct Post(
 24    u8,
 25    &'static str,
 26    &'static str,
 27);
 28
 29const POSTS: [Post; 2] = [
 30    Post(
 31        0,
 32        "K8S private gitlab registry using podman",
 33        include_str!("../assets/post1.html"),
 34    ),
 35    Post(
 36        1,
 37        "Automation part 1",
 38        include_str!("../assets/post2.html"),
 39    ),
 40];
 41
 42fn get_path_id(path: &str) -> usize {
 43    let re = Regex::new(r"(?P<id>\d+)").unwrap();
 44    let caps = re.captures(path).unwrap();
 45    let id = &caps["id"];
 46
 47    return id.parse::<usize>().unwrap();
 48}
 49
 50async fn index() -> Result<Response<Body>, Infallible> {
 51    let body = IndexTemplate { posts: POSTS }
 52        .render_once()
 53        .unwrap();
 54
 55    let resp: Response<Body> = Response::builder()
 56        .status(200)
 57        .header("posts-type", "text/html")
 58        .body(body.into())
 59        .unwrap();
 60
 61    Ok(resp)
 62}
 63
 64
 65async fn post(index: usize) -> Result<Response<Body>, Infallible> {
 66    let body = PostTemplate { content: POSTS[index].2 }
 67        .render_once()
 68        .unwrap();
 69
 70    let resp: Response<Body> = Response::builder()
 71        .status(200)
 72        .header("posts-type", "text/html")
 73        .body(body.into())
 74        .unwrap();
 75
 76    Ok(resp)
 77}
 78
 79async fn request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
 80    let path = req.uri().path();
 81    if path == "/favicon.ico" {
 82        return index().await
 83    }
 84    if path != "/" {
 85        let index = get_path_id(&path);
 86        return post(index).await;
 87    }
 88
 89
 90    return index().await;
 91}
 92
 93
 94#[tokio::main]
 95async fn main() {
 96    let port = env::var("PORT").unwrap_or("3000".into()).parse::<u16>().unwrap_or(300);
 97    let addr = SocketAddr::from(([127, 0, 0, 1], port));
 98
 99    let make_svc = make_service_fn(|_conn| async {
100        Ok::<_, Infallible>(service_fn(request))
101    });
102
103    let server = Server::bind(&addr).serve(make_svc);
104
105    if let Err(e) = server.await {
106        eprintln!("server error: {}", e);
107    }
108}