feat: update dependencies, enhance upload rate limiting, and improve UI elements
This commit is contained in:
82
Cargo.lock
generated
82
Cargo.lock
generated
@@ -340,9 +340,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
version = "1.2.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@@ -503,15 +503,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.5"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
||||
checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
@@ -837,9 +837,9 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.12.1"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
@@ -879,9 +879,9 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -1059,18 +1059,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.104"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
||||
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1103,9 +1103,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
@@ -1219,9 +1219,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.148"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -1315,9 +1315,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.112"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1337,30 +1337,30 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.44"
|
||||
version = "0.3.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||
checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||
checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.24"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||
checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
@@ -1378,9 +1378,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.48.0"
|
||||
version = "1.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
|
||||
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -1406,9 +1406,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.17"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
|
||||
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -1457,9 +1457,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.8.1"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -1481,9 +1481,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.7"
|
||||
version = "2.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
|
||||
checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@@ -1832,18 +1832,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.31"
|
||||
version = "0.8.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.31"
|
||||
version = "0.8.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1906,9 +1906,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.7"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de9211a9f64b825911bdf0240f58b7a8dac217fe260fc61f080a07f61372fbd5"
|
||||
checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea"
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Black Hole Share</h1>
|
||||
<h1><a href="/" class="home-link">Black Hole Share</a></h1>
|
||||
|
||||
<div class="upload-container">
|
||||
<div class="upload-area">
|
||||
@@ -368,6 +368,26 @@
|
||||
}
|
||||
});
|
||||
|
||||
function canTriggerUpload() {
|
||||
return (
|
||||
currentContentData &&
|
||||
window.getComputedStyle(uploadBtn).display !== "none" &&
|
||||
zoomOverlay.style.display !== "flex"
|
||||
);
|
||||
}
|
||||
|
||||
// ENTER TO UPLOAD (when content is ready)
|
||||
document.addEventListener(
|
||||
"keydown",
|
||||
function (e) {
|
||||
if ((e.key === "Enter" || e.code === "NumpadEnter") && canTriggerUpload()) {
|
||||
e.preventDefault();
|
||||
uploadBtn.click();
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
window.addEventListener("resize", function () {
|
||||
if (currentContentData) {
|
||||
displayContent(currentContentData);
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
|
||||
.activity-list {
|
||||
max-height: 300px;
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
font-size: 0.85em;
|
||||
|
||||
@@ -29,7 +29,7 @@ body {
|
||||
height: 100vh;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
padding-bottom: 140px;
|
||||
padding-bottom: 80px;
|
||||
background-color: var(--bg-tertiary);
|
||||
background-image:
|
||||
radial-gradient(1200px 800px at 10% -20%, var(--bg-glow), transparent 60%),
|
||||
@@ -453,7 +453,7 @@ h1 .home-link:hover {
|
||||
/* View page styles */
|
||||
body.view-page {
|
||||
width: 860px;
|
||||
padding-bottom: 140px;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
.view-container {
|
||||
@@ -476,6 +476,8 @@ body.view-page {
|
||||
border-top: 1px solid var(--border-color);
|
||||
font-size: 0.9em;
|
||||
color: var(--text-secondary);
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.powered-by .home-link {
|
||||
|
||||
0
data/html/test/test.txt
Normal file
0
data/html/test/test.txt
Normal file
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "1.90.0"
|
||||
36
src/api.rs
36
src/api.rs
@@ -6,7 +6,7 @@ use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
LOG_FILE_NAME,
|
||||
data_mgt::{Asset, AssetTracker},
|
||||
data_mgt::{AppState, Asset},
|
||||
logs::{LogEvent, LogEventType, log_event},
|
||||
};
|
||||
|
||||
@@ -21,8 +21,24 @@ pub struct UploadRequest {
|
||||
async fn api_upload(
|
||||
req: HttpRequest,
|
||||
body: web::Json<UploadRequest>,
|
||||
assets: web::Data<AssetTracker>,
|
||||
app_state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Check for rate limiting
|
||||
let connection_info = req.connection_info();
|
||||
|
||||
let uploader_ip = connection_info
|
||||
.realip_remote_addr()
|
||||
.map(|s| s.to_string())
|
||||
.or_else(|| connection_info.peer_addr().map(|value| value.to_string()))
|
||||
.ok_or_else(|| actix_web::error::ErrorBadRequest("Cannot determine client ip"))?;
|
||||
|
||||
match app_state.connection_tracker.is_allowed(&uploader_ip).await {
|
||||
true => {}
|
||||
false => {
|
||||
return Ok(HttpResponse::TooManyRequests().body("Upload limit exceeded"));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to bytes
|
||||
let content_bytes = if body.content_type == "text/plain" {
|
||||
body.content.as_bytes().to_vec()
|
||||
@@ -32,12 +48,6 @@ async fn api_upload(
|
||||
Err(_) => return Ok(HttpResponse::BadRequest().body("Invalid base64 payload")),
|
||||
}
|
||||
};
|
||||
let connection_info = req.connection_info();
|
||||
let uploader_ip = connection_info
|
||||
.realip_remote_addr()
|
||||
.or_else(|| connection_info.peer_addr())
|
||||
.unwrap_or("-")
|
||||
.to_string();
|
||||
|
||||
let asset = crate::data_mgt::Asset::new(
|
||||
body.duration,
|
||||
@@ -48,7 +58,7 @@ async fn api_upload(
|
||||
|
||||
let id = asset.id();
|
||||
log_event(LogEventType::AssetUploaded(asset.to_value()));
|
||||
assets.add_asset(asset).await;
|
||||
app_state.assets.add_asset(asset).await;
|
||||
let response_body = json!({ "link": format!("/bhs/{}", id) });
|
||||
Ok(HttpResponse::Ok().json(response_body))
|
||||
}
|
||||
@@ -57,11 +67,11 @@ async fn api_upload(
|
||||
async fn api_get_asset(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
assets: web::Data<AssetTracker>,
|
||||
app_state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
log_event(LogEventType::HttpRequest(req.into()));
|
||||
|
||||
match assets.get_asset(&path.into_inner()).await {
|
||||
match app_state.assets.get_asset(&path.into_inner()).await {
|
||||
None => Ok(HttpResponse::NotFound().body("Asset not found")),
|
||||
Some(asset) => Ok(HttpResponse::Ok()
|
||||
.content_type(asset.mime())
|
||||
@@ -90,11 +100,11 @@ struct ActivityItem {
|
||||
}
|
||||
|
||||
#[get("/api/stats")]
|
||||
async fn api_stats(assets: web::Data<AssetTracker>) -> Result<HttpResponse, actix_web::Error> {
|
||||
async fn api_stats(app_state: web::Data<AppState>) -> Result<HttpResponse, actix_web::Error> {
|
||||
use crate::LOG_DIR;
|
||||
use std::fs;
|
||||
|
||||
let (active_assets, storage_bytes, image_count, text_count) = assets.stats_summary().await;
|
||||
let (active_assets, storage_bytes, image_count, text_count) = app_state.assets.stats_summary().await;
|
||||
|
||||
let mut total_uploads = 0;
|
||||
let mut total_deleted = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use anyhow::Result;
|
||||
use chrono::{Duration, Utc};
|
||||
@@ -7,7 +7,11 @@ use futures::lock::Mutex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::logs::{LogEventType, log_event};
|
||||
use crate::MAX_ASSETS;
|
||||
use crate::{
|
||||
MAX_UPLOADS_PER_HOUR_PER_USER,
|
||||
logs::{LogEventType, log_event},
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Asset {
|
||||
@@ -85,31 +89,30 @@ impl Asset {
|
||||
pub fn to_value(&self) -> Value {
|
||||
serde_json::to_value(self).unwrap_or(Value::Null)
|
||||
}
|
||||
|
||||
// pub fn save(&self) -> Result<String> {
|
||||
// let id = self.id.clone();
|
||||
// let path = format!("{}{}", DATA_STORAGE, self.id);
|
||||
// std::fs::create_dir_all(DATA_STORAGE)?;
|
||||
// std::fs::write(&path, self.to_bytes()?)?;
|
||||
// Ok(id)
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AssetTracker {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct AppState {
|
||||
pub assets: AssetStorage,
|
||||
pub connection_tracker: RateLimiter,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct AssetStorage {
|
||||
assets: Arc<Mutex<Vec<Asset>>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl AssetTracker {
|
||||
impl AssetStorage {
|
||||
pub fn new() -> Self {
|
||||
AssetTracker {
|
||||
assets: Arc::new(Mutex::new(Vec::new())),
|
||||
Self {
|
||||
assets: Arc::new(Mutex::new(Vec::with_capacity(MAX_ASSETS))),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn add_asset(&self, asset: Asset) {
|
||||
print!("[{}] Adding asset: {}", chrono::Local::now().to_rfc3339(), asset.id());
|
||||
|
||||
self.assets.lock().await.push(asset);
|
||||
self.show_assets().await;
|
||||
}
|
||||
@@ -173,7 +176,43 @@ impl AssetTracker {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn clear_assets(assets: AssetTracker) -> Result<()> {
|
||||
assets.remove_expired().await;
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct RateLimiter {
|
||||
pub clients: Arc<Mutex<HashMap<String, Vec<i64>>>>,
|
||||
}
|
||||
|
||||
impl RateLimiter {
|
||||
pub async fn is_allowed(&self, client_ip: &str) -> bool {
|
||||
let mut clients = self.clients.lock().await;
|
||||
let now = Utc::now().timestamp_millis();
|
||||
let one_hour_ago = now - Duration::hours(1).num_milliseconds();
|
||||
|
||||
let entry = clients.entry(client_ip.to_string()).or_insert_with(Vec::new);
|
||||
entry.retain(|×tamp| timestamp > one_hour_ago);
|
||||
|
||||
let ret_val = if entry.len() < MAX_UPLOADS_PER_HOUR_PER_USER {
|
||||
entry.push(now);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
println!("{:?}", clients);
|
||||
ret_val
|
||||
}
|
||||
|
||||
pub async fn clear_expired(&self) {
|
||||
let mut clients = self.clients.lock().await;
|
||||
let now = Utc::now().timestamp_millis();
|
||||
let one_hour_ago = now - Duration::hours(1).num_milliseconds();
|
||||
|
||||
for timestamps in clients.values_mut() {
|
||||
timestamps.retain(|×tamp| timestamp > one_hour_ago);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn clear_app_data(app_state: &AppState) -> Result<()> {
|
||||
app_state.assets.remove_expired().await;
|
||||
app_state.connection_tracker.clear_expired().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
14
src/main.rs
14
src/main.rs
@@ -14,6 +14,9 @@ use std::{env, fs, path::PathBuf, sync::LazyLock};
|
||||
pub static HTML_DIR: &str = "data/html/";
|
||||
pub static LOG_DIR: &str = "data/logs/";
|
||||
pub static LOG_FILE_NAME: &str = "log.txt";
|
||||
pub static MAX_ASSETS: usize = 1000;
|
||||
pub static MAX_ASSET_SIZE_BYTES: usize = 3 * 1024 * 1024; // 3 MB
|
||||
pub static MAX_UPLOADS_PER_HOUR_PER_USER: usize = 10;
|
||||
|
||||
pub static BIND_ADDR: LazyLock<String> = LazyLock::new(|| match env::var("BIND_ADDR") {
|
||||
Ok(addr) => {
|
||||
@@ -71,6 +74,7 @@ async fn view_asset(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
||||
|
||||
#[route("/{tail:.*}", method = "GET", method = "POST")]
|
||||
async fn catch_all(req: HttpRequest, _payload: Option<web::Json<Value>>) -> actix_web::Result<NamedFile> {
|
||||
println!("Catch-all route triggered for path: {}", req.uri().path());
|
||||
let response = match req.uri().path() {
|
||||
path if STATIC_PAGES.contains(&path[1..].into()) => {
|
||||
let file_path = HTML_DIR.to_string() + path;
|
||||
@@ -108,24 +112,24 @@ async fn main() -> std::io::Result<()> {
|
||||
});
|
||||
println!("Rotated log file to: {}_{}", time_tag, &LOG_FILE_NAME);
|
||||
}
|
||||
let assets = data_mgt::AssetTracker::new();
|
||||
let app_state = data_mgt::AppState::default();
|
||||
|
||||
println!("Starting server at http://{}:{}/", *BIND_ADDR, *BIND_PORT);
|
||||
let assets_clone = assets.clone();
|
||||
|
||||
let inner_appt_state = app_state.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(1));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
if let Err(e) = data_mgt::clear_assets(assets_clone.clone()).await {
|
||||
if let Err(e) = data_mgt::clear_app_data(&inner_appt_state).await {
|
||||
eprintln!("Error clearing assets: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::JsonConfig::default().limit(1024 * 1024 * 3))
|
||||
.app_data(web::Data::new(assets.clone()))
|
||||
.app_data(web::JsonConfig::default().limit(1024 * 1024 * 3)) // 3MB limit
|
||||
.app_data(web::Data::new(app_state.clone()))
|
||||
.service(index)
|
||||
.service(stats)
|
||||
.service(view_asset)
|
||||
|
||||
Reference in New Issue
Block a user