Skip to content

Commit

Permalink
HTTP/2 for JNH connector
Browse files Browse the repository at this point in the history
Signed-off-by: Maxim Nesen <[email protected]>
  • Loading branch information
senivam committed Aug 9, 2023
1 parent 050f93b commit dc35123
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ public class JavaNetHttpClientProperties {
public static final String DISABLE_COOKIES =
"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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ public class JavaNetHttpConnector implements Connector {
* @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);
Expand Down Expand Up @@ -230,6 +232,9 @@ private <T> T getPropertyOrNull(final Configuration configuration, final String
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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
18 changes: 18 additions & 0 deletions docs/src/main/docbook/appendix-properties.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/docbook/jersey.ent
Original file line number Diff line number Diff line change
Expand Up @@ -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>">
Expand Down

0 comments on commit dc35123

Please sign in to comment.