Skip to content

Commit 9900575

Browse files
spencergibbpoutsma
authored andcommitted
Allow customization of disallowed JdkClientHttpRequest headers
By default, the JDK HttpClient's HttpRequest does not allow Connection, Content-Length, Expect, Host, or Upgrade headers to be set, but this can be overriden with the `jdk.httpclient.allowRestrictedHeaders` system property. See https://bugs.openjdk.org/browse/JDK-8213696 Closes gh-30787
1 parent 2ed10f1 commit 9900575

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
import java.net.http.HttpResponse;
2626
import java.nio.ByteBuffer;
2727
import java.time.Duration;
28-
import java.util.List;
28+
import java.util.Collections;
29+
import java.util.Set;
30+
import java.util.TreeSet;
2931
import java.util.concurrent.Executor;
3032
import java.util.concurrent.Flow;
3133

3234
import org.springframework.http.HttpHeaders;
3335
import org.springframework.http.HttpMethod;
3436
import org.springframework.lang.Nullable;
3537
import org.springframework.util.StreamUtils;
38+
import org.springframework.util.StringUtils;
3639

3740
/**
3841
* {@link ClientHttpRequest} implementation based the Java {@link HttpClient}.
@@ -48,8 +51,19 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
4851
* The JDK HttpRequest doesn't allow all headers to be set. The named headers are taken from the default
4952
* implementation for HttpRequest.
5053
*/
51-
private static final List<String> DISALLOWED_HEADERS =
52-
List.of("connection", "content-length", "expect", "host", "upgrade");
54+
protected static final Set<String> DISALLOWED_HEADERS = getDisallowedHeaders();
55+
56+
private static Set<String> getDisallowedHeaders() {
57+
TreeSet<String> headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
58+
headers.addAll(Set.of("connection", "content-length", "expect", "host", "upgrade"));
59+
60+
String headersToAllow = System.getProperty("jdk.httpclient.allowRestrictedHeaders");
61+
if (headersToAllow != null) {
62+
Set<String> toAllow = StringUtils.commaDelimitedListToSet(headersToAllow);
63+
headers.removeAll(toAllow);
64+
}
65+
return Collections.unmodifiableSet(headers);
66+
}
5367

5468
private final HttpClient httpClient;
5569

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@
1616

1717
package org.springframework.http.client;
1818

19+
import java.net.URI;
20+
import java.net.http.HttpClient;
21+
import java.time.Duration;
22+
import java.util.concurrent.Executor;
23+
1924
import org.junit.jupiter.api.Test;
2025

2126
import org.springframework.http.HttpMethod;
2227

28+
import static org.assertj.core.api.Assertions.assertThat;
29+
2330
/**
2431
* @author Marten Deinum
2532
*/
@@ -37,4 +44,26 @@ public void httpMethods() throws Exception {
3744
assertHttpMethod("patch", HttpMethod.PATCH);
3845
}
3946

47+
@Test
48+
public void customizeDisallowedHeaders() {
49+
String original = System.getProperty("jdk.httpclient.allowRestrictedHeaders");
50+
System.setProperty("jdk.httpclient.allowRestrictedHeaders", "host");
51+
52+
assertThat(TestJdkClientHttpRequest.DISALLOWED_HEADERS).doesNotContain("host");
53+
54+
if (original != null) {
55+
System.setProperty("jdk.httpclient.allowRestrictedHeaders", original);
56+
}
57+
else {
58+
System.clearProperty("jdk.httpclient.allowRestrictedHeaders");
59+
}
60+
}
61+
62+
static class TestJdkClientHttpRequest extends JdkClientHttpRequest {
63+
64+
public TestJdkClientHttpRequest(HttpClient httpClient, URI uri, HttpMethod method, Executor executor, Duration readTimeout) {
65+
super(httpClient, uri, method, executor, readTimeout);
66+
}
67+
}
68+
4069
}

0 commit comments

Comments
 (0)