Merge 2.x into 3.0
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
index 838ca4b..ae46be8 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
@@ -494,7 +494,7 @@
* </p>
* @since 2.43
*/
- public static final String SNI_HOST_NAME = "jersey.config.client.snihostname";
+ public static final String SNI_HOST_NAME = "jersey.config.client.sniHostName";
/**
* <p>The {@link javax.net.ssl.SSLContext} {@link java.util.function.Supplier} to be used to set ssl context in the current
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
index 65cb5f1..49fc03c 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
@@ -18,6 +18,7 @@
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.http.HttpHeaders;
import org.glassfish.jersey.internal.PropertiesResolver;
import javax.net.ssl.SSLEngine;
@@ -29,6 +30,7 @@
import java.net.URI;
import java.net.UnknownHostException;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
@@ -44,11 +46,11 @@
* Builder of the {@link SSLParamConfigurator} instance.
*/
public static final class Builder {
- private ClientRequest clientRequest;
private URI uri;
- private Map<String, List<Object>> httpHeaders;
- private boolean setAlways = false;
+ private String sniHostNameHeader = null;
private String sniHostPrecedence = null;
+ private boolean setAlways = false;
+
/**
* Sets the {@link ClientRequest} instance.
@@ -56,9 +58,19 @@
* @return the builder instance
*/
public Builder request(ClientRequest clientRequest) {
- this.clientRequest = clientRequest;
- this.httpHeaders = null;
- this.uri = null;
+ this.sniHostNameHeader = getSniHostNameHeader(clientRequest.getHeaders());
+ this.sniHostPrecedence = resolveSniHostNameProperty(clientRequest);
+ this.uri = clientRequest.getUri();
+ return this;
+ }
+
+ /**
+ * Sets the SNIHostName from the {@link Configuration} instance.
+ * @param configuration the {@link Configuration}
+ * @return the builder instance
+ */
+ public Builder configuration(Configuration configuration) {
+ this.sniHostPrecedence = getSniHostNameProperty(configuration);
return this;
}
@@ -68,7 +80,6 @@
* @return the builder instance
*/
public Builder uri(URI uri) {
- this.clientRequest = null;
this.uri = uri;
return this;
}
@@ -79,8 +90,7 @@
* @return the builder instance
*/
public Builder headers(Map<String, List<Object>> httpHeaders) {
- this.clientRequest = null;
- this.httpHeaders = httpHeaders;
+ this.sniHostNameHeader = getSniHostNameHeader(httpHeaders);
return this;
}
@@ -129,7 +139,7 @@
* @return the builder instance.
*/
public Builder setSNIHostName(Configuration configuration) {
- return setSNIHostName((String) configuration.getProperty(ClientProperties.SNI_HOST_NAME));
+ return setSNIHostName(getSniHostNameProperty(configuration));
}
/**
@@ -148,7 +158,7 @@
* @return the builder instance.
*/
public Builder setSNIHostName(PropertiesResolver resolver) {
- return setSNIHostName(resolver.resolveProperty(ClientProperties.SNI_HOST_NAME, String.class));
+ return setSNIHostName(resolveSniHostNameProperty(resolver));
}
/**
@@ -158,14 +168,38 @@
public SSLParamConfigurator build() {
return new SSLParamConfigurator(this);
}
+
+ private static String getSniHostNameHeader(Map<String, List<Object>> httpHeaders) {
+ List<Object> hostHeaders = httpHeaders.get(HttpHeaders.HOST);
+ if (hostHeaders == null || hostHeaders.get(0) == null) {
+ return null;
+ }
+
+ final String hostHeader = hostHeaders.get(0).toString();
+ return hostHeader;
+ }
+
+ private static String resolveSniHostNameProperty(PropertiesResolver resolver) {
+ String property = resolver.resolveProperty(ClientProperties.SNI_HOST_NAME, String.class);
+ if (property == null) {
+ property = resolver.resolveProperty(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT), String.class);
+ }
+ return property;
+ }
+
+ private static String getSniHostNameProperty(Configuration configuration) {
+ Object property = configuration.getProperty(ClientProperties.SNI_HOST_NAME);
+ if (property == null) {
+ property = configuration.getProperty(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT));
+ }
+ return (String) property;
+ }
}
private SSLParamConfigurator(SSLParamConfigurator.Builder builder) {
- final Map<String, List<Object>> httpHeaders =
- builder.clientRequest != null ? builder.clientRequest.getHeaders() : builder.httpHeaders;
- this.uri = builder.clientRequest != null ? builder.clientRequest.getUri() : builder.uri;
+ uri = builder.uri;
if (builder.sniHostPrecedence == null) {
- sniConfigurator = SniConfigurator.createWhenHostHeader(uri, httpHeaders, builder.setAlways);
+ sniConfigurator = SniConfigurator.createWhenHostHeader(uri, builder.sniHostNameHeader, builder.setAlways);
} else {
// Do not set SNI always, the property can be used to turn the SNI off
sniConfigurator = SniConfigurator.createWhenHostHeader(uri, builder.sniHostPrecedence, false);
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
index 59c8422..cb1d937 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
@@ -51,24 +51,6 @@
}
/**
- * Create {@link SniConfigurator} when {@link HttpHeaders#HOST} is set different from the request URI host
- * (or {@code whenDiffer}.is false).
- * @param hostUri the Uri of the HTTP request
- * @param headers the HttpHeaders
- * @param whenDiffer create {@SniConfigurator only when different from the request URI host}
- * @return Optional {@link SniConfigurator} or empty when {@link HttpHeaders#HOST} is equal to the requestHost
- */
- static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, Map<String, List<Object>> headers, boolean whenDiffer) {
- List<Object> hostHeaders = headers.get(HttpHeaders.HOST);
- if (hostHeaders == null || hostHeaders.get(0) == null) {
- return Optional.empty();
- }
-
- final String hostHeader = hostHeaders.get(0).toString();
- return createWhenHostHeader(hostUri, hostHeader, whenDiffer);
- }
-
- /**
* Create {@link SniConfigurator} when {@code sniHost} is set different from the request URI host
* (or {@code whenDiffer}.is false).
* @param hostUri the Uri of the HTTP request
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java
new file mode 100644
index 0000000..06dcdec
--- /dev/null
+++ b/core-client/src/test/java/org/glassfish/jersey/client/innate/http/SSLParamConfiguratorTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.http;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.ClientRequest;
+import org.glassfish.jersey.client.JerseyClient;
+import org.glassfish.jersey.http.HttpHeaders;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class SSLParamConfiguratorTest {
+ @Test
+ public void testNoHost() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(false));
+ }
+
+ @Test
+ public void testHostHeaderHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "yyy.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testPropertyOnClientHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testPropertyOnDelegateHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "zzz.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("zzz.com"));
+ }
+
+ @Test
+ public void testPropertyOnDelegateHasPrecedenceOverHost() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "zzz.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("zzz.com"));
+ }
+
+ @Test
+ public void testDisableSni() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ delegate.setProperty(ClientProperties.SNI_HOST_NAME, "xxx.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(false));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("xxx.com"));
+ }
+
+ @Test
+ public void testLowerCasePropertyOnClientHasPrecedence() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ final ClientConfig config = client.getConfiguration();
+ final PropertiesDelegate delegate = new MapPropertiesDelegate();
+ client.property(ClientProperties.SNI_HOST_NAME.toLowerCase(Locale.ROOT), "yyy.com");
+ ClientRequest request = new ClientRequest(uri, config, delegate) {};
+ request.getHeaders().add(HttpHeaders.HOST, "www.com");
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder().request(request).build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+
+ @Test
+ public void testUriAndHeadersAndConfig() {
+ final URI uri = URI.create("http://xxx.com:8080");
+ final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
+ Map<String, List<Object>> httpHeaders = new MultivaluedHashMap<>();
+ httpHeaders.put(HttpHeaders.HOST, Collections.singletonList("www.com"));
+ SSLParamConfigurator configurator = SSLParamConfigurator.builder()
+ .uri(uri)
+ .headers(httpHeaders)
+ .configuration(client.getConfiguration())
+ .build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("www.com"));
+
+ client.property(ClientProperties.SNI_HOST_NAME, "yyy.com");
+ configurator = SSLParamConfigurator.builder()
+ .uri(uri)
+ .headers(httpHeaders)
+ .configuration(client.getConfiguration())
+ .build();
+ MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
+ MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
+ }
+}
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml
index 5f2d0a4..b1a04c9 100644
--- a/docs/src/main/docbook/appendix-properties.xml
+++ b/docs/src/main/docbook/appendix-properties.xml
@@ -1132,7 +1132,7 @@
</row>
<row>
<entry>&jersey.client.ClientProperties.SNI_HOST_NAME; (Jersey 2.43 or later)</entry>
- <entry><literal>jersey.config.client.snihostname</literal></entry>
+ <entry><literal>jersey.config.client.sniHostName</literal></entry>
<entry>
<para>
Sets the host name to be used for calculating the <literal>javax.net.ssl.SNIHostName</literal>