From b159d656cc87a91822c84e104d66f31b79966232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=AD=A3=E8=B6=85?= Date: Thu, 7 May 2026 17:51:09 +0800 Subject: [PATCH] test(admin): cover POST content length compat layer (#2844) Co-authored-by: houseme --- rustfs/src/server/layer.rs | 51 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/rustfs/src/server/layer.rs b/rustfs/src/server/layer.rs index c24e52518..d36672594 100644 --- a/rustfs/src/server/layer.rs +++ b/rustfs/src/server/layer.rs @@ -232,11 +232,12 @@ pub struct AdminChunkedContentLengthCompatService { inner: S, } -impl Service> for AdminChunkedContentLengthCompatService +impl Service> for AdminChunkedContentLengthCompatService where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, S::Error: Into> + Send + 'static, + ReqBody: Send + 'static, ResBody: Send + 'static, { type Response = Response; @@ -247,7 +248,7 @@ where self.inner.poll_ready(cx).map_err(Into::into) } - fn call(&mut self, mut req: HttpRequest) -> Self::Future { + fn call(&mut self, mut req: HttpRequest) -> Self::Future { if should_force_zero_content_length_for_admin_empty_body(&req) { req.headers_mut() .insert(http::header::CONTENT_LENGTH, HeaderValue::from_static("0")); @@ -933,6 +934,7 @@ mod tests { use http_body_util::BodyExt; use http_body_util::Full; use std::convert::Infallible; + use std::sync::Mutex; use temp_env::with_var; #[derive(Clone, Debug)] @@ -952,6 +954,32 @@ mod tests { } } + #[derive(Clone, Default)] + struct HeaderCaptureService { + headers: Arc>>, + } + + impl HeaderCaptureService { + fn headers(&self) -> Arc>> { + Arc::clone(&self.headers) + } + } + + impl Service> for HeaderCaptureService { + type Response = Response>; + type Error = Infallible; + type Future = Ready>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Request) -> Self::Future { + *self.headers.lock().expect("capture headers") = Some(req.headers().clone()); + ready(Ok(Response::new(Full::from(Bytes::new())))) + } + } + #[test] fn admin_chunked_put_without_content_length_is_normalized() { let request = Request::builder() @@ -986,6 +1014,23 @@ mod tests { } } + #[tokio::test] + async fn admin_empty_body_post_layer_inserts_zero_content_length() { + let capture = HeaderCaptureService::default(); + let headers = capture.headers(); + let mut service = AdminChunkedContentLengthCompatLayer.layer(capture); + let request = Request::builder() + .method(Method::POST) + .uri("/rustfs/admin/v3/rebalance/start") + .body(()) + .expect("request"); + + let _ = service.call(request).await.expect("service call"); + + let headers = headers.lock().expect("captured headers").take().expect("captured headers"); + assert_eq!(headers.get(http::header::CONTENT_LENGTH).unwrap(), "0"); + } + #[test] fn admin_request_with_explicit_content_length_is_left_unchanged() { let request = Request::builder()