HTTP/2 for JNH connector
Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java
index a964200..a9c0248 100644
--- a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpClientProperties.java
@@ -86,6 +86,17 @@
"jersey.config.jnh.client.disableCookies";
/**
+ * HTTP version - if null or instance of HttpClient.Version.HTTP_1_1 the version will be set to HTTP_1_1
+ * if version is HttpClient.Version.HTTP_2 the client will attempt to perform each request using HTTP_2 protocol
+ * but if not supported by server, the protocol will be still HTTP_1_1
+ *
+ * @since 3.1.4
+ */
+ public static final String HTTP_VERSION =
+ "jersey.config.jnh.client.httpVersion";
+
+
+ /**
* Prevent this class from instantiation.
*/
private JavaNetHttpClientProperties() {}
diff --git a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
index fb0f613..69d25eb 100644
--- a/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
+++ b/connectors/jnh-connector/src/main/java/org/glassfish/jersey/jnh/connector/JavaNetHttpConnector.java
@@ -83,8 +83,10 @@
* @param configuration the configuration properties for this connector
*/
public JavaNetHttpConnector(final Client client, final Configuration configuration) {
- HttpClient.Builder httpClientBuilder = HttpClient.newBuilder();
- httpClientBuilder.version(HttpClient.Version.HTTP_1_1);
+ final HttpClient.Builder httpClientBuilder = HttpClient.newBuilder();
+ final HttpClient.Version version =
+ getPropertyOrNull(configuration, JavaNetHttpClientProperties.HTTP_VERSION, HttpClient.Version.class);
+ httpClientBuilder.version(version == null ? HttpClient.Version.HTTP_1_1 : version);
SSLContext sslContext = client.getSslContext();
if (sslContext != null) {
httpClientBuilder.sslContext(sslContext);
@@ -230,6 +232,9 @@
if (propertyObject == null) {
return null;
}
+ if (resultClass.isEnum() && propertyObject instanceof String) {
+ return (T) Enum.valueOf(resultClass.asSubclass(Enum.class), (String) propertyObject);
+ }
if (!resultClass.isInstance(propertyObject)) {
LOGGER.warning(LocalizationMessages.ERROR_INVALID_CLASS(propertyKey, resultClass.getName()));
return null;
diff --git a/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java
new file mode 100644
index 0000000..a2eaa3b
--- /dev/null
+++ b/connectors/jnh-connector/src/test/java/org/glassfish/jersey/jnh/connector/Http2PresenceTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 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.jnh.connector;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.Test;
+
+import java.net.http.HttpClient;
+import java.util.List;
+import java.util.logging.Logger;
+
+import static java.net.http.HttpClient.Version.HTTP_2;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests the HTTP2 presence.
+ *
+ */
+public class Http2PresenceTest extends JerseyTest {
+
+ private static final Logger LOGGER = Logger.getLogger(Http2PresenceTest.class.getName());
+
+ @Path("/test")
+ public static class HttpMethodResource {
+
+ @GET
+ public String testUserAgent(@Context HttpHeaders httpHeaders) {
+ final List<String> requestHeader = httpHeaders.getRequestHeader(HttpHeaders.USER_AGENT);
+ if (requestHeader.size() != 1) {
+ return "FAIL";
+ }
+ return requestHeader.get(0);
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
+ config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
+ return config;
+ }
+
+ @Override
+ protected void configureClient(ClientConfig config) {
+ config.property(JavaNetHttpClientProperties.HTTP_VERSION, HTTP_2).connectorProvider(new JavaNetHttpConnectorProvider());
+ }
+
+ @Test
+ public void testHttp2Presence() {
+ final ConnectorProvider provider = ((ClientConfig) target().getConfiguration()).getConnectorProvider();
+ assertTrue(provider instanceof JavaNetHttpConnectorProvider);
+
+ final HttpClient client = ((JavaNetHttpConnectorProvider) provider).getHttpClient(target());
+ assertEquals(HTTP_2, client.version());
+ }
+
+ /**
+ * Test, that {@code User-agent} header is as set by Jersey, not by underlying Jetty client.
+ */
+ @Test
+ public void testUserAgent() {
+ String response = target().path("test").request().get(String.class);
+ assertTrue(response.startsWith("Jersey"), "User-agent header should start with 'Jersey', but was " + response);
+ }
+}
\ No newline at end of file
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml
index d8dad09..78bfb96 100644
--- a/docs/src/main/docbook/appendix-properties.xml
+++ b/docs/src/main/docbook/appendix-properties.xml
@@ -2119,6 +2119,24 @@
</para>
</entry>
</row>
+ <row>
+ <entry>&jersey.jnh.JavaNetHttpClientProperties.HTTP_VERSION;</entry>
+ <entry><literal>jersey.config.jnh.client.httpVersion</literal></entry>
+ <entry>
+ <para>
+ HTTP version - if null or instance of HttpClient.Version.HTTP_1_1
+ the version will be set to HTTP_1_1. If version is HttpClient.Version.HTTP_2
+ the client will attempt to perform each request using HTTP_2 protocol
+ but if not supported by server, the protocol will be still HTTP_1_1
+ </para>
+ <para>
+ The value MUST be an instance of <literal>java.net.http.HttpClient.Version</literal>.
+ </para>
+ <para>
+ The default value is &lit.null;.
+ </para>
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent
index 4a81897..ab13afb 100644
--- a/docs/src/main/docbook/jersey.ent
+++ b/docs/src/main/docbook/jersey.ent
@@ -493,6 +493,7 @@
<!ENTITY jersey.jnh.JavaNetHttpClientProperties.SSL_PARAMETERS "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#SSL_PARAMETERS'>JavaNetHttpClientProperties.SSL_PARAMETERS</link>">
<!ENTITY jersey.jnh.JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#PREEMPTIVE_BASIC_AUTHENTICATION'>JavaNetHttpClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION</link>">
<!ENTITY jersey.jnh.JavaNetHttpClientProperties.DISABLE_COOKIES "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#DISABLE_COOKIES'>JavaNetHttpClientProperties.DISABLE_COOKIES</link>">
+<!ENTITY jersey.jnh.JavaNetHttpClientProperties.HTTP_VERSION "<link xlink:href='&jersey.javadoc.uri.prefix;/jnh/connector/JavaNetHttpClientProperties.html#HTTP_VERSION'>JavaNetHttpClientProperties.HTTP_VERSION</link>">
<!ENTITY jersey.linking.DeclarativeLinkingFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/linking/DeclarativeLinkingFeature.html'>DeclarativeLinkingFeature</link>">
<!ENTITY jersey.logging.LoggingFeature "<link xlink:href='&jersey.javadoc.uri.prefix;/logging/LoggingFeature.html'>LoggingFeature</link>">
<!ENTITY jersey.logging.LoggingFeature.DEFAULT_LOGGER_NAME "<link xlink:href='&jersey.javadoc.uri.prefix;/logging/LoggingFeature.html#DEFAULT_LOGGER_NAME'>LoggingFeature.DEFAULT_LOGGER_NAME</link>">