Solely the second encoding is legitimate in response to RFC 3986. A colon is allowed in a relative path (which your string is), besides within the first path element (i.e. earlier than the primary slash).
addingPercentEncoding
handles the built-in URL-related character courses in another way from the random character courses you create in your code. The character courses you create in your code can’t encode difficult logic like “colon is allowed until it’s earlier than the primary slash”, even when it incorporates the identical characters as a built-in URL character class.
You possibly can see how this works by wanting on the _CFStringCreateByAddingPercentEncodingWithAllowedCharacters
operate in swift-corelibs-foundation repository. This is not precisely what’s run on Apple platforms, but it surely’s an excellent reference.
This operate calls GetURLPredefinedCharacterSet
to see if the handed in character set is likely one of the built-in ones. Crucially, GetURLPredefinedCharacterSet
does a pointer comparability with the built-in character units:
for ( outcome = 0; outcome < kURLAllowedCharacterSetIllegal; ++outcome ) {
// sure, I actually desire a pointer comparability as a result of a few of the sURLAllowedCharacterSets have the identical bitmaps
if ( characterSet == sURLAllowedCharacterSets[result] ) {
break;
}
}
It is not going to discover your set
within the sURLAllowedCharacterSets
array, so it’s going to return kURLAllowedCharacterSetIllegal
, and _CFStringCreateByAddingPercentEncodingWithAllowedCharacters
will deal with your set as an everyday character set with no particular that means, and never escape the colon, for the reason that colon character is within the set.
If you happen to use the built-in .urlPathAllowed
, _CFStringCreateByAddingPercentEncodingWithAllowedCharacters
will go down a unique path, and attain right here, the place the particular dealing with is completed.
We will see that within the else
department of if (pastSlash)
, it explicitly disallows colons:
Boolean allowed = (ch <= 127) && (ch != ';') && (ch != ':') && ((sURLAllowedCharacters[ch] & allowedMask) != 0);
whereas within the if
department, there is no such thing as a && (ch != ';')
.