Browse Source

Use HTTP methods in JdkClientHttpRequest when possible

Prior to this commit, we would use the
`java.net.http.HttpRequest.Builder#method(String, BodyPublisher)` to
create HTTP requests for the JDK HttpClient. This method requires a
non-null body publisher; providing an empty publisher writes a
"Content-Length: 0" header to all requests.

As of Java 19, this behavior changes for `HttpRequest.Builder#GET` and
similar methods, where the body publisher is considered as null and no
"Content-Length" header is written.

This commit aligns with this behavior and favors dedicated HTTP methods
whenever available.`

Closes gh-34971
pull/35405/head
Brian Clozel 7 months ago
parent
commit
659472f9e3
  1. 11
      spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java
  2. 23
      spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java

11
spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java

@ -149,7 +149,16 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
} }
}); });
builder.method(this.method.name(), bodyPublisher(headers, body)); switch (this.method.name()) {
case "GET" :
builder.GET();
break;
case "DELETE" :
builder.DELETE();
break;
default :
builder.method(this.method.name(), bodyPublisher(headers, body));
}
return builder.build(); return builder.build();
} }

23
spring-web/src/test/java/org/springframework/http/client/JdkClientHttpRequestFactoryTests.java

@ -18,15 +18,19 @@ package org.springframework.http.client;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode; import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -34,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link JdkClientHttpRequestFactory}. * Tests for {@link JdkClientHttpRequestFactory}.
* *
* @author Marten Deinum * @author Marten Deinum
* @author Brian Clozel
*/ */
class JdkClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTests { class JdkClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTests {
@ -88,4 +93,22 @@ class JdkClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTests {
} }
} }
@Test // gh-34971
@EnabledForJreRange(min = JRE.JAVA_19) // behavior fixed in Java 19
void requestContentLengthHeader() throws Exception {
URI uri = URI.create(baseUrl + "/header/Content-Length");
assertNoContentLength(uri, HttpMethod.GET);
assertNoContentLength(uri, HttpMethod.DELETE);
}
protected void assertNoContentLength(URI uri, HttpMethod method) throws Exception {
ClientHttpRequest request = factory.createRequest(uri, method);
try (ClientHttpResponse response = request.execute()) {
assertThat(response.getStatusCode()).as("Invalid response status").isEqualTo(HttpStatus.OK);
assertThat(StreamUtils.copyToString(response.getBody(), StandardCharsets.ISO_8859_1))
.as("Invalid Content-Length request header").isEqualTo("Content-Length:null");
}
}
} }

Loading…
Cancel
Save