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}