GH-9489: Remove Content-Length HTTP before sending GET request
Fixes: #9489
Issue link: https://github.com/spring-projects/spring-integration/issues/9489
If request message has a `Content-Length` HTTP, it is still mapped to the target HTTP request
even if that one is indicated as "no-body" (`GET`, `HEAD`, `TRACE`).
In this case Netty fails to decode such a missed body with error:
```
java.lang.IllegalArgumentException: text is empty (possibly HTTP/0.9)), version: HTTP/1.0
```
* Since `Content-Length` is not supposed to be supported for those methods,
remove it altogether from the HTTP request headers
* Add nullability API into the `org.springframework.integration.http.outbound`
* Check received HTTP request on the server side that it does not have such a header for `GET`
(cherry picked from commit 891dca7179)
This commit is contained in:
committed by
Spring Builds
parent
5d65797395
commit
31090da79a
@@ -32,6 +32,7 @@ import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferLimitException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
@@ -95,6 +96,47 @@ class WebFluxRequestExecutingMessageHandlerTests {
|
||||
.verify(Duration.ofSeconds(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noContentLengthHeaderForGetMethod() {
|
||||
ClientHttpConnector httpConnector =
|
||||
new HttpHandlerConnector((request, response) -> {
|
||||
assertThat(request.getHeaders())
|
||||
.doesNotContainKey(org.springframework.http.HttpHeaders.CONTENT_LENGTH);
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return Mono.defer(response::setComplete);
|
||||
});
|
||||
|
||||
WebClient webClient = WebClient.builder()
|
||||
.clientConnector(httpConnector)
|
||||
.build();
|
||||
|
||||
String destinationUri = "https://www.springsource.org/spring-integration";
|
||||
WebFluxRequestExecutingMessageHandler reactiveHandler =
|
||||
new WebFluxRequestExecutingMessageHandler(destinationUri, webClient);
|
||||
reactiveHandler.setHttpMethod(HttpMethod.GET);
|
||||
|
||||
FluxMessageChannel ackChannel = new FluxMessageChannel();
|
||||
reactiveHandler.setOutputChannel(ackChannel);
|
||||
String testPayload = "hello, world";
|
||||
Message<?> testMessage =
|
||||
MessageBuilder.withPayload(testPayload)
|
||||
.setHeader(org.springframework.http.HttpHeaders.CONTENT_LENGTH, testPayload.length())
|
||||
.build();
|
||||
reactiveHandler.handleMessage(testMessage);
|
||||
reactiveHandler.handleMessage(testMessage);
|
||||
|
||||
StepVerifier.create(ackChannel, 2)
|
||||
.assertNext(m ->
|
||||
assertThat(m.getHeaders())
|
||||
.containsEntry(HttpHeaders.STATUS_CODE, HttpStatus.OK)
|
||||
// The reply message headers are copied from the request message
|
||||
.containsEntry(org.springframework.http.HttpHeaders.CONTENT_LENGTH, testPayload.length()))
|
||||
.assertNext(m -> assertThat(m.getHeaders()).containsEntry(HttpHeaders.STATUS_CODE, HttpStatus.OK))
|
||||
.expectNoEvent(Duration.ofMillis(100))
|
||||
.thenCancel()
|
||||
.verify(Duration.ofSeconds(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReactiveErrorOneWay() {
|
||||
ClientHttpConnector httpConnector =
|
||||
|
||||
Reference in New Issue
Block a user