Change hosts file resolver to be case-insensitive

Motivation:

Resolving hosts via the /etc/hosts file should be case-insensitive, e.g. localhost and LOCALHOST refer to the same host, this is the same that is applied to dns queries.

Modifications:

Store hosts Map with lowercase keys, lookup the keys as lowercase
Add to unit test for the hosts file parser to use an UPPERCASE file entry
Add unit test for DefaultHostsFileEntriesResolver to resolve both localhost and LOCALHOST

Result:

host resolution for local hosts file should match the rules applied to "getent hosts" or "ping"
This commit is contained in:
alexlehm 2016-04-29 21:06:30 +02:00 committed by Norman Maurer
parent d580245afc
commit 24784bfcd1
4 changed files with 45 additions and 4 deletions

View File

@ -16,6 +16,7 @@
package io.netty.resolver;
import java.net.InetAddress;
import java.util.Locale;
import java.util.Map;
/**
@ -27,6 +28,6 @@ public final class DefaultHostsFileEntriesResolver implements HostsFileEntriesRe
@Override
public InetAddress address(String inetHost) {
return entries.get(inetHost);
return entries.get(inetHost.toLowerCase(Locale.ENGLISH));
}
}

View File

@ -29,6 +29,7 @@ import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
@ -151,10 +152,11 @@ public final class HostsFileParser {
// loop over hostname and aliases
for (int i = 1; i < lineParts.size(); i ++) {
String hostname = lineParts.get(i);
if (!entries.containsKey(hostname)) {
String hostnameLower = hostname.toLowerCase(Locale.ENGLISH);
if (!entries.containsKey(hostnameLower)) {
// trying to map a host to multiple IPs is wrong
// only the first entry is honored
entries.put(hostname, InetAddress.getByAddress(hostname, ipBytes));
entries.put(hostnameLower, InetAddress.getByAddress(hostname, ipBytes));
}
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* show issue https://github.com/netty/netty/issues/5182
* HostsFileParser tries to resolve hostnames as case-sensitive
*/
package io.netty.resolver;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
public class DefaultHostsFileEntriesResolverTest {
@Test
public void testLocalhost() {
DefaultHostsFileEntriesResolver resolver = new DefaultHostsFileEntriesResolver();
assertNotNull("localhost doesn't resolve", resolver.address("localhost"));
assertNotNull("LOCALHOST doesn't resolve", resolver.address("LOCALHOST"));
}
}

View File

@ -38,16 +38,20 @@ public class HostsFileParserTest {
.append("192.168.0.2 host3 #comment").append("\n") // comment after hostname
.append("192.168.0.3 host4 host5 host6").append("\n") // multiple aliases
.append("192.168.0.4 host4").append("\n") // host mapped to a second address, must be ignored
.append("192.168.0.5 HOST7").append("\n") // uppercase host, should match lowercase host
.append("192.168.0.6 host7").append("\n") // should be ignored since we have the uppercase host already
.toString();
Map<String, InetAddress> entries = HostsFileParser.parse(new BufferedReader(new StringReader(hostsString)));
assertEquals("Expected 6 entries", 6, entries.size());
assertEquals("Expected 7 entries", 7, entries.size());
assertEquals("127.0.0.1", entries.get("host1").getHostAddress());
assertEquals("192.168.0.1", entries.get("host2").getHostAddress());
assertEquals("192.168.0.2", entries.get("host3").getHostAddress());
assertEquals("192.168.0.3", entries.get("host4").getHostAddress());
assertEquals("192.168.0.3", entries.get("host5").getHostAddress());
assertEquals("192.168.0.3", entries.get("host6").getHostAddress());
assertNotNull("uppercase host doesn't resolve", entries.get("host7"));
assertEquals("192.168.0.5", entries.get("host7").getHostAddress());
}
}