From 4a0fefe4a2102228fd21efa0357439d59e68085c Mon Sep 17 00:00:00 2001 From: RA <70325462+RAprogramm@users.noreply.github.com> Date: Thu, 11 Sep 2025 14:34:39 +0700 Subject: [PATCH] Document multipart error mapping --- src/convert/multipart.rs | 44 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/convert/multipart.rs b/src/convert/multipart.rs index f2e522a..f23750e 100644 --- a/src/convert/multipart.rs +++ b/src/convert/multipart.rs @@ -1,11 +1,51 @@ +//! Maps [`MultipartError`] into [`AppError`] with +//! [`AppErrorKind::BadRequest`], preserving the original message. +//! +//! Intended for Axum multipart form parsing so that client mistakes are +//! surfaced as bad requests. + #![cfg(all(feature = "axum", feature = "multipart"))] use axum::extract::multipart::MultipartError; -use crate::AppError; +use crate::{AppError, AppErrorKind}; impl From for AppError { fn from(err: MultipartError) -> Self { - AppError::bad_request(format!("Multipart error: {err}")) + AppError::with(AppErrorKind::BadRequest, format!("Multipart error: {err}")) + } +} + +#[cfg(all(test, feature = "axum", feature = "multipart"))] +mod tests { + use axum::{ + body::Body, + extract::{FromRequest, multipart::Multipart}, + http::Request + }; + + use crate::{AppError, AppErrorKind}; + + #[tokio::test] + async fn multipart_error_maps_to_bad_request() { + let boundary = "XBOUNDARY"; + let request = Request::builder() + .header( + "content-type", + format!("multipart/form-data; boundary={boundary}") + ) + .body(Body::from("not-a-multipart-body")) + .expect("request"); + + let mut multipart = Multipart::from_request(request, &()) + .await + .expect("extractor"); + + let err = multipart.next_field().await.expect_err("error"); + let expected = format!("Multipart error: {err}"); + let app_err: AppError = err.into(); + + assert_eq!(app_err.kind, AppErrorKind::BadRequest); + assert_eq!(app_err.message.as_deref(), Some(expected.as_str())); } }