|
| 1 | +# New HTTP loader for URLSession |
| 2 | + |
| 3 | +* Proposal: [SF-0018](0018-urlsession-new-loader.md) |
| 4 | +* Authors: [Guoye Zhang](https://github.com/guoye-zhang) |
| 5 | +* Review Manager: [Tina L](https://github.com/itingliu) |
| 6 | +* Status: **Accepted** |
| 7 | +* Implementation: [swiftlang/swift-corelibs-foundation#5162](https://github.com/swiftlang/swift-corelibs-foundation/pull/5162) |
| 8 | +* Review: ([pitch](https://forums.swift.org/t/pitch-new-http-loader-for-urlsession-on-darwin/77440)) |
| 9 | + |
| 10 | +## Introduction |
| 11 | + |
| 12 | +The new HTTP stack built in Network framework was enabled in Safari on iOS 18 and macOS Sequoia. It supports new features like 0-RTT early data, oblivious HTTP, WebSocket over HTTP/2, and unix domain socket. Support for FTP and HTTP/1 pipelining was dropped. |
| 13 | + |
| 14 | +In this proposal, we are introducing an API to enable the new HTTP loader in URLSession on Darwin, as well as deprecating several legacy features not supported in the new stack. |
| 15 | + |
| 16 | +## Proposed solution |
| 17 | + |
| 18 | +Introducing a new flag `usesClassicLoadingMode` that defaults to true on URLSessionConfiguration to allow developers to opt-in to the new stack. |
| 19 | + |
| 20 | +The flag is not available on non-Darwin platforms at this moment. |
| 21 | + |
| 22 | +## Detailed design |
| 23 | + |
| 24 | +### Opt-in flag |
| 25 | + |
| 26 | +The new loader is enabled when `usesClassicLoadingMode` is set to false. `usesClassicLoadingMode` currently defaults to true, but might default to false in a future OS. |
| 27 | + |
| 28 | +```swift |
| 29 | +open class URLSessionConfiguration { |
| 30 | + |
| 31 | + /* Uses the classic network loader */ |
| 32 | + @available(*, unavailable, message: "Not available on non-Darwin platforms") |
| 33 | + open var usesClassicLoadingMode: Bool |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +### Deprecations |
| 38 | + |
| 39 | +* FTP was deprecated in the old stack and unsupported in the new stack. |
| 40 | +* HTTP/1 pipelining is not supported in the new HTTP stack. It is disabled by default in the old stack and has known compatibility issues with some servers. |
| 41 | +* Server push was disabled in both stacks on iOS 17 and aligned releases due to low adoption and web compatibility issues. |
| 42 | +* `NSURLErrorFailingURLStringErrorKey` is redundant with `NSURLErrorFailingURLErrorKey` and it is incompatible with WHATWG URLs. |
| 43 | +* `shouldUseExtendedBackgroundIdleMode` was not supported in either the old stack or the new stack. |
| 44 | + |
| 45 | +```swift |
| 46 | +public struct URLRequest { |
| 47 | + |
| 48 | + @available(swift, deprecated: 6.1, message: "HTTP/1 pipelining has known compatibility issues, please adopt HTTP/2 and HTTP/3 instead") |
| 49 | + public var httpShouldUsePipelining: Bool |
| 50 | +} |
| 51 | + |
| 52 | +open class NSURLRequest { |
| 53 | + |
| 54 | + @available(swift, deprecated: 6.1, message: "HTTP/1 pipelining has known compatibility issues, please adopt HTTP/2 and HTTP/3 instead") |
| 55 | + open var httpShouldUsePipelining: Bool { get } |
| 56 | +} |
| 57 | + |
| 58 | +open class NSMutableURLRequest { |
| 59 | + |
| 60 | + @available(swift, deprecated: 6.1, message: "HTTP/1 pipelining has known compatibility issues, please adopt HTTP/2 and HTTP/3 instead") |
| 61 | + open override var httpShouldUsePipelining: Bool |
| 62 | +} |
| 63 | + |
| 64 | +open class URLSessionConfiguration { |
| 65 | + |
| 66 | + @available(swift, deprecated: 6.1, message: "HTTP/1 pipelining has known compatibility issues, please adopt HTTP/2 and HTTP/3 instead") |
| 67 | + open var httpShouldUsePipelining: Bool |
| 68 | + |
| 69 | + @available(swift, deprecated: 6.1, message: "Not supported") |
| 70 | + open var shouldUseExtendedBackgroundIdleMode: Bool |
| 71 | +} |
| 72 | + |
| 73 | +public enum URLSessionTaskMetrics.ResourceFetchType { |
| 74 | + |
| 75 | + @available(swift, deprecated: 6.1, message: "Server push is not supported") |
| 76 | + case serverPush |
| 77 | +} |
| 78 | + |
| 79 | +public struct URLError { |
| 80 | + |
| 81 | + @available(swift, deprecated: 6.1, message: "Use failingURL instead") |
| 82 | + public var failureURLString: String? |
| 83 | +} |
| 84 | + |
| 85 | +@available(swift, deprecated: 6.1, message: "Use NSURLErrorFailingURLErrorKey instead") |
| 86 | +public let NSURLErrorFailingURLStringErrorKey: String |
| 87 | + |
| 88 | +@available(swift, deprecated: 6.1, message: "FTP is deprecated") |
| 89 | +public let NSURLProtectionSpaceFTP: String |
| 90 | + |
| 91 | +@available(swift, deprecated: 6.1, message: "FTP is deprecated") |
| 92 | +public let NSURLProtectionSpaceFTPProxy: String |
| 93 | +``` |
| 94 | + |
| 95 | +## Source compatibility |
| 96 | + |
| 97 | +No impact. |
| 98 | + |
| 99 | +## Implications on adoption |
| 100 | + |
| 101 | +This feature can be freely adopted and un-adopted in source code with no deployment constraints and without affecting source compatibility. |
| 102 | + |
| 103 | +## Future directions |
| 104 | + |
| 105 | +The new HTTP stack might become the default on a future Darwin release. |
| 106 | + |
| 107 | +## Alternatives considered |
| 108 | + |
| 109 | +### Alternative spelling `usesNewLoader` |
| 110 | + |
| 111 | +The initial idea was an opt-in flag where YES means the new loader, and we considered multiple variants, including `usesModernLoader`, `usesNWLoader` (NW stands for Network framework). However, this makes it hard to come up with names for newer loaders in the future, and an opt-out flag gives the impression that the new loader is the default, not the exception. |
0 commit comments