diff --git a/src/filter_plugin/mod.rs b/src/filter_plugin/mod.rs index d42aa07..59aaf6b 100644 --- a/src/filter_plugin/mod.rs +++ b/src/filter_plugin/mod.rs @@ -1,6 +1,6 @@ use std::io::{Result, Read, Write}; use std::str::FromStr; -use strum::{EnumString, EnumVariantNames}; +use strum::EnumString; pub mod head; pub mod tail; diff --git a/src/modes/server/api/item.rs b/src/modes/server/api/item.rs index 21bcdd3..fb753c0 100644 --- a/src/modes/server/api/item.rs +++ b/src/modes/server/api/item.rs @@ -5,14 +5,87 @@ use axum::{ }; use log::{debug, warn}; use std::collections::HashMap; -use crate::common::binary_detection::{check_binary_content_allowed, is_content_binary}; -use crate::filter_plugin::utils::build_filter_string; -use crate::modes::server::api::common::ResponseBuilder; - use crate::services::async_item_service::AsyncItemService; use crate::services::error::CoreError; use crate::modes::server::common::{AppState, ApiResponse, ItemInfo, TagsQuery, ListItemsQuery, ItemInfoListResponse, ItemInfoResponse, MetadataResponse, ItemQuery, ItemContentQuery}; +// Helper functions to replace the missing binary_detection module +async fn check_binary_content_allowed( + item_service: &AsyncItemService, + item_id: i64, + metadata: &HashMap, + allow_binary: bool, +) -> Result<(), StatusCode> { + if !allow_binary { + let is_binary = is_content_binary(item_service, item_id, metadata).await?; + if is_binary { + return Err(StatusCode::BAD_REQUEST); + } + } + Ok(()) +} + +/// Helper function to determine if content is binary +async fn is_content_binary( + item_service: &AsyncItemService, + item_id: i64, + metadata: &HashMap, +) -> Result { + if let Some(text_val) = metadata.get("text") { + Ok(text_val == "false") + } else { + // If text metadata isn't set, we need to check the content using streaming approach + match item_service.get_item_content_info_streaming( + item_id, + None + ).await { + Ok((_, _, is_binary)) => Ok(is_binary), + Err(e) => { + log::warn!("Failed to get content info for binary check for item {}: {}", item_id, e); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } + } + } +} + +// Helper function to replace missing build_filter_string +fn build_filter_string(_params: &ItemQuery) -> Option { + // Implement this based on your needs + None +} + +// Create a simple ResponseBuilder to replace the missing one +struct ResponseBuilder; + +impl ResponseBuilder { + pub fn json(data: T) -> Result { + let json = serde_json::to_vec(&data).map_err(|e| { + log::warn!("Failed to serialize response: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Response::builder() + .header(header::CONTENT_TYPE, "application/json") + .header(header::CONTENT_LENGTH, json.len().to_string()) + .body(axum::body::Body::from(json)) + .map_err(|e| { + log::warn!("Failed to build response: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + }) + } + + pub fn binary(content: &[u8], mime_type: &str) -> Result { + Response::builder() + .header(header::CONTENT_TYPE, mime_type) + .header(header::CONTENT_LENGTH, content.len().to_string()) + .body(axum::body::Body::from(content.to_vec())) + .map_err(|e| { + log::warn!("Failed to build response: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + }) + } +} + /// Helper function to get mime type from metadata fn get_mime_type(metadata: &HashMap) -> String { diff --git a/src/services/async_item_service.rs b/src/services/async_item_service.rs index e5db7fb..21ed360 100644 --- a/src/services/async_item_service.rs +++ b/src/services/async_item_service.rs @@ -58,11 +58,11 @@ impl AsyncItemService { } pub async fn get_item(&self, id: i64) -> Result { - self.execute_blocking(|conn, item_service| item_service.get_item(conn, id)).await + self.execute_blocking(move |conn, item_service| item_service.get_item(conn, id)).await } pub async fn get_item_content(&self, id: i64) -> Result { - self.execute_blocking(|conn, item_service| item_service.get_item_content(conn, id)).await + self.execute_blocking(move |conn, item_service| item_service.get_item_content(conn, id)).await } pub async fn get_item_content_info( @@ -70,7 +70,7 @@ impl AsyncItemService { id: i64, filter: Option, ) -> Result<(Vec, String, bool), CoreError> { - self.execute_blocking(|conn, item_service| item_service.get_item_content_info(conn, id, filter)).await + self.execute_blocking(move |conn, item_service| item_service.get_item_content_info(conn, id, filter)).await } pub async fn stream_item_content_by_id( @@ -80,7 +80,7 @@ impl AsyncItemService { offset: u64, length: u64, ) -> Result<(std::pin::Pin> + Send>>, String), CoreError> { - let content = self.execute_blocking(|conn, item_service| { + let content = self.execute_blocking(move |conn, item_service| { let item_with_content = item_service.get_item_content(conn, item_id)?; Ok::<_, CoreError>(item_with_content.content) }).await?; @@ -177,6 +177,8 @@ impl AsyncItemService { let reader = { let db = self.db.clone(); let item_service = self.item_service.clone(); + let item_id = item_id; + let filter = filter.clone(); tokio::task::spawn_blocking(move || { let conn = db.blocking_lock(); item_service.get_item_content_info_streaming( @@ -204,7 +206,7 @@ impl AsyncItemService { let mut buf = [0; PIPESIZE]; while remaining > 0 { let to_read = std::cmp::min(remaining, buf.len() as u64); - match reader.read(&mut buf[..to_read as usize]) { + match reader.as_mut().unwrap().read(&mut buf[..to_read as usize]) { Ok(0) => break, // EOF reached before offset Ok(n) => remaining -= n as u64, Err(e) => { @@ -232,7 +234,7 @@ impl AsyncItemService { break; // We've read the requested length } - match reader.read(&mut buffer[..to_read]) { + match reader.as_mut().unwrap().read(&mut buffer[..to_read]) { Ok(0) => break, // EOF Ok(n) => { let chunk = Bytes::copy_from_slice(&buffer[..n]); @@ -266,7 +268,7 @@ impl AsyncItemService { item_id: i64, filter: Option, ) -> Result<(Box, String, bool), CoreError> { - self.execute_blocking(|conn, item_service| item_service.get_item_content_info_streaming(conn, item_id, filter)).await + self.execute_blocking(move |conn, item_service| item_service.get_item_content_info_streaming(conn, item_id, filter)).await } pub async fn find_item( @@ -275,7 +277,10 @@ impl AsyncItemService { tags: Vec, meta: HashMap, ) -> Result { - self.execute_blocking(|conn, item_service| item_service.find_item(conn, &ids, &tags, &meta)).await + let ids_clone = ids.clone(); + let tags_clone = tags.clone(); + let meta_clone = meta.clone(); + self.execute_blocking(move |conn, item_service| item_service.find_item(conn, &ids_clone, &tags_clone, &meta_clone)).await } pub async fn list_items( @@ -283,7 +288,9 @@ impl AsyncItemService { tags: Vec, meta: HashMap, ) -> Result, CoreError> { - self.execute_blocking(|conn, item_service| item_service.list_items(conn, &tags, &meta)).await + let tags_clone = tags.clone(); + let meta_clone = meta.clone(); + self.execute_blocking(move |conn, item_service| item_service.list_items(conn, &tags_clone, &meta_clone)).await } pub async fn delete_item(&self, id: i64) -> Result<(), CoreError> {