哪种URL不符合RFC 3986,但符合RFC 1808,RFC 1738和RFC 2732?

时间:2019-04-10 09:20:37

标签: swift url nsurl rfc3986 nsurlcomponents

URLComponents.init(url:resolvingAgainstBaseURL:)的文档说:

  

返回初始化的URL组件对象;如果无法解析URL,则返回nil。

知道:

我假设URL符合RFC 1808/1738/2732但不符合RFC 3986时,URLComponents的初始化将失败。那是什么类型的URL?有什么例子吗?

我到目前为止唯一的暗示可能与不同的保留字符有关?

1 个答案:

答案 0 :(得分:2)

由于Swift Foundation是开源的,因此让我们从源代码中进行探索。

  1. URLComponents初始化程序在apple/swift – URLComponents.swiftapple/swift-corelibs-foundation – URLComponents.swift中实现,并且仅调用NSURLComponents的初始化程序。

  2. NSURLComponents初始化程序是在apple/swift-corelibs-foundation – NSURL.swift中实现的,只需调用_CFURLComponentsCreateWithURL

  3. _CFURLComponentsCreateWithURLapple/swift-corelibs-foundation – CFURLComponents.c中实现,并且可以:

    • 带有CFURLCopyAbsoluteURL的失败副本
    • 使用_CFURLComponentsCreateWithString的失败创建,它调用:
      • _CFURIParserParseURIReference +失败的_CFURIParserURLStringIsValid
  4. CFURLCopyAbsoluteURLapple/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的实现在opensource.apple.com/source/CF – CFURL.c中,我的理解是,只有在没有方案或路径的情况下它才会失败,这在我们之前对文件进行测试时是不可能的方案或文件存在CFURLIsFileReferenceURL

  5. _CFURIParserParseURIReferenceapple/swift-corelibs-foundation – CFURLComponents_URIParser.c中实现,并且只有在URL长度超过2 GB时才会失败,我认为这与RFC规范无关。

  6. _CFURIParserURLStringIsValid实际上将为每个组件调用_CFURIParserValidateComponent,并且对于无效字符或转义序列将失败。 这可能是最相关的部分。

现在,通过一些实验,我们知道我们需要一个方案(例如https://或简单的a://),并且我们使用保留字符来举例,例如: / p>

// 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差异)as seen in URL.swift

  

//将来的实现说明:
     // NSURL(实际上是CFURL,提供其实现)在处理一些更深奥的(有些不是那么深奥的)字符串时有很多怪癖。我们想将其中的大部分转移到更现代的NSURLComponents上,但是二进制兼容性问题使这变得很困难。
     //希望很快,我们可以将以下某些对NSURL的委托替换为对NSURLComponents的委托。不能零星地完成它,因为否则我们将从API中获得不一致的结果。

我不确定他们计划如何执行此操作,因为这将意味着URL(string: "a://@@")将失败或URLComponents(string: "a://@@")将成功。