Remove hostname from NetworkAddress.format

This removes the inconsistent output of IP addresses. The format was parsing-unfriendly and it makes it hard
to reason about API responses, such as to _nodes.

With this change in place, it will never print the hostname as part of the default format, which has the
added benefit that it can be used consistently for URIs, which was not the case when the hostname might
appear at the front with "hostname/ip:port".
This commit is contained in:
Chris Earle 2016-04-07 15:12:50 -04:00
parent ee3c15898b
commit d97d5ebb8b
15 changed files with 70 additions and 165 deletions

View File

@ -114,14 +114,14 @@ final class IfConfig {
InetAddress address = interfaceAddress.getAddress();
if (address instanceof Inet6Address) {
sb.append("inet6 ");
sb.append(NetworkAddress.formatAddress(address));
sb.append(NetworkAddress.format(address));
sb.append(" prefixlen:");
sb.append(interfaceAddress.getNetworkPrefixLength());
} else {
sb.append("inet ");
sb.append(NetworkAddress.formatAddress(address));
sb.append(NetworkAddress.format(address));
int netmask = 0xFFFFFFFF << (32 - interfaceAddress.getNetworkPrefixLength());
sb.append(" netmask:" + NetworkAddress.formatAddress(InetAddress.getByAddress(new byte[] {
sb.append(" netmask:" + NetworkAddress.format(InetAddress.getByAddress(new byte[] {
(byte)(netmask >>> 24),
(byte)(netmask >>> 16 & 0xFF),
(byte)(netmask >>> 8 & 0xFF),
@ -129,7 +129,7 @@ final class IfConfig {
})));
InetAddress broadcast = interfaceAddress.getBroadcast();
if (broadcast != null) {
sb.append(" broadcast:" + NetworkAddress.formatAddress(broadcast));
sb.append(" broadcast:" + NetworkAddress.format(broadcast));
}
}
if (address.isLoopbackAddress()) {

View File

@ -19,14 +19,12 @@
package org.elasticsearch.common.network;
import org.elasticsearch.common.SuppressForbidden;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Objects;
/**
/**
* Utility functions for presentation of network addresses.
* <p>
* Java's address formatting is particularly bad, every address
@ -42,7 +40,9 @@ import java.util.Objects;
* <pre>
* {@code /0:0:0:0:0:0:0:1%1}
* </pre>
* This class provides sane address formatting instead, e.g.
* Note: the {@code %1} is the "scopeid".
* <p>
* This class provides sane address formatting instead, e.g.
* {@code 127.0.0.1} and {@code ::1} respectively. No methods do reverse
* lookups.
*/
@ -50,71 +50,11 @@ public final class NetworkAddress {
/** No instantiation */
private NetworkAddress() {}
/**
* Formats a network address (with optional host) for display purposes.
* <p>
* If the host is already resolved (typically because, we looked up
* a name to do that), then we include it, otherwise it is
* omitted. See {@link #formatAddress(InetAddress)} if you only
* want the address.
* <p>
* IPv6 addresses are compressed and without scope
* identifiers.
* <p>
* Example output with already-resolved hostnames:
* <ul>
* <li>IPv4: {@code localhost/127.0.0.1}</li>
* <li>IPv6: {@code localhost/::1}</li>
* </ul>
* <p>
* Example output with just an address:
* <ul>
* <li>IPv4: {@code 127.0.0.1}</li>
* <li>IPv6: {@code ::1}</li>
* </ul>
* @param address IPv4 or IPv6 address
* @return formatted string
* @see #formatAddress(InetAddress)
*/
public static String format(InetAddress address) {
return format(address, -1, true);
}
/**
* Formats a network address and port for display purposes.
* <p>
* If the host is already resolved (typically because, we looked up
* a name to do that), then we include it, otherwise it is
* omitted. See {@link #formatAddress(InetSocketAddress)} if you only
* want the address.
* <p>
* This formats the address with {@link #format(InetAddress)}
* and appends the port number. IPv6 addresses will be bracketed.
* <p>
* Example output with already-resolved hostnames:
* <ul>
* <li>IPv4: {@code localhost/127.0.0.1:9300}</li>
* <li>IPv6: {@code localhost/[::1]:9300}</li>
* </ul>
* <p>
* Example output with just an address:
* <ul>
* <li>IPv4: {@code 127.0.0.1:9300}</li>
* <li>IPv6: {@code [::1]:9300}</li>
* </ul>
* @param address IPv4 or IPv6 address with port
* @return formatted string
* @see #formatAddress(InetSocketAddress)
*/
public static String format(InetSocketAddress address) {
return format(address.getAddress(), address.getPort(), true);
}
/**
* Formats a network address for display purposes.
* <p>
* This formats only the address, any hostname information,
* if present, is ignored. IPv6 addresses are compressed
* if present, is ignored. IPv6 addresses are compressed
* and without scope identifiers.
* <p>
* Example output with just an address:
@ -125,14 +65,14 @@ public final class NetworkAddress {
* @param address IPv4 or IPv6 address
* @return formatted string
*/
public static String formatAddress(InetAddress address) {
return format(address, -1, false);
public static String format(InetAddress address) {
return format(address, -1);
}
/**
* Formats a network address and port for display purposes.
* <p>
* This formats the address with {@link #formatAddress(InetAddress)}
* This formats the address with {@link #format(InetAddress)}
* and appends the port number. IPv6 addresses will be bracketed.
* Any host information, if present is ignored.
* <p>
@ -144,38 +84,27 @@ public final class NetworkAddress {
* @param address IPv4 or IPv6 address with port
* @return formatted string
*/
public static String formatAddress(InetSocketAddress address) {
return format(address.getAddress(), address.getPort(), false);
public static String format(InetSocketAddress address) {
return format(address.getAddress(), address.getPort());
}
// note, we don't validate port, because we only allow InetSocketAddress
@SuppressForbidden(reason = "we call toString to avoid a DNS lookup")
static String format(InetAddress address, int port, boolean includeHost) {
static String format(InetAddress address, int port) {
Objects.requireNonNull(address);
StringBuilder builder = new StringBuilder();
if (includeHost) {
// must use toString, to avoid DNS lookup. but the format is specified in the spec
String toString = address.toString();
int separator = toString.indexOf('/');
if (separator > 0) {
// append hostname, with the slash too
builder.append(toString, 0, separator + 1);
}
}
if (port != -1 && address instanceof Inet6Address) {
builder.append(InetAddresses.toUriString(address));
} else {
builder.append(InetAddresses.toAddrString(address));
}
if (port != -1) {
builder.append(':');
builder.append(port);
}
return builder.toString();
}
}

View File

@ -81,7 +81,7 @@ public final class InetSocketTransportAddress implements TransportAddress {
@Override
public String getAddress() {
return NetworkAddress.formatAddress(address.getAddress());
return NetworkAddress.format(address.getAddress());
}
@Override

View File

@ -533,7 +533,7 @@ public class Node implements Closeable {
// no link local, just causes problems
continue;
}
writer.write(NetworkAddress.formatAddress(new InetSocketAddress(inetAddress, address.getPort())) + "\n");
writer.write(NetworkAddress.format(new InetSocketAddress(inetAddress, address.getPort())) + "\n");
}
} catch (IOException e) {
throw new RuntimeException("Failed to write ports file", e);

View File

@ -251,7 +251,7 @@ public class RestNodesAction extends AbstractCatAction {
if (httpInfo != null) {
TransportAddress transportAddress = httpInfo.getAddress().publishAddress();
if (transportAddress instanceof InetSocketTransportAddress) {
table.addCell(NetworkAddress.formatAddress(((InetSocketTransportAddress)transportAddress).address()));
table.addCell(NetworkAddress.format(((InetSocketTransportAddress)transportAddress).address()));
} else {
table.addCell(transportAddress.toString());
}

View File

@ -22,7 +22,6 @@ package org.elasticsearch.common.network;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -32,93 +31,70 @@ import java.util.Random;
* Tests for network address formatting. Please avoid using any methods that cause DNS lookups!
*/
public class NetworkAddressTests extends ESTestCase {
public void testFormatV4() throws Exception {
assertEquals("localhost/127.0.0.1", NetworkAddress.format(forge("localhost", "127.0.0.1")));
assertEquals("127.0.0.1", NetworkAddress.format(forge("localhost", "127.0.0.1")));
assertEquals("127.0.0.1", NetworkAddress.format(forge(null, "127.0.0.1")));
}
public void testFormatV6() throws Exception {
assertEquals("localhost/::1", NetworkAddress.format(forge("localhost", "::1")));
assertEquals("::1", NetworkAddress.format(forge("localhost", "::1")));
assertEquals("::1", NetworkAddress.format(forge(null, "::1")));
}
public void testFormatAddressV4() throws Exception {
assertEquals("127.0.0.1", NetworkAddress.formatAddress(forge("localhost", "127.0.0.1")));
assertEquals("127.0.0.1", NetworkAddress.formatAddress(forge(null, "127.0.0.1")));
}
public void testFormatAddressV6() throws Exception {
assertEquals("::1", NetworkAddress.formatAddress(forge("localhost", "::1")));
assertEquals("::1", NetworkAddress.formatAddress(forge(null, "::1")));
}
public void testFormatPortV4() throws Exception {
assertEquals("localhost/127.0.0.1:1234", NetworkAddress.format(new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234)));
assertEquals("127.0.0.1:1234", NetworkAddress.format(new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234)));
assertEquals("127.0.0.1:1234", NetworkAddress.format(new InetSocketAddress(forge(null, "127.0.0.1"), 1234)));
}
public void testFormatPortV6() throws Exception {
assertEquals("localhost/[::1]:1234", NetworkAddress.format(new InetSocketAddress(forge("localhost", "::1"), 1234)));
assertEquals("[::1]:1234",NetworkAddress.format(new InetSocketAddress(forge(null, "::1"), 1234)));
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forge("localhost", "::1"), 1234)));
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forge(null, "::1"), 1234)));
}
public void testFormatAddressPortV4() throws Exception {
assertEquals("127.0.0.1:1234", NetworkAddress.formatAddress(new InetSocketAddress(forge("localhost", "127.0.0.1"), 1234)));
assertEquals("127.0.0.1:1234", NetworkAddress.formatAddress(new InetSocketAddress(forge(null, "127.0.0.1"), 1234)));
}
public void testFormatAddressPortV6() throws Exception {
assertEquals("[::1]:1234", NetworkAddress.formatAddress(new InetSocketAddress(forge("localhost", "::1"), 1234)));
assertEquals("[::1]:1234", NetworkAddress.formatAddress(new InetSocketAddress(forge(null, "::1"), 1234)));
}
public void testNoScopeID() throws Exception {
assertEquals("::1", NetworkAddress.format(forgeScoped(null, "::1", 5)));
assertEquals("localhost/::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5)));
assertEquals("::1", NetworkAddress.formatAddress(forgeScoped(null, "::1", 5)));
assertEquals("::1", NetworkAddress.formatAddress(forgeScoped("localhost", "::1", 5)));
assertEquals("::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5)));
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forgeScoped(null, "::1", 5), 1234)));
assertEquals("localhost/[::1]:1234", NetworkAddress.format(new InetSocketAddress(forgeScoped("localhost", "::1", 5), 1234)));
assertEquals("[::1]:1234", NetworkAddress.formatAddress(new InetSocketAddress(forgeScoped(null, "::1", 5), 1234)));
assertEquals("[::1]:1234", NetworkAddress.formatAddress(new InetSocketAddress(forgeScoped("localhost", "::1", 5), 1234)));
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forgeScoped("localhost", "::1", 5), 1234)));
}
/** Test that ipv4 address formatting round trips */
public void testRoundTripV4() throws Exception {
byte bytes[] = new byte[4];
roundTrip(new byte[4]);
}
/** Test that ipv6 address formatting round trips */
public void testRoundTripV6() throws Exception {
roundTrip(new byte[16]);
}
/**
* Round trip test code for both IPv4 and IPv6. {@link InetAddress} contains the {@code getByAddress} and
* {@code getbyName} methods for both IPv4 and IPv6, unless you also specify a {@code scopeid}, which this does not
* test.
*
* @param bytes 4 (32-bit for IPv4) or 16 bytes (128-bit for IPv6)
* @throws Exception if any error occurs while interacting with the network address
*/
private void roundTrip(byte[] bytes) throws Exception {
Random random = random();
for (int i = 0; i < 10000; i++) {
random.nextBytes(bytes);
InetAddress expected = Inet4Address.getByAddress(bytes);
String formatted = NetworkAddress.formatAddress(expected);
InetAddress expected = InetAddress.getByAddress(bytes);
String formatted = NetworkAddress.format(expected);
InetAddress actual = InetAddress.getByName(formatted);
assertEquals(expected, actual);
}
}
/** Test that ipv6 address formatting round trips */
public void testRoundTripV6() throws Exception {
byte bytes[] = new byte[16];
Random random = random();
for (int i = 0; i < 10000; i++) {
random.nextBytes(bytes);
InetAddress expected = Inet6Address.getByAddress(bytes);
String formatted = NetworkAddress.formatAddress(expected);
InetAddress actual = InetAddress.getByName(formatted);
assertEquals(expected, actual);
}
}
/** creates address without any lookups. hostname can be null, for missing */
private InetAddress forge(String hostname, String address) throws IOException {
byte bytes[] = InetAddress.getByName(address).getAddress();
return InetAddress.getByAddress(hostname, bytes);
}
/** creates scoped ipv6 address without any lookups. hostname can be null, for missing */
private InetAddress forgeScoped(String hostname, String address, int scopeid) throws IOException {
byte bytes[] = InetAddress.getByName(address).getAddress();

View File

@ -74,8 +74,8 @@ public class UnicastZenPingIT extends ESTestCase {
InetSocketTransportAddress addressB = (InetSocketTransportAddress) transportB.boundAddress().publishAddress();
Settings hostsSettings = Settings.settingsBuilder().putArray("discovery.zen.ping.unicast.hosts",
NetworkAddress.formatAddress(new InetSocketAddress(addressA.address().getAddress(), addressA.address().getPort())),
NetworkAddress.formatAddress(new InetSocketAddress(addressB.address().getAddress(), addressB.address().getPort())))
NetworkAddress.format(new InetSocketAddress(addressA.address().getAddress(), addressA.address().getPort())),
NetworkAddress.format(new InetSocketAddress(addressB.address().getAddress(), addressB.address().getPort())))
.build();
UnicastZenPing zenPingA = new UnicastZenPing(hostsSettings, threadPool, transportServiceA, clusterName, Version.CURRENT, electMasterService, null);

View File

@ -143,14 +143,14 @@ public class HttpPipeliningHandlerTests extends ESTestCase {
assertTrue(connectionFuture.await(CONNECTION_TIMEOUT));
final Channel clientChannel = connectionFuture.getChannel();
// NetworkAddress.formatAddress makes a proper HOST header.
// NetworkAddress.format makes a proper HOST header.
final HttpRequest request1 = new DefaultHttpRequest(
HTTP_1_1, HttpMethod.GET, PATH1);
request1.headers().add(HOST, NetworkAddress.formatAddress(boundAddress));
request1.headers().add(HOST, NetworkAddress.format(boundAddress));
final HttpRequest request2 = new DefaultHttpRequest(
HTTP_1_1, HttpMethod.GET, PATH2);
request2.headers().add(HOST, NetworkAddress.formatAddress(boundAddress));
request2.headers().add(HOST, NetworkAddress.format(boundAddress));
clientChannel.write(request1);
clientChannel.write(request2);

View File

@ -103,7 +103,7 @@ public class NettyTransportMultiPortIntegrationIT extends ESIntegTestCase {
// publish address
assertThat(nodeInfo.getTransport().getProfileAddresses().get("client1").publishAddress(), instanceOf(InetSocketTransportAddress.class));
InetSocketTransportAddress publishAddress = (InetSocketTransportAddress) nodeInfo.getTransport().getProfileAddresses().get("client1").publishAddress();
assertThat(NetworkAddress.formatAddress(publishAddress.address().getAddress()), is("127.0.0.7"));
assertThat(NetworkAddress.format(publishAddress.address().getAddress()), is("127.0.0.7"));
assertThat(publishAddress.address().getPort(), is(4321));
}
}

View File

@ -53,7 +53,7 @@ public class SimpleNettyTransportTests extends AbstractSimpleTransportTestCase {
fail("Expected ConnectTransportException");
} catch (ConnectTransportException e) {
assertThat(e.getMessage(), containsString("connect_timeout"));
assertThat(e.getMessage(), containsString("[localhost/127.0.0.1:9876]"));
assertThat(e.getMessage(), containsString("[127.0.0.1:9876]"));
}
}
}

View File

@ -219,7 +219,7 @@ public class AzureUnicastHostsProvider extends AbstractComponent implements Unic
if (privateIp.equals(ipAddress)) {
logger.trace("adding ourselves {}", NetworkAddress.format(ipAddress));
}
networkAddress = NetworkAddress.formatAddress(privateIp);
networkAddress = NetworkAddress.format(privateIp);
} else {
logger.trace("no private ip provided. ignoring [{}]...", instance.getInstanceName());
}
@ -232,7 +232,7 @@ public class AzureUnicastHostsProvider extends AbstractComponent implements Unic
continue;
}
networkAddress = NetworkAddress.formatAddress(new InetSocketAddress(endpoint.getVirtualIPAddress(),
networkAddress = NetworkAddress.format(new InetSocketAddress(endpoint.getVirtualIPAddress(),
endpoint.getPort()));
}

View File

@ -126,7 +126,7 @@ public class GceUnicastHostsProvider extends AbstractComponent implements Unicas
try {
InetAddress inetAddress = networkService.resolvePublishHostAddresses(null);
if (inetAddress != null) {
ipAddress = NetworkAddress.formatAddress(inetAddress);
ipAddress = NetworkAddress.format(inetAddress);
}
} catch (IOException e) {
// We can't find the publish host address... Hmmm. Too bad :-(

View File

@ -145,7 +145,7 @@ public final class GeoIpProcessor extends AbstractProcessor {
for (Field field : fields) {
switch (field) {
case IP:
geoData.put("ip", NetworkAddress.formatAddress(ipAddress));
geoData.put("ip", NetworkAddress.format(ipAddress));
break;
case COUNTRY_ISO_CODE:
geoData.put("country_iso_code", country.getIsoCode());
@ -198,7 +198,7 @@ public final class GeoIpProcessor extends AbstractProcessor {
for (Field field : fields) {
switch (field) {
case IP:
geoData.put("ip", NetworkAddress.formatAddress(ipAddress));
geoData.put("ip", NetworkAddress.format(ipAddress));
break;
case COUNTRY_ISO_CODE:
geoData.put("country_iso_code", country.getIsoCode());

View File

@ -2047,7 +2047,7 @@ public abstract class ESIntegTestCase extends ESTestCase {
TransportAddress publishAddress = randomFrom(nodes).getHttp().address().publishAddress();
assertEquals(1, publishAddress.uniqueAddressTypeId());
InetSocketAddress address = ((InetSocketTransportAddress) publishAddress).address();
return new HttpRequestBuilder(HttpClients.createDefault()).host(NetworkAddress.formatAddress(address.getAddress())).port(address.getPort());
return new HttpRequestBuilder(HttpClients.createDefault()).host(NetworkAddress.format(address.getAddress())).port(address.getPort());
}
/**

View File

@ -83,7 +83,7 @@ public class HttpRequestBuilder {
public HttpRequestBuilder httpTransport(HttpServerTransport httpServerTransport) {
InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) httpServerTransport.boundAddress().publishAddress();
return host(NetworkAddress.formatAddress(transportAddress.address().getAddress())).port(transportAddress.address().getPort());
return host(NetworkAddress.format(transportAddress.address().getAddress())).port(transportAddress.address().getPort());
}
public HttpRequestBuilder port(int port) {