【问题标题】:What kind of URL is not conforming to RFC 3986 but is conforming to RFC 1808, RFC 1738, and RFC 2732?什么样的 URL 不符合 RFC 3986 但符合 RFC 1808、RFC 1738 和 RFC 2732?
【发布时间】:2019-08-31 16:52:49
【问题描述】:

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

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

知道:

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

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

【问题讨论】:

    标签: swift url nsurl rfc3986 nsurlcomponents


    【解决方案1】:

    让我们从它的源代码来探索它,因为 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中,我的理解是只有在没有scheme或者没有路径的情况下才会失败,这应该是不可能的,因为我们之前测试过文件scheme或者文件存在CFURLIsFileReferenceURL

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

    6. _CFURIParserURLStringIsValid 本质上会为每个组件调用_CFURIParserValidateComponent,并因无效字符或转义序列而失败。 这可能是最相关的部分。

    现在,通过一些实验,我们知道我们需要一个方案(例如,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 差异)as seen in URL.swift

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

    我不确定他们打算如何做到这一点,因为这意味着URL(string: "a://@@") 将失败或URLComponents(string: "a://@@") 将成功。

    【讨论】:

    • 这真的很有趣,谢谢!还帮助我摆脱了在我的代码覆盖率报告中困扰我的一行红色 - 即使是这样一个边缘情况!
    • 聪明的香肠 :-)
    猜你喜欢
    • 2010-10-25
    • 2019-06-14
    • 2011-10-25
    • 2011-11-20
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 2019-07-11
    相关资源
    最近更新 更多