Hi,
when using a custom URLProtocol in combination with a POST/PUT/PATCH request and an endpoint returning a 401 auth header, the URLSession just times out. It is working as expected for a GET request.
Any idea why it is failing for requests sending data to the server?
I've created a playground to demonstrate the issue:
import Foundation
import PlaygroundSupport
class MyURLProtocol: URLProtocol, URLSessionDelegate {
override class func canInit(with request: URLRequest) -> Bool {
return true
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override func startLoading() {
let session = URLSession(configuration: URLSessionConfiguration.default)
let sessionTask = session.dataTask(with: self.request, completionHandler: { (data, response, error) in
if let error = error {
debugPrint("proto error: ", error.localizedDescription)
self.client?.urlProtocol(self, didFailWithError: error)
self.client?.urlProtocolDidFinishLoading(self)
return
}
if let response = response, let httpResponse = response as? HTTPURLResponse {
let statusCode = httpResponse.statusCode
debugPrint("proto code: ", statusCode, httpResponse.allHeaderFields)
self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .allowed)
if let data = data {
self.client?.urlProtocol(self, didLoad: data)
}
self.client?.urlProtocolDidFinishLoading(self)
return
}
self.client?.urlProtocol(self, didFailWithError: NSError(domain: "unknown", code: 0, userInfo: nil))
self.client?.urlProtocolDidFinishLoading(self)
})
sessionTask.resume()
}
}
class Test: NSObject, URLSessionDelegate {
func run() {
let config = URLSessionConfiguration.default
var protos = config.protocolClasses ?? []
protos.insert(MyURLProtocol.self, at: 0)
config.protocolClasses = protos
config.timeoutIntervalForRequest = 5
config.timeoutIntervalForResource = 5
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
let url = URL(string: "h t t p : / / dan . shaula . uberspace . de / basic")
var request = URLRequest(url: url!)
request.httpMethod = "PATCH"
request.httpBody = "{\"test\":[{\"key\":\"val\"}]}".data(using: .utf8)
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
debugPrint("org req error: ", error.localizedDescription)
}
if let response = response as? HTTPURLResponse {
debugPrint("org req code: ", response.statusCode)
}
}
task.resume()
}
}
Test().run()
PlaygroundPage.current.needsIndefiniteExecution = true
(Please remove the spaces in the url string before running it.)