use anyhow::Result; use axum::http::HeaderMap; use log::info; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; use std::time::Instant; use tokio::sync::Mutex; use utoipa::ToSchema; #[derive(Debug, Clone)] pub struct ServerConfig { pub address: String, pub password: Option, } impl FromStr for ServerConfig { type Err = anyhow::Error; fn from_str(s: &str) -> Result { Ok(ServerConfig { address: s.to_string(), password: None, }) } } #[derive(Clone)] pub struct AppState { pub db: Arc>, pub data_dir: PathBuf, pub password: Option, } #[derive(Serialize, Deserialize, ToSchema)] pub struct ApiResponse { pub success: bool, pub data: Option, pub error: Option, } #[derive(Serialize, Deserialize, ToSchema)] pub struct ItemInfo { pub id: i64, pub ts: String, pub size: Option, pub compression: String, pub tags: Vec, pub metadata: HashMap, } #[derive(Debug, Deserialize)] pub struct TagsQuery { pub tags: Option, } #[derive(Debug, Deserialize)] pub struct ListItemsQuery { pub tags: Option, pub order: Option, pub start: Option, pub count: Option, } pub fn check_auth(headers: &HeaderMap, password: &Option) -> bool { if let Some(expected_password) = password { if let Some(auth_header) = headers.get("authorization") { if let Ok(auth_str) = auth_header.to_str() { return auth_str.starts_with("Bearer ") && &auth_str[7..] == expected_password; } } false } else { true // No password required } } // Custom middleware for logging requests and responses pub async fn logging_middleware( req: axum::http::Request, next: axum::middleware::Next, ) -> Result, axum::response::Response> { let method = req.method().clone(); let uri = req.uri().clone(); let headers = req.headers().clone(); // Log incoming request info!("SERVER: {} {} - Headers: {:?}", method, uri, headers); let start = Instant::now(); let response = next.run(req).await; let duration = start.elapsed(); // Log response info!("SERVER: {} {} - Status: {} - Duration: {:?}", method, uri, response.status(), duration); Ok(response) }