Merge pull request #3217 from vitorpamplona/claude/ipv6-url-parsing-xy4mvg

fix: parse IPv6-literal URLs in post content
This commit is contained in:
Vitor Pamplona
2026-06-14 12:23:38 -04:00
committed by GitHub
2 changed files with 26 additions and 0 deletions
@@ -47,6 +47,11 @@ class UrlParser {
fun Char.isAsciiLetter(): Boolean = (this in 'a'..'z' || this in 'A'..'Z')
fun Url.isValidTopLevelDomain(): Boolean {
// IPv6 literal hosts are bracketed (e.g. [2001:db8::1]) and have no dotted TLD, so the
// letter-first TLD rule below would wrongly reject them. The detector already validated
// the bracketed address as a syntactically correct IPv6 literal, so accept it directly.
if (host.startsWith('[')) return true
/*
According to the TLD Applicant Guidebook published June 2012, ICANN does not allow numbers in TLDs.
*/
@@ -300,6 +300,27 @@ class UrlParserTest {
Urls(withScheme = emptySet()),
)
@Test
fun testIPv6UrlWithScheme() =
test(
"http://[302:68d0:f0d5:b88d::bdb]/08e31992c51b06d8f8ee4e40207ede11d4c69b0db2d268fb2783d45d69094c2b",
Urls(withScheme = setOf("http://[302:68d0:f0d5:b88d::bdb]/08e31992c51b06d8f8ee4e40207ede11d4c69b0db2d268fb2783d45d69094c2b")),
)
@Test
fun testIPv6UrlWithPort() =
test(
"http://[2001:db8::1]:8080/path",
Urls(withScheme = setOf("http://[2001:db8::1]:8080/path")),
)
@Test
fun testIPv6UrlInSentence() =
test(
"check this http://[2a01:5cc0:1:2::4] out",
Urls(withScheme = setOf("http://[2a01:5cc0:1:2::4]")),
)
@Test
fun testBlossom() {
val blossom = "blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth"