From 4ff17676d3827fdef46f2d0e3243696730faea64 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 13 Feb 2017 21:00:46 +0100 Subject: [PATCH] Avoid duplicate Content-Length headers in Netty client This commit checks that a "Content-Length" request header isn't already present before adding one in `Netty4ClientHttpRequestFactory`. `HttpMessageConverter` implementations can write that request header so the Netty request factory should only write that value when the header is missing. If that header is not written (and since we're not dealing with the HTTP exchange in a chunked-based fashion), the HTTP client might not send the request body at all. Issue: SPR-15241 --- .../http/client/Netty4ClientHttpRequest.java | 10 +++++----- .../web/client/AbstractMockWebServerTestCase.java | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java index 24e773aadaf..7f7e32c9d5b 100644 --- a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,14 +137,14 @@ class Netty4ClientHttpRequest extends AbstractAsyncClientHttpRequest implements HttpVersion.HTTP_1_1, nettyMethod, path, this.body.buffer()); nettyRequest.headers().set(HttpHeaders.HOST, this.uri.getHost()); - if (this.body.buffer().readableBytes() > 0) { - nettyRequest.headers().set(HttpHeaders.CONTENT_LENGTH, this.body.buffer().readableBytes()); - } nettyRequest.headers().set(HttpHeaders.CONNECTION, "close"); - for (Map.Entry> entry : headers.entrySet()) { nettyRequest.headers().add(entry.getKey(), entry.getValue()); } + if (!nettyRequest.headers().contains(HttpHeaders.CONTENT_LENGTH) + && this.body.buffer().readableBytes() > 0) { + nettyRequest.headers().set(HttpHeaders.CONTENT_LENGTH, this.body.buffer().readableBytes()); + } return nettyRequest; } diff --git a/spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTestCase.java b/spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTestCase.java index 4c58bbb7aa2..4f0bf95b758 100644 --- a/spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTestCase.java +++ b/spring-web/src/test/java/org/springframework/web/client/AbstractMockWebServerTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,6 +85,7 @@ public class AbstractMockWebServerTestCase { private MockResponse postRequest(RecordedRequest request, String expectedRequestContent, String location, String contentType, byte[] responseBody) { + assertEquals(1, request.getHeaders().values("Content-Length").size()); assertTrue("Invalid request content-length", Integer.parseInt(request.getHeader("Content-Length")) > 0); String requestContentType = request.getHeader("Content-Type");