Какой тип URL не соответствует RFC 3986, но соответствует RFC 1808, RFC 1738 и RFC 2732?
Документ о URLComponents.init(url:resolvingAgainstBaseURL:)
говорит:
Возвращает инициализированный объект компонентов URL или nil, если URL не может быть проанализирован.
Знаю это:
- Swift URL / NSURL предназначен для URL на основе RFC 1808, RFC 1738 и RFC 2732: https://developer.apple.com/documentation/foundation/nsurl
- Swift URLComponents / NSURLComponents предназначен для URL-адресов на основе RFC 3986: https://developer.apple.com/documentation/foundation/nsurlcomponents
Я предполагаю, что инициализацияURLComponents
потерпит неудачу, когда URL соответствует RFC 1808/1738/2732, но не RFC 3986.Что это за URL? Любой пример?
Единственный совет, который я имею, поскольку разница может быть связана с различными зарезервированными символами?
1 ответ
Давайте рассмотрим его из его исходного кода, поскольку Swift Foundation является открытым исходным кодом.
URLComponents
инициализатор реализован в apple / swift - URLComponents.swift и apple / swift-corelibs-foundation - URLComponents.swift и просто вызывает инициализаторNSURLComponents
,NSURLComponents
инициализатор реализован в apple / swift-corelibs-foundation - NSURL.swift и просто вызывает_CFURLComponentsCreateWithURL
,_CFURLComponentsCreateWithURL
реализуется в apple / swift-corelibs-foundation - CFURLComponents.c и выполняет:- неудачная копия с
CFURLCopyAbsoluteURL
- неудачное создание с
_CFURLComponentsCreateWithString
который звонит:_CFURIParserParseURIReference
+ неудачный_CFURIParserURLStringIsValid
- неудачная копия с
CFURLCopyAbsoluteURL
реализован в apple / swift-corelibs-foundation - CFURL.c и не работает только для:#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED if ( base && CFURLIsFileReferenceURL(base) && !CFURLHasDirectoryPath(base) ) { // 16695827 - If the base URL is a file reference URL which doesn't end with a slash, we have to convert it to a file path URL before we can make it absolute. base = CFURLCreateFilePathURL(alloc, base, NULL); if ( !base ) { // could not convert file reference URL to file path URL -- fail will NULL return NULL; } } #endif
Реализация
CFURLCreateFilePathURL
находится в https://opensource.apple.com/source/CF/CF-1153.18/CFURL.c.auto.html, и я понимаю, что он потерпит неудачу только в том случае, если отсутствует схема или отсутствует путь, что не должно быть возможным, поскольку мы ранее тестировали файловую схему или файл существование сCFURLIsFileReferenceURL
,_CFURIParserParseURIReference
реализован в apple / swift-corelibs-foundation - CFURLComponents_URIParser.c и завершится сбоем только в том случае, если длина URL-адреса превышает 2 ГБ, что, я считаю, не связано со спецификациями RFC._CFURIParserURLStringIsValid
по существу позвонит_CFURIParserValidateComponent
для каждого компонента и сбой для недопустимых символов или escape-последовательностей. Это, возможно, самая важная часть.
Теперь, с небольшим количеством экспериментов, мы знаем, что нам нужна схема (например, https://
или просто a://
) и мы играем с зарезервированными символами, чтобы придумать примеры, такие как:
// OK
let url = URL(string: "a://@@")!
// CRASH
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
Попытка альтернативного инициализатора URLComponents
также потерпит неудачу, поэтому не пытайтесь думать, что это по-другому:
// CRASH
let components = URLComponents(string: url.absoluteString)!
Заключение
"a://@@"
пример допустимого NSURL, но недействительного RFC 3986
Кстати, некоторые пользователи Swift, похоже, хотят в будущем объединить поддержку URL и URLComponents (больше никаких различий в RFC), как это видно в URL.swift:
// Примечание о будущей реализации:
// NSURL (на самом деле CFURL, который обеспечивает его реализацию) имеет довольно много особенностей при обработке некоторых более эзотерических (и некоторых не очень эзотерических) строк. Мы хотели бы перенести большую часть этого на более современные NSURLComponents, но проблемы двоичного компатации сделали это трудным.
// Надеемся, что скоро мы сможем заменить некоторые из представленных ниже делегаций в NSURL вместо делегирования в NSURLComponents. Это невозможно сделать по частям, потому что в противном случае мы получим противоречивые результаты от API.
Я не уверен, как они планируют это сделать, так как это будет означать, что либо URL(string: "a://@@")
потерпит неудачу или URLComponents(string: "a://@@")
будет успешным.