Repository navigation
v3.0.0 - Internationalized hosts can be checked, and strings became objects #153
spaze
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
An internationalized host can be checked at all now. DNS does not resolve
háčkyčárky.cz, it resolvesxn--hkyrky-ptac70bc.cz, the same name written in ASCII: each part of it is an A-label, thexn--spelling, and the readable one is a U-label.dns_get_record()was being handed the U-labels, so the bundled DNS provider never resolved an internationalized host and never had.The rest of the release is why it is a major one. Values that were strings are now the things they describe: a host is a
SecurityTxtHost, a URL is aUri\WhatWg\Url, an address family is an enum case, a redirect chain is aSecurityTxtRedirects. And a host has one name wherever it is read, instead of one spelling in a message and another in a cache key.Fetching and validation behave as they did, apart from the fixes below. What changed is the shape of nearly everything the library hands back.
A host has one name
The A-labels now go to DNS, the
Host:header andCURLOPT_RESOLVE, and nowhere else; everywhere a person reads a host, it is the U-labels.Everything else reads the host as it was written, and reads it the same way everywhere, because the host is derived once from the URL that actually gets fetched rather than copied out of it at each call site. Not every A-label survives being turned back into a U-label, and where one does not, the whole host stays in A-labels rather than mixing the two:
xn--khby.exampledecodes to a name that re-encodes asxn--jgb.example, a different host, so decoding it would quietly name somewhere nobody asked about.A value arrives as the thing it is
getIpAddresses()as the enum, not its value (Return the IP address type fromgetIpAddresses()as the enum, not its value #114)A value the library holds as a URL or a host is passed on as that object rather than flattened first, so nothing downstream has to guess what a string was.
SecurityTxtRedirectsreplaces the bare arrays a redirect chain used to travel in.Fixes
A
Canonicalfield was compared byte for byte, soHTTPS://example.com/…was reported as not matching the URL it was fetched from. Anhttp://file location threw out of the parser with nothing catching it, which ended the process; that one is also in 2.2.2.Output
getMessage()encodes server-supplied values down to printable ASCII itself now, so it is safe to print wherever, not only throughConsolePrinter. A URL or a host is the exception: it exists because it parsed, so it is quoted as it reads.JSON
Stored results carry a
formatVersion, and decoding refuses one written by a newer version by name instead of failing on whichever field moved. A result stored by 2.x carries no such key and is still read.Internal changes
@testCasewhere Tester reads it (Put@testCasewhere Tester reads it #149)Upgrading
SecurityTxtCheckHosttakes a fourth constructor argument, aSecurityTxtUrlParser. That is the first thing you will hit.Getters hand back objects.
SecurityTxtCheckHostResult::getHost()returns aSecurityTxtHost,getConstructedUrl()andgetFinalUrl()return aUri\WhatWg\Url, and so do the same two onSecurityTxtFetchResultandSecurityTxtFetcherFetchHostResult.SecurityTxtFetcherException::getUrl()returns?UrlandgetRedirects()aSecurityTxtRedirects.SecurityTxtSpecViolation::getCorrectValue()returnsstring|Url|null.SecurityTxtUrlNotFoundException::getIpAddressType()returns the enum case.Callbacks are handed objects too, which PHP will not tell you about until one runs:
addOnUrl()andaddOnFinalUrl()get aUrl,addOnRedirect()two of them,addOnHost()aSecurityTxtHost.SecurityTxtHostis new here, and you build one from a parsed URL:new SecurityTxtHost($url). Neither it norUrlhas a string form of its own, so do not pass one toimplode()orhtmlspecialchars(). Render it withnew SecurityTxtPrintableValue($value)->render(), which takes all three kinds and spells a host the way the rest of the library does.If you implement
SecurityTxtDnsProviderorSecurityTxtFetcherHttpClientyourself, both now take aSecurityTxtHostwhere they took a string, and usegetAscii()for anything that goes on the wire.SecurityTxtIpAddressValidator::validate()takes aSecurityTxtHostand aUrl.ConsolePrinter::ok(),info(),error()andwarning()take a format and its values rather than a finished string,enableColors()issetColors(bool), and thecolor*()helpers are gone.Results stored as JSON by 2.x still decode here, and a 2.x decoder still reads most of what 3.x writes, since the values on the wire are the same strings. One violation breaks both directions:
SecurityTxtPreferredLanguagesCommonMistaketook five constructor arguments and now takes four, its reason having become an enum, so a result carrying it is refused by the other side either way. If a fetching side and a reading side deploy separately, upgrade the reader first, or treat what is cached as a miss and check again.This discussion was created from the release v3.0.0 - Internationalized hosts can be checked, and strings became objects.
All reactions