From a469e9b9d904feba98cfcd37c8e1321058705fa7 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 17 Mar 2026 22:47:21 -0700 Subject: [PATCH] Fix multipart fallback to use first part data when no filename Go reads the first part's data unconditionally, then looks for a part with a filename. If none found, Go uses the first part's data (with empty filename). Rust only captured parts with filenames, so when no part had a filename it fell back to the raw multipart body bytes (including boundary delimiters), producing corrupt needle data. --- seaweed-volume/src/server/handlers.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/seaweed-volume/src/server/handlers.rs b/seaweed-volume/src/server/handlers.rs index 3d5ba372b..28ef78bcb 100644 --- a/seaweed-volume/src/server/handlers.rs +++ b/seaweed-volume/src/server/handlers.rs @@ -1986,6 +1986,7 @@ pub async fn post_handler( ); let mut file_data: Option> = None; + let mut first_part_data: Option> = None; let mut file_name: Option = None; let mut file_content_type: Option = None; let mut file_content_encoding: Option = None; @@ -2007,8 +2008,14 @@ pub async fn post_handler( .map(|s| s.to_string()); if let Ok(data) = field.bytes().await { + // Go reads the first part's data unconditionally, then looks for + // a part with a filename. If no part has a filename, Go uses the + // first part's data (with empty filename). + if first_part_data.is_none() { + first_part_data = Some(data.to_vec()); + } if file_data.is_none() && fname.is_some() { - // First file field + // Found a file field — use this part's data file_data = Some(data.to_vec()); file_name = fname; file_content_type = fct; @@ -2031,9 +2038,12 @@ pub async fn post_handler( file_content_md5, form_fields, ) + } else if let Some(data) = first_part_data { + // No file field found, use first part's data (matching Go behavior) + (data, String::new(), None, None, None, form_fields) } else { - // No file field found, use raw body - (body.to_vec(), String::new(), None, None, None, form_fields) + // No parts at all + (Vec::new(), String::new(), None, None, None, form_fields) } } else { (