Какой тип URL не соответствует RFC 3986, но соответствует RFC 1808, RFC 1738 и RFC 2732?

Документ о URLComponents.init(url:resolvingAgainstBaseURL:)говорит:

Возвращает инициализированный объект компонентов URL или nil, если URL не может быть проанализирован.

Знаю это:

Я предполагаю, что инициализацияURLComponentsпотерпит неудачу, когда URL соответствует RFC 1808/1738/2732, но не RFC 3986.Что это за URL? Любой пример?

Единственный совет, который я имею, поскольку разница может быть связана с различными зарезервированными символами?

1 ответ

Решение

Давайте рассмотрим его из его исходного кода, поскольку Swift Foundation является открытым исходным кодом.

  1. URLComponents инициализатор реализован в apple / swift - URLComponents.swift и apple / swift-corelibs-foundation - URLComponents.swift и просто вызывает инициализатор NSURLComponents,

  2. NSURLComponents инициализатор реализован в apple / swift-corelibs-foundation - NSURL.swift и просто вызывает _CFURLComponentsCreateWithURL,

  3. _CFURLComponentsCreateWithURL реализуется в apple / swift-corelibs-foundation - CFURLComponents.c и выполняет:

    • неудачная копия с CFURLCopyAbsoluteURL
    • неудачное создание с _CFURLComponentsCreateWithString который звонит:
      • _CFURIParserParseURIReference + неудачный _CFURIParserURLStringIsValid
  4. 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,

  5. _CFURIParserParseURIReference реализован в apple / swift-corelibs-foundation - CFURLComponents_URIParser.c и завершится сбоем только в том случае, если длина URL-адреса превышает 2 ГБ, что, я считаю, не связано со спецификациями RFC.

  6. _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://@@") будет успешным.

Другие вопросы по тегам