main.rs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. extern crate chrono;
  2. mod config;
  3. mod theme;
  4. mod repository;
  5. use actix_web::middleware::Logger;
  6. use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
  7. use fern;
  8. use std::{env, io};
  9. use crate::config::Configuration;
  10. use crate::theme::Theme;
  11. use crate::repository::{
  12. ArticlesRepository,
  13. FsRepository
  14. };
  15. #[get("")]
  16. async fn show_articles_list() -> impl Responder {
  17. let repo: FsRepository = FsRepository {};
  18. const CONTENT_FOLDER: &str = "./content";
  19. let exe_dir = env::current_dir()
  20. .and_then(|dir| Ok(dir.to_str().unwrap_or("").to_string()))
  21. .unwrap();
  22. log::trace!("Estimated content repository: {exe_dir}/{CONTENT_FOLDER}");
  23. let paths = repo.get_directory_listing(&CONTENT_FOLDER).join("\n");
  24. HttpResponse::Ok().body(format!("List of articles:\r\n{paths}"))
  25. }
  26. #[get("/{path:.+}")]
  27. async fn show_article(path: web::Path<(String,)>) -> impl Responder {
  28. let p = format!("./content/{}", &path.0);
  29. let exe_dir = env::current_dir()
  30. .and_then(|dir| Ok(dir.to_str().unwrap_or("").to_string()))
  31. .unwrap();
  32. let theme_path = format!("{}/www/themes/default", exe_dir);
  33. log::info!("Theme path: {}", theme_path);
  34. let theme = Theme::new(theme_path);
  35. let rendered = theme.markdown_as_html(&p);
  36. match rendered {
  37. Ok(content) => HttpResponse::Ok().body(content),
  38. Err(e) => {
  39. log::error!("Couldn't find article located at '{}'. Error: {}", p, e);
  40. HttpResponse::NotFound().finish()
  41. }
  42. }
  43. }
  44. #[actix_web::main]
  45. async fn main() -> io::Result<()> {
  46. if !env::vars().any(|(k, _)| k == "RUST_LOG") {
  47. env::set_var("RUST_LOG", "trace");
  48. }
  49. let config = Configuration::default();
  50. let _ = fern::Dispatch::new()
  51. .format(|out, message, record| {
  52. out.finish(format_args!(
  53. "{}[{}][{}] {}",
  54. chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
  55. record.target(),
  56. record.level(),
  57. message
  58. ))
  59. })
  60. .level(log::LevelFilter::Info)
  61. .chain(io::stdout())
  62. .apply();
  63. HttpServer::new(|| {
  64. App::new()
  65. .wrap(Logger::default())
  66. .service(actix_files::Files::new("/css", "./www/themes/default/css"))
  67. .service(actix_files::Files::new(
  68. "/images",
  69. "./www/themes/default/images",
  70. ))
  71. .service(actix_files::Files::new("/js", "./www/themes/default/js"))
  72. .service(
  73. web::scope("/a")
  74. .service(show_article)
  75. .service(show_articles_list),
  76. )
  77. })
  78. .bind((config.listen_addr, config.listen_port))?
  79. .run()
  80. .await
  81. }