Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP/2 for JNH connector #5293

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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