Skip to content
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
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025 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
Expand All @@ -20,12 +20,14 @@
import org.glassfish.jersey.client.ClientRequest;
import org.glassfish.jersey.http.HttpHeaders;
import org.glassfish.jersey.internal.PropertiesResolver;
import org.glassfish.jersey.internal.guava.InetAddresses;

import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.UriBuilder;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
Expand Down Expand Up @@ -233,7 +235,9 @@ public URI toIPRequestUri() {
String host = uri.getHost();
try {
InetAddress ip = InetAddress.getByName(host);
return UriBuilder.fromUri(uri).host(ip.getHostAddress()).build();
// ipv6 is expected in square brackets in UriBuilder#host()
final String hostAddress = ip instanceof Inet6Address ? '[' + ip.getHostAddress() + ']' : ip.getHostAddress();
return UriBuilder.fromUri(uri).host(hostAddress).build();
} catch (UnknownHostException e) {
return uri;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025 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
Expand Down Expand Up @@ -61,7 +61,10 @@ String getHostName() {
static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, String sniHost, boolean whenDiffer) {
final String trimmedHeader;
if (sniHost != null) {
int index = sniHost.indexOf(':'); // RFC 7230 Host = uri-host [ ":" port ] ;
int index = sniHost.lastIndexOf(':'); // RFC 7230 Host = uri-host [ ":" port ] ;
if (sniHost.indexOf(']', index) != -1) {
index = -1; // beware of ipv6 [:1] without port
}
final String trimmedHeader0 = index != -1 ? sniHost.substring(0, index).trim() : sniHost.trim();
trimmedHeader = trimmedHeader0.isEmpty() ? sniHost : trimmedHeader0;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025 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
Expand Down Expand Up @@ -27,8 +27,12 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.Response;
import java.net.ConnectException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -155,4 +159,56 @@ public void testUriAndHeadersAndConfig() {
MatcherAssert.assertThat(configurator.isSNIRequired(), Matchers.is(true));
MatcherAssert.assertThat(configurator.getSNIHostName(), Matchers.is("yyy.com"));
}

@Test
public void testIPv6Header() {
final String HOST_HEADER_IPv6 = "[172:30::333b]";
final URI uri = URI.create("http://[172:30::333a]:8080/api/demo/v1");
final JerseyClient client = (JerseyClient) ClientBuilder.newClient();
Map<String, List<Object>> httpHeaders = new MultivaluedHashMap<>();
httpHeaders.put(HttpHeaders.HOST, Collections.singletonList(HOST_HEADER_IPv6 + ":8080"));
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(HOST_HEADER_IPv6));
URI expected = URI.create("http://" + HOST_HEADER_IPv6 + ":8080/api/demo/v1");
MatcherAssert.assertThat(configurator.getSNIUri(), Matchers.is(expected));
MatcherAssert.assertThat(configurator.toIPRequestUri().toString(),
Matchers.is(uri.toString().replace("::", ":0:0:0:0:0:")));
}

@Test
public void testIpv6Request() {
Client client = ClientBuilder.newClient();
String u = "http://[::1]:8080";
try {
client.target(u)
.request()
.header(HttpHeaders.HOST, "[172:30::333b]:8080")
.get();
} catch (ProcessingException pe) {
if (!ConnectException.class.isInstance(pe.getCause())) {
throw pe;
}
}
}

@Test
public void testIpv6RequestNoPort() {
Client client = ClientBuilder.newClient();
String u = "http://[::1]";
try {
client.target(u)
.request()
.header(HttpHeaders.HOST, "[172:30::333b]")
.get();
} catch (ProcessingException pe) {
if (!ConnectException.class.isInstance(pe.getCause())) {
throw pe;
}
}
}
}
Loading