101 lines
2.5 KiB
Rust
101 lines
2.5 KiB
Rust
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<String>,
|
|
}
|
|
|
|
impl FromStr for ServerConfig {
|
|
type Err = anyhow::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
Ok(ServerConfig {
|
|
address: s.to_string(),
|
|
password: None,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct AppState {
|
|
pub db: Arc<Mutex<rusqlite::Connection>>,
|
|
pub data_dir: PathBuf,
|
|
pub password: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, ToSchema)]
|
|
pub struct ApiResponse<T> {
|
|
pub success: bool,
|
|
pub data: Option<T>,
|
|
pub error: Option<String>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, ToSchema)]
|
|
pub struct ItemInfo {
|
|
pub id: i64,
|
|
pub ts: String,
|
|
pub size: Option<i64>,
|
|
pub compression: String,
|
|
pub tags: Vec<String>,
|
|
pub metadata: HashMap<String, String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct TagsQuery {
|
|
pub tags: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct ListItemsQuery {
|
|
pub tags: Option<String>,
|
|
pub order: Option<String>,
|
|
pub start: Option<u32>,
|
|
pub count: Option<u32>,
|
|
}
|
|
|
|
pub fn check_auth(headers: &HeaderMap, password: &Option<String>) -> 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<axum::body::Body>,
|
|
next: axum::middleware::Next,
|
|
) -> Result<axum::http::Response<axum::body::Body>, 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)
|
|
}
|