diff --git a/src/modes/server.rs b/src/modes/server.rs index 3f40195..ca6fb8e 100644 --- a/src/modes/server.rs +++ b/src/modes/server.rs @@ -6,6 +6,7 @@ use axum::{ routing::get, Router, }; +use axum::extract::connect_info::ConnectInfo as AxumConnectInfo; use clap::Command; use log::{debug, info, warn}; use serde::{Deserialize, Serialize}; @@ -19,6 +20,7 @@ use tokio::sync::Mutex; use tower_http::cors::CorsLayer; use tower::ServiceBuilder; use tower_http::trace::TraceLayer; +use std::net::SocketAddr; use crate::db; use crate::Args; @@ -128,6 +130,7 @@ async fn run_server( ServiceBuilder::new() .layer(TraceLayer::new_for_http()) .layer(CorsLayer::permissive()) + .layer(axum::extract::connect_info::IntoMakeServiceWithConnectInfo::into_make_service_with_connect_info::) ) .with_state(state); @@ -216,10 +219,16 @@ async fn handle_list_items( .unwrap_or_default(); let items = if tags.is_empty() { - db::get_items(&mut *conn).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + db::get_items(&mut *conn).map_err(|e| { + warn!("Failed to get items: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })? } else { db::get_items_matching(&mut *conn, &tags, &HashMap::new()) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .map_err(|e| { + warn!("Failed to get items matching tags {:?}: {}", tags, e); + StatusCode::INTERNAL_SERVER_ERROR + })? }; // Get item IDs for batch queries @@ -227,9 +236,15 @@ async fn handle_list_items( // Get tags and metadata for all items let tags_map = db::get_tags_for_items(&mut *conn, &item_ids) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + .map_err(|e| { + warn!("Failed to get tags for items: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })?; let meta_map = db::get_meta_for_items(&mut *conn, &item_ids) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + .map_err(|e| { + warn!("Failed to get metadata for items: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })?; let item_infos: Vec = items .into_iter() @@ -278,26 +293,39 @@ async fn handle_get_item( let mut conn = state.db.lock().await; let item = if let Ok(id) = item_id.parse::() { - db::get_item(&mut *conn, id).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + db::get_item(&mut *conn, id).map_err(|e| { + warn!("Failed to get item {}: {}", id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? } else { // Try to find by tags if let Some(tags_str) = params.tags { let tags: Vec = tags_str.split(',').map(|t| t.trim().to_string()).collect(); db::get_item_matching(&mut *conn, &tags, &HashMap::new()) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .map_err(|e| { + warn!("Failed to get item matching tags {:?}: {}", tags, e); + StatusCode::INTERNAL_SERVER_ERROR + })? } else { + warn!("Invalid item ID '{}' and no tags provided", item_id); return Err(StatusCode::BAD_REQUEST); } }; if let Some(item) = item { let item_tags = db::get_item_tags(&mut *conn, &item) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .map_err(|e| { + warn!("Failed to get tags for item {}: {}", item.id.unwrap_or(0), e); + StatusCode::INTERNAL_SERVER_ERROR + })? .into_iter() .map(|t| t.name) .collect(); let item_meta = db::get_item_meta(&mut *conn, &item) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .map_err(|e| { + warn!("Failed to get metadata for item {}: {}", item.id.unwrap_or(0), e); + StatusCode::INTERNAL_SERVER_ERROR + })? .into_iter() .map(|m| (m.name, m.value)) .collect(); @@ -362,8 +390,14 @@ async fn handle_delete_item( if let Ok(id) = item_id.parse::() { let mut conn = state.db.lock().await; - if let Some(item) = db::get_item(&mut *conn, id).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? { - db::delete_item(&mut *conn, item).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + if let Some(item) = db::get_item(&mut *conn, id).map_err(|e| { + warn!("Failed to get item {} for deletion: {}", id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? { + db::delete_item(&mut *conn, item).map_err(|e| { + warn!("Failed to delete item {}: {}", id, e); + StatusCode::INTERNAL_SERVER_ERROR + })?; let response = ApiResponse::<()> { success: true, @@ -396,9 +430,15 @@ async fn handle_get_content_latest( let item = if let Some(tags_str) = params.tags { let tags: Vec = tags_str.split(',').map(|t| t.trim().to_string()).collect(); db::get_item_matching(&mut *conn, &tags, &HashMap::new()) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .map_err(|e| { + warn!("Failed to get item matching tags {:?} for content: {}", tags, e); + StatusCode::INTERNAL_SERVER_ERROR + })? } else { - db::get_item_last(&mut *conn).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + db::get_item_last(&mut *conn).map_err(|e| { + warn!("Failed to get last item for content: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })? }; if let Some(_item) = item { @@ -430,7 +470,10 @@ async fn handle_get_content( if let Ok(id) = item_id.parse::() { let mut conn = state.db.lock().await; - if let Some(_item) = db::get_item(&mut *conn, id).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? { + if let Some(_item) = db::get_item(&mut *conn, id).map_err(|e| { + warn!("Failed to get item {} for content: {}", id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? { // Get the actual content - this would need to be implemented // based on how content is stored and retrieved in your system let response = ApiResponse:: {