فهرست منبع

Issue #1 - Refactor listing endpoint to extract fs logic

Alexandre Leblanc 3 سال پیش
والد
کامیت
b5d859d522
7فایلهای تغییر یافته به همراه171 افزوده شده و 25 حذف شده
  1. 1 1
      .gitignore
  2. 54 4
      Cargo.lock
  3. 2 1
      Cargo.toml
  4. 15 0
      src/config.rs
  5. 77 19
      src/main.rs
  6. 13 0
      src/vcs/git.rs
  7. 9 0
      src/vcs/mod.rs

+ 1 - 1
.gitignore

@@ -10,4 +10,4 @@
 
 # Generated by Cargo
 /target/
-
+/content/

+ 54 - 4
Cargo.lock

@@ -165,7 +165,7 @@ dependencies = [
  "serde_urlencoded",
  "smallvec",
  "socket2",
- "time",
+ "time 0.3.11",
  "url",
 ]
 
@@ -300,6 +300,19 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "chrono"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time 0.1.44",
+ "winapi",
+]
+
 [[package]]
 name = "convert_case"
 version = "0.4.0"
@@ -313,7 +326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
 dependencies = [
  "percent-encoding",
- "time",
+ "time 0.3.11",
  "version_check",
 ]
 
@@ -466,7 +479,7 @@ checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -646,10 +659,29 @@ checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
 dependencies = [
  "libc",
  "log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys",
 ]
 
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.13.1"
@@ -911,6 +943,17 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "time"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+dependencies = [
+ "libc",
+ "wasi 0.10.0+wasi-snapshot-preview1",
+ "winapi",
+]
+
 [[package]]
 name = "time"
 version = "0.3.11"
@@ -1041,6 +1084,7 @@ name = "vcs-blog"
 version = "0.1.0"
 dependencies = [
  "actix-web",
+ "chrono",
  "fern",
  "log",
 ]
@@ -1051,6 +1095,12 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"

+ 2 - 1
Cargo.toml

@@ -8,4 +8,5 @@ description = "Blog engine running on version control system to store articles"
 [dependencies]
 actix-web = "4"
 log = "0.4"
-fern = "0.6"
+fern = "0.6"
+chrono = "0.4"

+ 15 - 0
src/config.rs

@@ -0,0 +1,15 @@
+pub struct Configuration {
+    pub listen_port: u16,
+    pub listen_addr: String,
+    pub vcs_dir: String,
+}
+
+impl Configuration {
+    pub fn default() -> Self {
+        Configuration {
+            listen_port: 8080,
+            listen_addr: "127.0.0.1".to_owned(),
+            vcs_dir: "vcs/".to_owned(),
+        }
+    }
+}

+ 77 - 19
src/main.rs

@@ -1,31 +1,89 @@
-use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
+mod config;
+mod vcs;
+
+extern crate chrono;
+
 use actix_web::middleware::Logger;
-use log;
+use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
+use fern;
+use log::error;
+use std::{env, io};
+
+use config::Configuration;
 
-#[get("/")]
-async fn hello() -> impl Responder {
-    HttpResponse::Ok().body("Hello world!")
+fn get_directory_listing(path: &str) -> Result<Vec<String>, io::Error>
+{
+    match std::fs::read_dir(path) {
+        Ok(files) => {
+            Ok(files
+                .into_iter()
+                .filter(|dir| dir.as_ref().unwrap().path().starts_with("./."))
+                .map(|dir| dir.as_ref().unwrap().path().to_str().unwrap().to_owned())
+                .collect::<Vec<String>>())
+        },
+        Err(error) => {
+            Err(error)
+        }
+    }
 }
 
-#[post("/echo")]
-async fn echo(req_body: String) -> impl Responder {
-    HttpResponse::Ok().body(req_body)
+#[get("")]
+async fn show_articles_list() -> impl Responder {
+    const CONTENT_FOLDER: &str = "./content";
+    let estimated_path: String = env::current_dir()
+        .unwrap_or_default()
+        .to_str()
+        .unwrap_or_default()
+        .to_string();
+
+    log::trace!("Estimated content repository: {estimated_path}/{CONTENT_FOLDER}");
+
+    let paths = match get_directory_listing(&CONTENT_FOLDER) {
+        Ok(list) => list.join("\n"),
+        Err(error) => {
+            error!("Couldn't list articles from path. Error: {error}");
+            String::new()
+        }
+    };
+
+    HttpResponse::Ok().body(format!("List of articles:\r\n{paths}"))
 }
 
-async fn manual_hello() -> impl Responder {
-    HttpResponse::Ok().body("Hey there!")
+#[get("/{path:.+}")]
+async fn show_article(path: web::Path<(String,)>) -> impl Responder {
+    HttpResponse::Ok().body(format!("Specific article: {}", path.into_inner().0))
 }
 
 #[actix_web::main]
 async fn main() -> std::io::Result<()> {
+    if !std::env::vars().any(|(k, _)| k == "RUST_LOG") {
+        std::env::set_var("RUST_LOG", "trace");
+    }
+
+    let config = Configuration::default();
+
+    let _ = fern::Dispatch::new()
+        .format(|out, message, record| {
+            out.finish(format_args!(
+                "{}[{}][{}] {}",
+                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
+                record.target(),
+                record.level(),
+                message
+            ))
+        })
+        .level(log::LevelFilter::Info)
+        .chain(std::io::stdout())
+        .apply();
+
     HttpServer::new(|| {
-        App::new()
-            .wrap(Logger::default())
-            .service(hello)
-            .service(echo)
-            .route("/hey", web::get().to(manual_hello))
+        App::new().wrap(Logger::default()).service(
+            web::scope("/a")
+                .service(show_article)
+                .service(show_articles_list),
+        )
     })
-        .bind(("127.0.0.1", 8080))?
-        .run()
-        .await
-}
+    .bind((config.listen_addr, config.listen_port))?
+    .run()
+    .await
+}

+ 13 - 0
src/vcs/git.rs

@@ -0,0 +1,13 @@
+use crate::vcs::VersionSource;
+
+struct Git {}
+
+impl VersionSource for Git {
+    fn update() -> Result<String, String> {
+        todo!()
+    }
+
+    fn commit() -> Result<String, String> {
+        todo!()
+    }
+}

+ 9 - 0
src/vcs/mod.rs

@@ -0,0 +1,9 @@
+mod git;
+
+trait VersionSource {
+    // Update local
+    fn update() -> Result<String, String>;
+
+    // Update remotes
+    fn commit() -> Result<String, String>;
+}