Does anyone have a good (preferably tested) regex for accepting only a valid DNS hostname, IPv4, or IPv6 address?
I understand that you may be forced to use a regex. However, if possible it is better to avoid using regexes for this task and use a Java library class to do the validation instead.
If you want to do validation and DNS lookup together, then InetAddress.getByName(String)
is a good choice. This will cope with DNS, IPv4 and IPv6 in one go, and it returns you a neatly wrapped InetAddress
instance that contains both the DNS name (if provided) and the IPv4 or IPv6 address.
If you just want to do a syntactic validation, then Apache commons has a couple of classes that should do the job: DomainValidator
and InetAddressValidator
.
DomainValidator
) that uses a static table of TLDs is liable to get out of date. However, that API does allow you to supply a more up to date table; see the updateTLDOverride
method. –
Kirchhoff Guava has a new class HostSpecifier. It will even validate that the host name (if it is a host name) ends in a valid "public suffix" (e.g., ".com", ".co.uk", etc.), based on the latest mozilla public suffix list. That's something you would NOT want to attempt with a hand-crafted regex!
As others have said, doing this with a regex is quite a challenge and not advisable. But it is easy to do with the IPAddress Java library which can parse host names, IPv4 and IPv6 addresses, without triggering DNS lookup. Disclaimer: I am the project manager of that library.
Sample code:
check("1.2.3.4");
check("::1");
check("a.b.com");
static void check(String hostStr) {
HostName host = new HostName(hostStr);
try {
host.validate(); // triggers exception for invalid
if(host.isAddress()) {
IPAddress address = host.asAddress();
System.out.println(address.getIPVersion() + " address: " + address);
} else {
System.out.println("host name: " + host);
}
} catch(HostNameException e) {
System.out.println(e.getMessage());
}
}
Output:
IPv4 address: 1.2.3.4
IPv6 address: ::1
host name: a.b.com
Inspired by the code I found in this post, I created the following validator method that seems to suit simple validation needs quite nicely. By reading the JavaDoc of URI I removed some false positives such as "host:80" and "hostname/page", but I cannot guarantee there are some false positives left.
public static boolean isValidHostNameSyntax(String candidateHost) {
if (candidateHost.contains("/")) {
return false;
}
try {
// WORKAROUND: add any scheme and port to make the resulting URI valid
return new URI("my://userinfo@" + candidateHost + ":80").getHost() != null;
} catch (URISyntaxException e) {
return false;
}
}
You can also do this. Let's say:
public boolean isHostnameValid(String hostname) {
try {
InetAddress.getAllByName(hostname); // throws an error when the hostnme could not be found, if so, then return false
return true;
} catch(Exception exc) {
return false;
}
}
© 2022 - 2024 — McMap. All rights reserved.