7 ms·
> "Two hosts are considered equivalent if both host names can be resolved into the same IP addresses" Uhmm... yikes. Why are they resolving anything? A URL is
by strictnein 7y ago
> "Two hosts are considered equivalent if both host names can be resolved into the same IP addresses"
Uhmm... yikes. Why are they resolving anything? A URL is a string, this should just be doing a string comparison. All of the parts of the URL object are strings or ints, so at worst they should just be comparing all of those individually, not resolving domains and comparing IP addresses. That makes no sense at all.
- boofgod 7y agoIt's possible to have URLs that are not equal as strings but resolve to the same thing so this actually makes perfect sense. If you really want to test if URLs are equal as strings, I'm sure you could still do it that way.
- Someone1234 7y ago> It's possible to have URLs that are not equal as strings but resolve to the same thing so this actually makes perfect sense. No, that doesn't make "perfect sense." Two different URLs are different, they cannot be equal if they're different, and a library called "URL" shouldn't use voodoo-magic to say that two different URLs are equal when they're not. If it was e.g. Net.DNS.Equal(Uri, Uri), perhaps. But even then it is ambiguous as DNS has multiple record types, not just "A" records. So is it pulling all records (A, AAAA, MX, etc) and comparing them all? Or just arbitrary comparing one? But as it stands, it is a URL library that is ignoring the URL part of the URL and using resolution to decide equality instead. It is nonsensical. And even if they did resolve identically they may not be treated identically by routing or endpoints.
- deleted 7y ago[deleted]
- jerf 7y agoNot only is it possible to have two hostnames that resolve to the same IP address, hostname -> IP address is not unique either: $ dig amazon.com ... ;; ANSWER SECTION: amazon.com. 60 IN A 205.251.242.103 amazon.com. 60 IN A 176.32.103.205 amazon.com. 60 IN A 176.32.98.166 Something resolving "amazon.com" is welcome to resolve it to any of those three addresses. Code that tries to "resolve" these IPs is at the very least coming perilously close to deciding that amazon.com != amazon.com, nondeterministically, if the underlying resolution call changes its behavior. The further obvious change of trying to compare the whole record just gets worse; what is the answer if domain 1 resolves to IPs (V, X, Y) and domain 2 resolves to (X, Y, Z)? Oh, and let's not forget, DNS can be different depending on your geographical location, so in the US two domains may happen to resolve to the same IP but in Europe they may be different. What's the use of a URL equality operator that changes behavior based on where the user is? Whatever the use of such a thing may be (I mean, yeah, I get the internet contrarian impulse, yeah, I can construct some bizarre situation in which it is useful), it is certainly less useful than a simpler operator. Basically, the entire idea is just fundamentally flawed and shouldn't be used. I make no claim to have exhaustively enumerated all the ways in which this is a bad idea, merely added to the pile, and demonstrated sufficient evidence for my claim that it shouldn't be used. Edit: They know, see yzmtf2008: https://news.ycombinator.com/item?id=21766138 https://news.ycombinator.com/item?id=21766138 and consider my post here a lightly educational post on further reasons why it's a bad idea. If you only take one thing away, remember, a function that takes a hostname and yields an IP doesn't have very many useful properties beyond just that it yields an IP or failure. You can count on very little else about that IP. It should be treated as opaque and not compared, stored (other than logging), etc.
- jefftk 7y agoUnlike virtual hosting, which wasn't possible when java.net.URL was written, this kind of DNS behavior had been around for years: https://tools.ietf.org/html/rfc1794 https://tools.ietf.org/html/rfc1794
- lmkg 7y agoI mean, I can see host resolution equivalence being a useful piece of functionality. I could even see it being built-in to a std URL library. Just, y'know... not as the default equality operator. And yes, I know that overriding .equals() does not change the behavior of == in Java. But I would still consider .equals() to be the "default" equality operator for objects.
- BenjiWiebe 7y agoThanks to virtual hosting (which is extremely common) host resolution is actively harmful to URL comparison.
- jefftk 7y ago> Thanks to virtual hosting (which is extremely common) It's extremely common now, but it wasn't possible yet when they made this design decision.
- pdw 7y agoI'm pretty sure the specification of this class predates name-based virtual hosting. After all, that only appeared in 1997, or perhaps late 1996, and it took a couple of years to be standardized. The URL class existed in Java in 1995 :) (Edit: And really, virtual hosts are an extremely weird HTTP feature. What other internet protocol cares about what domain name you used to establish a connection?)
- merb 7y ago> (Edit: And really, virtual hosts are an extremely weird HTTP feature. What other internet protocol cares about what domain name you used to establish a connection?) kerberos? (btw. this is older than 1995) or smtp (little bit different than the http version, tough)
- tootie 7y agoSounds like a developer with too much time on their hands decided to add some humongous side effects.
- kevin_thibedeau 7y agoProbably a PHB who wanted to "put the . in .com" with network enhanced string processing.
- whalesalad 7y agoIt makes a lot of sense if you pull your head out of the code and consider a URL is a universal resource locator. I don’t agree with what this is doing... but you can’t say it makes no sense at all.
- strictnein 7y agoWith this definition two different resources could be said to have the equivalent universal resource locators. foo.bar/baz would be said to be equivalent to bar.wack/baz if they shared the same IP address. If there is some sense to be made from that, it eludes me.
- lkschubert8 7y agoI think the argument is the domain name is an abstraction over ip address and ip address is the definitive "resource".
- kstrauser 7y agoIt definitely doesn't make sense, because two unrelated hosts can share the same IP. If you tried to fetch http://a.b.c.d/some/path http://a.b.c.d/some/path, then the server will fail because it doesn't know which host you mean. In this case, Java has thrown away the critical distinction between the two.
- sjwright 7y agoAnd it especially doesn’t make sense because resolving to the same IP on the server right now doesn’t guarantee it will resolve the same on the client, or even on the same server in 15 minutes time.
- desc 7y ago* A URL is a name for a pointer. * A URL is a parameter to a function returning a resource. * A URL is a string, conforming to a certain format. Neither of these specifies that the resource it points to is always the same resource, nor that it's always possible to resolve it. That's by design; hostnames change. The Web is not permanent and that's why we have eg. HTTP 404. Network topologies also change. However, the default equals() comparison between two objects is supposed to compare those two objects, not the current topology of the Internet. There is no way this behaviour ever made sense, nor any way it ever could make sense. It's moronic, through and through, for any language or library, to implement default equality in this way. If you want to implement a comparer which does stuff like this and accepts a hostname resolver as a dependency, great. But there is simply no excuse for this kind of stupidity in a default dependency-less implementation.
- tyre 7y agoThat's an interesting way to think about URLs. If both `url`.com` and `url2.com` resolve to the same IP then they are functionally the same. It's like comparing two strings whose variable names are different but that resolve to the same space in memory. It also means that if one URL changes, then they could be equal sometimes and not others.
- kohtatsu 7y agoThey are not functionally the same. Full stop. It sends a different Host HTTP header; servers send different responses based on that header ~100% of the time.
- ses1984 7y agoNo, they aren't functionally the same for all protocols, because of things like SNI.
- duskwuff 7y agoOr, even before that: because of things like HTTP 1.1 virtual hosting.
- sli 7y ago> Note: The defined behavior for equals is known to be inconsistent with virtual hosting in HTTP. They even seem to know it makes no sense.
- Gaelan 7y agoPresumably, at the point they realized that, something already depended on this behavior.
- kuschku 7y agoAt the point someone invented virtual hosting, sun already depended on this behavior ;)
- Twirrim 7y agoThis feature was introduced in 1995. Before virtual hosting was a thing. (HTTP/1.1 wasn't formalised until 1999)
- eliaspro 7y ago...and what if my resolver uses round-robin and returns a different IP on each request?
- duskwuff 7y agoOr if the computer running the JVM doesn't have a reliable network connection? Does the behavior of URL.equals() change if your network connection is down? ... and what happens when you try to compare a URL which contains a nonexistent hostname, like http://asdfghjkl.example.com/ http://asdfghjkl.example.com/ ? Does that compare as equal to all other URLs with unresolvable hostnames?
- wolfgang42 7y ago> if either host name can't be resolved, the host names must be equal without regard to case; or both host names equal to null.
- cotillion 7y agoI wonder if anything is using URL.equals to check for 'safe' urls. Some creative use of DNS TTL could probably make things interesting.
- adrusi 7y agoBuy a domain name, point it at Enterprise Business Inc.'s server, submit a link using your domain to a form the operate which does a if (internalURLs.contains(submittedURL)) { check. Then change your DNS records to point to some other server, once your domain is in their database and they assume it to have already been validated as internal.
- kstrauser 7y agoExploiters, start your engines. This seems absolutely ripe for abuse, as now there's a nice string you can search for in GitHub to see where that's used as a security feature. I'm imagining things like "if URL("http://example.com/some/path" http://example.com/some/path").equals(URL(checkedUrl)) { return AllowEditRights }", and checkedUrl = "http://wiki.example.com/some/path" http://wiki.example.com/some/path" or similar.
- toyg 7y ago"now"? This has been the case for more than 20 years...
- ivan_gammel 7y agoThere's one thing in Javadoc that says it all: `@since JDK 1.0` Java is as good as Windows in the sense, that its standard library and set of APIs is very stable and supports a lot of legacy software. I doubt there's a real need for URL class in the new code by now, given that URI class was introduced in JDK 1.4 almost 18 years ago. There's plenty of dependencies though, so URL will probably stay in the core library forever, but URI represents a superset for URLs, has reasonable implementation of equals/hashCode and is sufficient for majority of the uses.
- toyg 7y agoIndeed, and tbh I'm somewhat surprised this is front-page in 2019. I guess younglings are (re-)learning java and unhearting its umpteen WTFs...
- kelnos 7y agoEh, I dunno, I've been an on-and-off Java person since ~2000 (with consistent JVM development over the last 8 years or so), and I only learned about this URL gotcha within the last couple years. I think https://imgs.xkcd.com/comics/ten_thousand_2x.png https://imgs.xkcd.com/comics/ten_thousand_2x.png applies here, just in a more restricted programmer-y sense..
- vbezhenar 7y ago> I doubt there's a real need for URL class in the new code by now URL class is used to establish actual connection to a resource.
- dionian 7y agoI'm a seasoned java dev (since before 1.4) and i didnt realize i was supposed to use URI, i did know of it, but I'm always confused what to use and wind up using URL. But, just like Vector remains in use in Swing, URL remains in use in the core java library (looking at you, classloader.getresource), so it's easy for me to have made that mistake. then again i dont use it often. mostly come in contact with it when using ClassLoader API.,
- boring_twenties 7y agoWhat about http://foo/ http://foo/ and http://foo:80/ http://foo:80/? Are those different URLs?
- beart 7y agoYes, they just resolve to the same thing
- iso-8859-1 7y agoPort numbers do not resolve. And your 'thing' is ambiguous.
- spc476 7y agoRFC-3986, section 6.2.3: For example, because the "http" scheme makes use of an authority component, has a default port of "80", and defines an empty path to be equivalent to "/", the following four URIs are equivalent: http://example.com http://example.com/ http://example.com:/ http://example.com:80/
- patrickthebold 7y ago> January 2005
- spc476 7y agoAnd? It has not been obsoleted, and it's marked as STD0066.
- kelnos 7y agoOne thing I find interesting is that it doesn't canonicalize the path portion at all. E.g.: scala> new URL("http://localhost/foo/bar/baz").equals(new URL("http://localhost/foo/../foo/bar/baz")) res0: Boolean = false It's just funny to me that they went to the effort to do a full network request to see if the hostnames resolve to the same IP, but didn't bother to normalize paths.
- jacinabox 7y agoStill this sort of expansionary philosophy in library design does give some cause for optimism. In general library authors want to make their specs efficiently implementable, so when an method has this sort of semantics in an official spec it makes one suspect that a breakthrough in AI/algorithms research is right around the corner.
- smarks 7y agoThis might have something to do with the way that name resolution worked inside of Sun at the time. If there was a host, say doppio.eng.sun.com it would be referred to simply as "doppio" from within the engineering ("eng.sun.com") domain, or possibly as "doppio.eng" from other domains inside of Sun. It was fairly rare to use FQDNs inside of Sun to refer to other hosts inside of Sun. Thus, the following URLs all referred to the same resource: http://doppio/foo.html http://doppio.eng/foo.html http://doppio.eng.sun.com/foo.html It's a plausible point of view that URL.equals() should report true for any two of the above URLs. (That doesn't mean that I think it was a good idea, though.)
- cryptonector 7y agoBut then again, an HTTP server is allowed to provide different semantics for an URLs depending on the authority portion of those URLs. So, no, this is not remotely Ok at all.
- kelnos 7y agoAgreed, but consider that the internet, and state of HTTP hosting, was a very different place in 1995. Was the Host header even a thing back then? (And if it was, was it widely deployed?) This is clearly wrong in hindsight, but I could see why it was naively designed that way in the first place. Regardless, given all Java's warts, this doesn't even make my top 10.
- cryptonector 7y agoSure, but since no one in their right mind wants this behavior now, it's best to rip it out and fix the spec to not require it.