@ -25,7 +25,9 @@ import java.net.http.HttpRequest;
@@ -25,7 +25,9 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse ;
import java.nio.ByteBuffer ;
import java.time.Duration ;
import java.util.List ;
import java.util.Collections ;
import java.util.Set ;
import java.util.TreeSet ;
import java.util.concurrent.Executor ;
import java.util.concurrent.Flow ;
@ -33,6 +35,7 @@ import org.springframework.http.HttpHeaders;
@@ -33,6 +35,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod ;
import org.springframework.lang.Nullable ;
import org.springframework.util.StreamUtils ;
import org.springframework.util.StringUtils ;
/ * *
* { @link ClientHttpRequest } implementation based the Java { @link HttpClient } .
@ -44,12 +47,27 @@ import org.springframework.util.StreamUtils;
@@ -44,12 +47,27 @@ import org.springframework.util.StreamUtils;
* /
class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
/ *
* The JDK HttpRequest doesn ' t allow all headers to be set . The named headers are taken from the default
* implementation for HttpRequest .
private static final Set < String > DISALLOWED_HEADERS = disallowedHeaders ( ) ;
/ * *
* By default , { @link HttpRequest } does not allow { @code Connection } ,
* { @code Content - Length } , { @code Expect } , { @code Host } , or { @code Upgrade }
* headers to be set , but this can be overriden with the
* { @code jdk . httpclient . allowRestrictedHeaders } system property .
* @see jdk . internal . net . http . common . Utils # getDisallowedHeaders ( )
* /
private static final List < String > DISALLOWED_HEADERS =
List . of ( "connection" , "content-length" , "expect" , "host" , "upgrade" ) ;
private static Set < String > disallowedHeaders ( ) {
TreeSet < String > headers = new TreeSet < > ( String . CASE_INSENSITIVE_ORDER ) ;
headers . addAll ( Set . of ( "connection" , "content-length" , "expect" , "host" , "upgrade" ) ) ;
String headersToAllow = System . getProperty ( "jdk.httpclient.allowRestrictedHeaders" ) ;
if ( headersToAllow ! = null ) {
Set < String > toAllow = StringUtils . commaDelimitedListToSet ( headersToAllow ) ;
headers . removeAll ( toAllow ) ;
}
return Collections . unmodifiableSet ( headers ) ;
}
private final HttpClient httpClient ;
@ -109,11 +127,9 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
@@ -109,11 +127,9 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
}
headers . forEach ( ( headerName , headerValues ) - > {
if ( ! headerName . equalsIgnoreCase ( HttpHeaders . CONTENT_LENGTH ) ) {
if ( ! DISALLOWED_HEADERS . contains ( headerName . toLowerCase ( ) ) ) {
for ( String headerValue : headerValues ) {
builder . header ( headerName , headerValue ) ;
}
if ( ! DISALLOWED_HEADERS . contains ( headerName . toLowerCase ( ) ) ) {
for ( String headerValue : headerValues ) {
builder . header ( headerName , headerValue ) ;
}
}
} ) ;