From e58b166f0eb02d492431819953fa9e19d99b2585 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 27 Dec 2024 23:36:21 +0100 Subject: [PATCH] axum-extra/multipart: Use rejection macros for `MultipartRejection` (#3123) --- axum-extra/src/extract/multipart.rs | 103 ++++------------------------ 1 file changed, 14 insertions(+), 89 deletions(-) diff --git a/axum-extra/src/extract/multipart.rs b/axum-extra/src/extract/multipart.rs index bcfae64eee..2fb5e400c7 100644 --- a/axum-extra/src/extract/multipart.rs +++ b/axum-extra/src/extract/multipart.rs @@ -8,6 +8,8 @@ use axum::{ response::{IntoResponse, Response}, RequestExt, }; +use axum_core::__composite_rejection as composite_rejection; +use axum_core::__define_rejection as define_rejection; use futures_util::stream::Stream; use http::{ header::{HeaderMap, CONTENT_TYPE}, @@ -313,100 +315,23 @@ fn parse_boundary(headers: &HeaderMap) -> Option { multer::parse_boundary(content_type).ok() } -/// Rejection used for [`Multipart`]. -/// -/// Contains one variant for each way the [`Multipart`] extractor can fail. -#[derive(Debug)] -#[non_exhaustive] -pub enum MultipartRejection { - #[allow(missing_docs)] - InvalidBoundary(InvalidBoundary), -} - -impl IntoResponse for MultipartRejection { - fn into_response(self) -> Response { - match self { - Self::InvalidBoundary(inner) => inner.into_response(), - } - } -} - -impl MultipartRejection { - /// Get the response body text used for this rejection. - pub fn body_text(&self) -> String { - match self { - Self::InvalidBoundary(inner) => inner.body_text(), - } - } - - /// Get the status code used for this rejection. - pub fn status(&self) -> http::StatusCode { - match self { - Self::InvalidBoundary(inner) => inner.status(), - } - } -} - -impl From for MultipartRejection { - fn from(inner: InvalidBoundary) -> Self { - Self::InvalidBoundary(inner) - } -} - -impl std::fmt::Display for MultipartRejection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::InvalidBoundary(inner) => write!(f, "{}", inner.body_text()), - } - } -} - -impl std::error::Error for MultipartRejection { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::InvalidBoundary(inner) => Some(inner), - } - } -} - -/// Rejection type used if the `boundary` in a `multipart/form-data` is -/// missing or invalid. -#[derive(Debug, Default)] -#[non_exhaustive] -pub struct InvalidBoundary; - -impl IntoResponse for InvalidBoundary { - fn into_response(self) -> Response { - let body = self.body_text(); - axum_core::__log_rejection!( - rejection_type = Self, - body_text = body, - status = self.status(), - ); - (self.status(), body).into_response() - } -} - -impl InvalidBoundary { - /// Get the response body text used for this rejection. - pub fn body_text(&self) -> String { - "Invalid `boundary` for `multipart/form-data` request".into() - } - - /// Get the status code used for this rejection. - pub fn status(&self) -> http::StatusCode { - http::StatusCode::BAD_REQUEST +composite_rejection! { + /// Rejection used for [`Multipart`]. + /// + /// Contains one variant for each way the [`Multipart`] extractor can fail. + pub enum MultipartRejection { + InvalidBoundary, } } -impl std::fmt::Display for InvalidBoundary { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.body_text()) - } +define_rejection! { + #[status = BAD_REQUEST] + #[body = "Invalid `boundary` for `multipart/form-data` request"] + /// Rejection type used if the `boundary` in a `multipart/form-data` is + /// missing or invalid. + pub struct InvalidBoundary; } -impl std::error::Error for InvalidBoundary {} - #[cfg(test)] mod tests { use super::*;