Are there two URL (from java.net.URL
) objects whose equality is false but whose toString is the same?
val url1 = ...
val url2 = ...
println(url1 == url2) // should print false
printnln(url1.toString() == url2.toString()) // should print true
The opposite is much easier
val u1: URL = java.net.URL("http://example.com/path")
val u2: URL = java.net.URL("http://example.com:80/path") // explicit default port
println(url1 == url2) // prints true
printnln(url1.toString() == url2.toString()) // prints false
For context, I'm migrating from old way to do URLs via URL(string)
to new way using URI and I see these cases in the logs, but then the toString is the same.
My theory is that URL equals performs a DNS check for both URLs. So if there were to be an IP change in between the host check, it would not be equal.
So the following simple code can already fail:
val urla = "http://oracle.com"
val url1 = URL(urla)
val url2 = URL(urla)
assertTrue(url1 == url2)
In order to reproduce it, I prepare two files
cat /etc/hosts.with_overrides
> ## contains
> 127.0.0.1 oracle.com
And
cat /etc/hosts.no_overrides
> # normal file
I set a debugger in UrlStreamHandler, at
protected boolean hostsEqual(URL u1, URL u2) {
InetAddress a1 = getHostAddress(u1);
InetAddress a2 = getHostAddress(u2);
I let the first resolution happen, then
sudo cp /etc/hosts.with_overrides /etc/hosts
or the other way around. Wait for some time for cache to clean up. I run a line and now I see:
And the assert fails.
In production with more volume, this happens quite often.