- Updated the layout and styling of the statistics page for better responsiveness and visual appeal. - Introduced a new error page for 404 errors with user-friendly messaging and navigation options. - Enhanced logging functionality to capture detailed events related to asset uploads, deletions, and HTTP requests. - Implemented an AssetTracker to manage assets in memory, allowing for efficient tracking and retrieval. - Improved the API for uploading and retrieving assets, ensuring better error handling and response formatting. - Added auto-refresh functionality to the statistics page to keep data up-to-date.
82 lines
2.1 KiB
Rust
82 lines
2.1 KiB
Rust
use std::{fs::OpenOptions, io::Write};
|
|
|
|
use actix_web::HttpRequest;
|
|
use serde::Serialize;
|
|
|
|
use crate::{LOG_DIR, data_mgt::Asset};
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct LogHttpRequest {
|
|
pub method: String,
|
|
pub path: String,
|
|
pub query_string: String,
|
|
pub scheme: String,
|
|
pub ip: String,
|
|
pub real_ip: String,
|
|
pub user_agent: String,
|
|
}
|
|
impl From<HttpRequest> for LogHttpRequest {
|
|
fn from(req: HttpRequest) -> Self {
|
|
let method = req.method().as_str().to_string();
|
|
let uri = req.uri();
|
|
let path = uri.path().to_string();
|
|
let query_string = uri.query().unwrap_or("-").to_string();
|
|
|
|
let connection_info = req.connection_info();
|
|
let scheme = connection_info.scheme().to_string();
|
|
let ip = connection_info.peer_addr().unwrap_or("-").to_string();
|
|
let real_ip = connection_info.realip_remote_addr().unwrap_or("-").to_string();
|
|
|
|
let user_agent = req
|
|
.headers()
|
|
.get("user-agent")
|
|
.and_then(|v| v.to_str().ok())
|
|
.unwrap_or("-")
|
|
.to_string();
|
|
|
|
LogHttpRequest {
|
|
method,
|
|
path,
|
|
query_string,
|
|
scheme,
|
|
ip,
|
|
real_ip,
|
|
user_agent,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub enum LogEventType<'a> {
|
|
AssetUploaded(&'a Asset),
|
|
AssetDeleted(&'a Asset),
|
|
HttpRequest(&'a LogHttpRequest),
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct LogEvent<'a> {
|
|
pub time: String,
|
|
pub event: LogEventType<'a>,
|
|
}
|
|
|
|
impl<'a> From<LogEventType<'a>> for LogEvent<'a> {
|
|
fn from(event: LogEventType<'a>) -> Self {
|
|
let time = chrono::Utc::now().to_rfc3339();
|
|
LogEvent { time, event }
|
|
}
|
|
}
|
|
|
|
pub fn log_event(event: LogEventType) {
|
|
let log_path = LOG_DIR.to_string() + "access.log";
|
|
|
|
let Ok(mut file) = OpenOptions::new().create(true).append(true).open(log_path) else {
|
|
eprintln!("failed to open log file for asset event");
|
|
return;
|
|
};
|
|
|
|
let log_event: LogEvent = event.into();
|
|
let line = serde_json::to_string(&log_event).unwrap_or_else(|e| e.to_string());
|
|
|
|
let _ = writeln!(file, "{}", line);
|
|
}
|