macroblog.rs @ 00229809fbb412342f76b503c7745f67090c5813

  1pub mod router;
  2
  3use std::convert::Infallible;
  4use rust_embed::RustEmbed;
  5use std::{env, str};
  6use std::net::SocketAddr;
  7use hyper::{Body, Request, Response, Server};
  8use hyper::service::{make_service_fn, service_fn};
  9use sailfish::TemplateOnce;
 10use ::router::Router;
 11
 12#[derive(TemplateOnce)]
 13#[template(path = "index.html")]
 14struct IndexTemplate {
 15    posts: Vec<String>,
 16}
 17
 18#[derive(TemplateOnce)]
 19#[template(path = "post.html")]
 20struct PostTemplate {
 21    content: String,
 22}
 23
 24#[derive(RustEmbed)]
 25#[folder = "content/posts/"]
 26struct PostAsset;
 27
 28
 29fn get_file_content(path: &str) -> String {
 30    let buffer = PostAsset::get(path)
 31        .unwrap()
 32        .data
 33        .into_owned();
 34
 35    return String::from_utf8(buffer).unwrap();
 36}
 37
 38fn get_post_title() -> Vec<String> {
 39    PostAsset::iter()
 40        .map(|e| format!("{}", e))
 41        .collect()
 42}
 43
 44
 45async fn not_found() -> Result<Response<Body>, Infallible> {
 46    let resp: Response<Body> = Response::builder()
 47        .status(404)
 48        .body("Not Found".into())
 49        .unwrap();
 50    Ok(resp)
 51}
 52
 53
 54async fn index() -> Result<Response<Body>, Infallible> {
 55    let files = get_post_title();
 56    let body = IndexTemplate { posts: files }
 57        .render_once()
 58        .unwrap();
 59
 60    let resp: Response<Body> = Response::builder()
 61        .status(200)
 62        .header("posts-type", "text/html")
 63        .body(body.into())
 64        .unwrap();
 65
 66    Ok(resp)
 67}
 68
 69
 70async fn post(path: &String) -> Result<Response<Body>, Infallible> {
 71    let body = PostTemplate { content: get_file_content(path) }
 72        .render_once()
 73        .unwrap();
 74
 75    let resp: Response<Body> = Response::builder()
 76        .status(200)
 77        .header("posts-type", "text/html")
 78        .body(body.into())
 79        .unwrap();
 80
 81    Ok(resp)
 82}
 83
 84async fn request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
 85    let path = req.uri().path();
 86
 87    match Router::new(path) {
 88        Router::Index => index().await,
 89        Router::Post { page } => post(&page).await,
 90        Router::NotFound => not_found().await
 91    }
 92}
 93
 94
 95#[tokio::main]
 96async fn main() {
 97    let port = env::var("PORT").unwrap_or("3000".into()).parse::<u16>().unwrap_or(3000);
 98    let addr = SocketAddr::from(([0, 0, 0, 0], port));
 99
100    let make_svc = make_service_fn(|_conn| async {
101        Ok::<_, Infallible>(service_fn(request))
102    });
103
104    let server = Server::bind(&addr).serve(make_svc);
105
106    if let Err(e) = server.await {
107        eprintln!("server error: {}", e);
108    }
109}