test(admin): cover POST content length compat layer (#2844)

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
安正超
2026-05-07 17:51:09 +08:00
committed by GitHub
parent b7815b0694
commit b159d656cc
+48 -3
View File
@@ -232,11 +232,12 @@ pub struct AdminChunkedContentLengthCompatService<S> {
inner: S,
}
impl<S, ResBody> Service<HttpRequest<Incoming>> for AdminChunkedContentLengthCompatService<S>
impl<S, ReqBody, ResBody> Service<HttpRequest<ReqBody>> for AdminChunkedContentLengthCompatService<S>
where
S: Service<HttpRequest<Incoming>, Response = Response<ResBody>> + Clone + Send + 'static,
S: Service<HttpRequest<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
S::Future: Send + 'static,
S::Error: Into<Box<dyn std::error::Error + Send + Sync>> + Send + 'static,
ReqBody: Send + 'static,
ResBody: Send + 'static,
{
type Response = Response<ResBody>;
@@ -247,7 +248,7 @@ where
self.inner.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, mut req: HttpRequest<Incoming>) -> Self::Future {
fn call(&mut self, mut req: HttpRequest<ReqBody>) -> 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<Mutex<Option<HeaderMap>>>,
}
impl HeaderCaptureService {
fn headers(&self) -> Arc<Mutex<Option<HeaderMap>>> {
Arc::clone(&self.headers)
}
}
impl<B: Send + 'static> Service<Request<B>> for HeaderCaptureService {
type Response = Response<Full<Bytes>>;
type Error = Infallible;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request<B>) -> 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()