Skip to content

Commit c26f465

Browse files
Pushkar N Kulkarniparkera
authored andcommitted
Updating PR 299 (NSURLSession) to work with the latest Foundation (#426)
Also includes support for downloadTask and uploadTask with Data and a completion handler. The original PR 299 doesn't build on Ubuntu 14.04, due to an older level of libcurl. This rework removes some of that code (it does not affect any functionality). Updated to use the Dispatch 3.0 API. Includes basic tests with external URLs.
1 parent a08e895 commit c26f465

20 files changed

+5830
-812
lines changed

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <CoreFoundation/CFXMLInterface.h>
2424
#include <CoreFoundation/CFRegularExpression.h>
2525
#include <CoreFoundation/CFLogUtilities.h>
26+
#include <CoreFoundation/CFURLSessionInterface.h>
2627
#include <CoreFoundation/ForFoundationOnly.h>
2728
#include <fts.h>
2829
#include <pthread.h>

CoreFoundation/URL.subproj/CFURLSessionInterface.c

Lines changed: 609 additions & 0 deletions
Large diffs are not rendered by default.

CoreFoundation/URL.subproj/CFURLSessionInterface.h

Lines changed: 605 additions & 0 deletions
Large diffs are not rendered by default.

Foundation/NSData.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
164164
if url.isFileURL {
165165
try self.init(contentsOfFile: url.path, options: readOptionsMask)
166166
} else {
167-
let session = URLSession(configuration: URLSessionConfiguration.defaultSessionConfiguration())
167+
let session = URLSession(configuration: URLSessionConfiguration.default)
168168
let cond = NSCondition()
169169
var resError: NSError?
170170
var resData: Data?
171-
let task = session.dataTaskWithURL(url, completionHandler: { (data: Data?, response: URLResponse?, error: NSError?) -> Void in
171+
let task = session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: NSError?) -> Void in
172172
resData = data
173173
resError = error
174174
cond.broadcast()

Foundation/NSURLSession.swift

Lines changed: 0 additions & 805 deletions
This file was deleted.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Foundation/NSURLSession/Configuration.swift - NSURLSession & libcurl
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
// -----------------------------------------------------------------------------
12+
///
13+
/// These are libcurl helpers for the URLSession API code.
14+
/// - SeeAlso: https://curl.haxx.se/libcurl/c/
15+
/// - SeeAlso: NSURLSession.swift
16+
///
17+
// -----------------------------------------------------------------------------
18+
19+
20+
internal extension URLSession {
21+
/// This is an immutable / `struct` version of `URLSessionConfiguration`.
22+
struct _Configuration {
23+
/// identifier for the background session configuration
24+
let identifier: String?
25+
26+
/// default cache policy for requests
27+
let requestCachePolicy: NSURLRequest.CachePolicy
28+
29+
/// default timeout for requests. This will cause a timeout if no data is transmitted for the given timeout value, and is reset whenever data is transmitted.
30+
let timeoutIntervalForRequest: TimeInterval
31+
32+
/// default timeout for requests. This will cause a timeout if a resource is not able to be retrieved within a given timeout.
33+
let timeoutIntervalForResource: TimeInterval
34+
35+
/// type of service for requests.
36+
let networkServiceType: NSURLRequest.NetworkServiceType
37+
38+
/// allow request to route over cellular.
39+
let allowsCellularAccess: Bool
40+
41+
/// allows background tasks to be scheduled at the discretion of the system for optimal performance.
42+
let discretionary: Bool
43+
44+
/// The proxy dictionary, as described by <CFNetwork/CFHTTPStream.h>
45+
let connectionProxyDictionary: [AnyHashable : Any]?
46+
47+
/// Allow the use of HTTP pipelining
48+
let httpShouldUsePipelining: Bool
49+
50+
/// Allow the session to set cookies on requests
51+
let httpShouldSetCookies: Bool
52+
53+
/// Policy for accepting cookies. This overrides the policy otherwise specified by the cookie storage.
54+
let httpCookieAcceptPolicy: HTTPCookie.AcceptPolicy
55+
56+
/// Specifies additional headers which will be set on outgoing requests.
57+
/// Note that these headers are added to the request only if not already present.
58+
59+
let httpAdditionalHeaders: [String : String]?
60+
/// The maximum number of simultanous persistent connections per host
61+
let httpMaximumConnectionsPerHost: Int
62+
63+
/// The cookie storage object to use, or nil to indicate that no cookies should be handled
64+
let httpCookieStorage: HTTPCookieStorage?
65+
66+
/// The credential storage object, or nil to indicate that no credential storage is to be used
67+
let urlCredentialStorage: URLCredentialStorage?
68+
69+
/// The URL resource cache, or nil to indicate that no caching is to be performed
70+
let urlCache: URLCache?
71+
72+
/// Enable extended background idle mode for any tcp sockets created.
73+
let shouldUseExtendedBackgroundIdleMode: Bool
74+
75+
let protocolClasses: [AnyClass]?
76+
}
77+
}
78+
internal extension URLSession._Configuration {
79+
init(URLSessionConfiguration config: URLSessionConfiguration) {
80+
identifier = config.identifier
81+
requestCachePolicy = config.requestCachePolicy
82+
timeoutIntervalForRequest = config.timeoutIntervalForRequest
83+
timeoutIntervalForResource = config.timeoutIntervalForResource
84+
networkServiceType = config.networkServiceType
85+
allowsCellularAccess = config.allowsCellularAccess
86+
discretionary = config.discretionary
87+
connectionProxyDictionary = config.connectionProxyDictionary
88+
httpShouldUsePipelining = config.httpShouldUsePipelining
89+
httpShouldSetCookies = config.httpShouldSetCookies
90+
httpCookieAcceptPolicy = config.httpCookieAcceptPolicy
91+
httpAdditionalHeaders = config.httpAdditionalHeaders.map { convertToStringString(dictionary: $0) }
92+
httpMaximumConnectionsPerHost = config.httpMaximumConnectionsPerHost
93+
httpCookieStorage = config.httpCookieStorage
94+
urlCredentialStorage = config.urlCredentialStorage
95+
urlCache = config.urlCache
96+
shouldUseExtendedBackgroundIdleMode = config.shouldUseExtendedBackgroundIdleMode
97+
protocolClasses = config.protocolClasses
98+
}
99+
}
100+
101+
// Configure NSURLRequests
102+
internal extension URLSession._Configuration {
103+
func configure(request: NSMutableURLRequest) {
104+
httpAdditionalHeaders?.forEach {
105+
guard request.value(forHTTPHeaderField: $0.0) == nil else { return }
106+
request.setValue($0.1, forHTTPHeaderField: $0.0)
107+
}
108+
}
109+
func setCookies(on request: NSMutableURLRequest) {
110+
if httpShouldSetCookies {
111+
//TODO: Ask the cookie storage what cookie to set.
112+
}
113+
}
114+
}
115+
// Cache Management
116+
private extension URLSession._Configuration {
117+
func cachedResponse(forRequest request: NSURLRequest) -> CachedURLResponse? {
118+
//TODO: Check the policy & consult the cache.
119+
// There's more detail on how this should work here:
120+
// <https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/index.html#//apple_ref/swift/enum/c:@E@URLRequestCachePolicy>
121+
switch requestCachePolicy {
122+
default: return nil
123+
}
124+
}
125+
}
126+
127+
private func convertToStringString(dictionary: [AnyHashable:Any]) -> [String: String] {
128+
//TODO: There's some confusion about [NSObject:AnyObject] vs. [String:String] for headers.
129+
// C.f. <https://github.com/apple/swift-corelibs-foundation/pull/287>
130+
var r: [String: String] = [:]
131+
dictionary.forEach {
132+
let k = String(describing: $0.key as! NSString)
133+
let v = String(describing: $0.value as! NSString)
134+
r[k] = v
135+
}
136+
return r
137+
}

0 commit comments

Comments
 (0)