From aca264942d8509e87c8ba7dfc4e426828176e886 Mon Sep 17 00:00:00 2001 From: zhoukq Date: Sun, 1 Sep 2024 18:48:11 +0800 Subject: [PATCH] Update Content-Length if body changed by client interceptor Prior to this commit, the HTTP interceptor model used for `RestTemplate` and `RestClient` would not update the "Content-Length" request header, even when the request body had been updated by a `ClientHttpRequestInterceptor`. Even though this is the `ClientHttpRequestInterceptor`'s responsibility (along with the content type and encoding changes if needed), this would result in invalid requests. This invalid situation can be detected by `InterceptingClientHttpRequest`. This commit ensures that such situations are detected and fixed automatically by setting the Content-Length header to the actual body size, right before executing the actual request, after all interceptors are done. Closes gh-33459 --- .../http/client/InterceptingClientHttpRequest.java | 4 ++++ .../client/InterceptingClientHttpRequestFactoryTests.java | 1 + 2 files changed, 5 insertions(+) diff --git a/spring-web/src/main/java/org/springframework/http/client/InterceptingClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/InterceptingClientHttpRequest.java index 07203df3710..84ee77f3d70 100644 --- a/spring-web/src/main/java/org/springframework/http/client/InterceptingClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/InterceptingClientHttpRequest.java @@ -93,6 +93,10 @@ class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest { request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value)); request.getAttributes().forEach((key, value) -> delegate.getAttributes().put(key, value)); if (body.length > 0) { + long contentLength = delegate.getHeaders().getContentLength(); + if (contentLength > -1 && contentLength != body.length) { + delegate.getHeaders().setContentLength(body.length); + } if (delegate instanceof StreamingHttpOutputMessage streamingOutputMessage) { streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { @Override diff --git a/spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java index 2735c00e315..f8248d0e085 100644 --- a/spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/InterceptingClientHttpRequestFactoryTests.java @@ -204,6 +204,7 @@ class InterceptingClientHttpRequestFactoryTests { ClientHttpRequest request = requestFactory.createRequest(URI.create("https://example.com"), HttpMethod.GET); request.execute(); assertThat(Arrays.equals(changedBody, requestMock.getBodyAsBytes())).isTrue(); + assertThat(requestMock.getHeaders().getContentLength()).isEqualTo(changedBody.length); }