Skip to content

Commit 290d49b

Browse files
Fix for URLProtocolClient doesn't deliver response and data to URLSession delegates
1 parent 6f7f692 commit 290d49b

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

Foundation/NSURLSession/NSURLSessionTask.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,20 @@ public let URLSessionDownloadTaskResumeData: String = "NSURLSessionDownloadTaskR
526526
extension _ProtocolClient : URLProtocolClient {
527527

528528
func urlProtocol(_ protocol: URLProtocol, didReceive response: URLResponse, cacheStoragePolicy policy: URLCache.StoragePolicy) {
529-
`protocol`.task?.response = response
529+
guard let task = `protocol`.task else { fatalError("Received response, but there's no task.") }
530+
task.response = response
531+
let session = task.session as! URLSession
532+
guard let dataTask = task as? URLSessionDataTask else { return }
533+
switch session.behaviour(for: task) {
534+
case .taskDelegate(let delegate as URLSessionDataDelegate):
535+
session.delegateQueue.addOperation {
536+
delegate.urlSession(session, dataTask: dataTask, didReceive: response, completionHandler: { _ in
537+
URLSession.printDebug("warning: Ignoring disposition from completion handler.")
538+
})
539+
}
540+
case .noDelegate, .taskDelegate, .dataCompletionHandler, .downloadCompletionHandler:
541+
break
542+
}
530543
}
531544

532545
func urlProtocolDidFinishLoading(_ protocol: URLProtocol) {
@@ -567,7 +580,17 @@ extension _ProtocolClient : URLProtocolClient {
567580

568581
func urlProtocol(_ protocol: URLProtocol, didLoad data: Data) {
569582
`protocol`.properties[.responseData] = data
570-
//TODO: this method needs to be extended to call the urlSession(_:dataTask:didReceive:)
583+
guard let task = `protocol`.task else { fatalError() }
584+
guard let session = task.session as? URLSession else { fatalError() }
585+
switch session.behaviour(for: task) {
586+
case .taskDelegate(let delegate):
587+
let dataDelegate = delegate as? URLSessionDataDelegate
588+
let dataTask = task as? URLSessionDataTask
589+
session.delegateQueue.addOperation {
590+
dataDelegate?.urlSession(session, dataTask: dataTask!, didReceive: data)
591+
}
592+
default: return
593+
}
571594
}
572595

573596
func urlProtocol(_ protocol: URLProtocol, didFailWithError error: Error) {

TestFoundation/TestNSURLSession.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class TestURLSession : XCTestCase {
3838
("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
3939
("test_timeoutInterval", test_timeoutInterval),
4040
("test_customProtocol", test_customProtocol),
41+
("test_customProtocolResponseWithDelegate", test_customProtocolResponseWithDelegate),
4142
("test_httpRedirection", test_httpRedirection),
4243
("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
4344
]
@@ -344,6 +345,14 @@ class TestURLSession : XCTestCase {
344345
task.resume()
345346
waitForExpectations(timeout: 12)
346347
}
348+
349+
func test_customProtocolResponseWithDelegate() {
350+
let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!
351+
let d = DataTask(with: expectation(description: "Custom protocol with delegate"), protocolClasses: [CustomProtocol.self])
352+
d.responseReceivedExpectation = expectation(description: "A response wasn't received")
353+
d.run(with: url)
354+
waitForExpectations(timeout: 12)
355+
}
347356

348357
func test_httpRedirection() {
349358
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
@@ -387,16 +396,22 @@ class DataTask : NSObject {
387396
var session: URLSession! = nil
388397
var task: URLSessionDataTask! = nil
389398
var cancelExpectation: XCTestExpectation?
399+
var responseReceivedExpectation: XCTestExpectation?
400+
var protocols: [AnyClass]?
390401

391402
public var error = false
392403

393-
init(with expectation: XCTestExpectation) {
404+
init(with expectation: XCTestExpectation, protocolClasses: [AnyClass]? = nil) {
394405
dataTaskExpectation = expectation
406+
protocols = protocolClasses
395407
}
396408

397409
func run(with request: URLRequest) {
398410
let config = URLSessionConfiguration.default
399411
config.timeoutIntervalForRequest = 8
412+
if let customProtocols = protocols {
413+
config.protocolClasses = customProtocols
414+
}
400415
session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
401416
task = session.dataTask(with: request)
402417
task.resume()
@@ -405,6 +420,9 @@ class DataTask : NSObject {
405420
func run(with url: URL) {
406421
let config = URLSessionConfiguration.default
407422
config.timeoutIntervalForRequest = 8
423+
if let customProtocols = protocols {
424+
config.protocolClasses = customProtocols
425+
}
408426
session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
409427
task = session.dataTask(with: url)
410428
task.resume()
@@ -419,6 +437,14 @@ extension DataTask : URLSessionDataDelegate {
419437
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
420438
capital = String(data: data, encoding: String.Encoding.utf8)!
421439
}
440+
441+
public func urlSession(_ session: URLSession,
442+
dataTask: URLSessionDataTask,
443+
didReceive response: URLResponse,
444+
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
445+
guard responseReceivedExpectation != nil else { return }
446+
responseReceivedExpectation!.fulfill()
447+
}
422448
}
423449

424450
extension DataTask : URLSessionTaskDelegate {

0 commit comments

Comments
 (0)