This commit is contained in:
Mrrp 2025-03-23 18:29:29 -07:00
parent e3f54d988e
commit a5ed3001e2
12 changed files with 1763 additions and 14 deletions

1523
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,4 +6,8 @@ version = "0.1.0"
license = "MIT License"
edition = "2024"
[dependencies]
[dependencies]
actix-web = "4"
log = "0.4"
fern = "0.7"
gitea_sdk = "0.5"

38
output.log Normal file
View file

@ -0,0 +1,38 @@
[INFO actix_server::builder] starting 16 workers
[INFO actix_server::server] Actix runtime found; starting in Actix runtime
[INFO actix_server::server] starting service: "actix-web-service-127.0.0.1:8080", workers: 16, listening on: 127.0.0.1:8080
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset a is a file
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset a is a file
[INFO actix_server::server] SIGINT received; starting forced shutdown
[DEBUG actix_server::accept] paused accepting connections on 127.0.0.1:8080
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::worker] shutting down idle worker
[INFO actix_server::accept] accept thread stopped
[INFO actix_server::builder] starting 16 workers
[INFO actix_server::server] Actix runtime found; starting in Actix runtime
[INFO actix_server::server] starting service: "actix-web-service-127.0.0.1:8080", workers: 16, listening on: 127.0.0.1:8080
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset /index.html is a file
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset exampleDir is a directory
[DEBUG pages::storage::backend_filesystem] Requested asset is a directory: Inferring index.html
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset exampleDir/test.html is a file
[DEBUG pages::storage::backend_filesystem] Checking if site a exists: true
[DEBUG pages::storage::backend_filesystem] Asset exampleDir/index.html is a file

1
src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod storage;

View file

@ -1,5 +1,66 @@
pub mod storage;
use actix_web::{get, App, HttpRequest, HttpServer, Result};
use pages::storage::{backend_filesystem::PageStorageBackendFilesystem, PageStorageRead};
fn main() {
#[get("/page/{site_id}/{url:.*}")]
async fn asset(req: HttpRequest) -> Result<String> {
let v1: String = req.match_info().get("site_id").unwrap().parse().unwrap();
let v2: String = req.match_info().query("url").parse().unwrap();
let storage = PageStorageBackendFilesystem::new(
"C:/Users/anmei/Documents/MSS-LLC/pages/test_dir".to_string()
).unwrap();
match storage.asset_contents(&v1, &v2) {
Ok(content) => Ok(String::from_utf8(content).unwrap()),
Err(_) => Ok("Error".to_string())
}
}
#[get("/page/{site_id}")]
async fn index(req: HttpRequest) -> Result<String> {
let v1: String = req.match_info().get("site_id").unwrap().parse().unwrap();
let v2: String = req.match_info().query("url").parse().unwrap();
let storage = PageStorageBackendFilesystem::new(
"C:/Users/anmei/Documents/MSS-LLC/pages/test_dir".to_string()
).unwrap();
let fmt = format!("{}/index.html", &v2);
match storage.asset_contents(&v1, &fmt) {
Ok(content) => Ok(String::from_utf8(content).unwrap()),
Err(_) => Ok("Error".to_string())
}
}
fn setup_logger() -> Result<(), fern::InitError> {
fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
"[{} {}] {}",
record.level(),
record.target(),
message
))
})
.level(log::LevelFilter::Debug)
.chain(std::io::stdout())
.chain(fern::log_file("output.log")?)
.apply()?;
Ok(())
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let _ = setup_logger();
HttpServer::new(|| {
App::new()
.service(index)
.service(asset)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}

View file

@ -1,10 +0,0 @@
pub trait PageStorageRead {
fn url_contents(site_id: &str, url: &str) -> Result<[u8], ()>;
fn url_exists(site_id: &str, url: &str) -> Result<bool, ()>;
}
pub trait PageStorageWrite {
}

View file

@ -0,0 +1,100 @@
use std::{fs, io::Read, path::{self, Path}};
use log::debug;
use super::{PageStorageAssetType, PageStorageError, PageStorageRead};
#[derive(Debug)]
pub enum PageStorageBackendFilesystemError {
InvalidDirectory(String)
}
pub struct PageStorageBackendFilesystem {
storage_directory: String
}
impl PageStorageBackendFilesystem {
pub fn new(storage_directory: String) -> Result<Self, PageStorageBackendFilesystemError> {
// TODO: Perform checks on storage directory.
// - Is it a valid directory?
// - Is it a system directory?
Ok(Self {
storage_directory
})
}
}
// Stores page assets on filesystem as the following layout:
// - page_data
// - [...site_id...]
// - [...site assets...]
// ! WARNING: THIS IS NOT CURRENTLY ROBUST ENOUGH FOR PRODUCTION
impl PageStorageRead for PageStorageBackendFilesystem {
fn asset_contents(&self, site_id: &str, url: &str) -> Result<Vec<u8>, super::PageStorageError> {
match self.asset_exists(site_id, url) {
Ok(exists) => {
let mut url: String = url.to_string();
match exists {
PageStorageAssetType::IsFile => {},
PageStorageAssetType::IsDirectory => {
debug!("Requested asset is a directory: Inferring index.html");
url = format!("{}/index.html", url);
}
PageStorageAssetType::IsNone => return Err(PageStorageError::AssetDoesNotExist(url.to_string()))
}
// TODO: Reprocessing the path - Make it only do it once
let path_raw = format!("{}/{}/{}", &self.storage_directory, site_id, url);
let path: &Path = Path::new(&path_raw);
let file_result = fs::File::open(path);
match file_result {
Ok(mut file) => {
let mut vec = Vec::new();
// TODO: Unused result
file.read_to_end(&mut vec);
return Ok(vec)
}
Err(_) => Err(super::PageStorageError::InternalError("".to_string()))
}
},
Err(e) => Err(e)
}
}
fn asset_exists(&self, site_id: &str, url: &str) -> Result<PageStorageAssetType, super::PageStorageError> {
match self.site_exists(site_id) {
Ok(exists) => {
match exists {
true => {}
false => return Err(PageStorageError::SiteDoesNotExist(site_id.to_string()))
}
// TODO: VALIDATE URL
// TODO: We're reprocessing the path here - Make it only do it once
let path_raw = format!("{}/{}/{}", &self.storage_directory, site_id, url);
let path: &Path = Path::new(&path_raw);
if !path.exists() {
debug!("Asset {} does not exist", url);
return Ok(PageStorageAssetType::IsNone)
} if path.is_file() {
debug!("Asset {} is a file", url);
return Ok(PageStorageAssetType::IsFile)
} else if path.is_dir() {
debug!("Asset {} is a directory", url);
return Ok(PageStorageAssetType::IsDirectory)
} else {
return Err(PageStorageError::InternalError("Page exists, but is neither a file nor directory".to_string()))
}
},
Err(e) => Err(e)
}
}
fn site_exists(&self, site_id: &str) -> Result<bool, super::PageStorageError> {
// TODO: VALIDATE SITE_ID
let path_raw = format!("{}/{}", &self.storage_directory, site_id);
let path: &Path = Path::new(&path_raw);
let exists = path.exists() && path.is_dir();
debug!("Checking if site {} exists: {}", site_id, exists);
Ok(exists)
}
}

View file

@ -0,0 +1,3 @@
pub struct PageBackendFilesystemGitea {
client:
}

20
src/storage/mod.rs Normal file
View file

@ -0,0 +1,20 @@
pub mod backend_filesystem;
pub mod gitea_filesystem;
pub enum PageStorageError {
SiteDoesNotExist(String),
AssetDoesNotExist(String),
InternalError(String)
}
pub enum PageStorageAssetType {
IsNone,
IsFile,
IsDirectory
}
pub trait PageStorageRead {
fn asset_contents(&self, site_id: &str, url: &str) -> Result<Vec<u8>, PageStorageError>;
fn asset_exists(&self, site_id: &str, url: &str) -> Result<PageStorageAssetType, PageStorageError>;
fn site_exists(&self, site_id: &str) -> Result<bool, PageStorageError>;
}

View file

@ -0,0 +1,3 @@
<html>
<h1>Example Directory Index</h1>
</html>

View file

@ -0,0 +1,3 @@
<html>
<p>Specific HTML file test</p>
</html>

3
test_dir/a/index.html Normal file
View file

@ -0,0 +1,3 @@
<html>
<h1>Test</h1>
</html>