I'm having this weird issue in which a newly created URLSessionUploadTask gets cancelled instantly. I'm not sure if it's a bug with the current beta of Xcode 8.
I'm trying to build a Framework project.
I suspect it might be a bug because the code I'm about to post ran fine exactly once. No changes were made to it afterwards and then it simply stopped working. Yes, it literally ran once, and then it stopped working. I will post the error near the end.
I will post the code below, but first I will summarize how the logic here works.
My test, or user-exposed API (IE for use in Playgrounds or directly on apps), calls the `authorize` method. This `authorize` method will in turn call `buildPOSTTask`, which will construct a valid URL and return a `URLSessionUploadTask` to be used by the `authorize` method.
With that said, the code is below:
The session:
internal let urlSession = URLSession(configuration: .default)
Function to create an upload task:
internal func buildPOSTTask(onURLSession urlSession: URLSession, appendingPath path: String, withPostParameters postParams: [String : String]?, getParameters getParams: [String : String]?, httpHeaders: [String : String]?, completionHandler completion: URLSessionUploadTaskCompletionHandler) -> URLSessionUploadTask {
let fullURL: URL
if let gets = getParams {
fullURL = buildURL(appendingPath: path, withGetParameters: gets)
} else {
fullURL = URL(string: path, relativeTo: baseURL)!
}
var request = URLRequest(url: fullURL)
request.httpMethod = "POST"
var postParameters: Data? = nil
if let posts = postParams {
do {
postParameters = try JSONSerialization.data(withJSONObject: posts, options: [])
} catch let error as NSError {
fatalError("[\(#function) \(#line)]: Could not build POST task: \(error.localizedDescription)")
}
}
let postTask = urlSession.uploadTask(with: request, from: postParameters, completionHandler: completion)
return postTask
}
The authentication function, which uses a task created by the above function (I have removed a lot of irrelevant code):
public func authorize(withCode code: String?, completion: AccessTokenExchangeCompletionHandler) {
// I hav
let obtainTokenTask = buildPOSTTask(onURLSession: self.urlSession, appendingPath: "auth/access_token", withPostParameters: nil, getParameters: body, httpHeaders: nil) { (data, response, error) in
if let err = error {
completion(error: err)
} else {
print("Response is \(response)")
completion(error: nil)
}
}
obtainTokenTask.resume()
}
I caught this error in a test:
let testUser = Anilist(grantType: grant, name: "Test Session")
let exp = expectation(withDescription: "Waiting for authorization")
testUser.authorize(withCode: "a valid code") { (error) in
if let er = error {
XCTFail("Authentication error: \(er.localizedDescription)")
}
exp.fulfill()
}
self.waitForExpectations(withTimeout: 5) { (err) in
if let error = err {
XCTFail(error.localizedDescription)
}
}
It always fails instantly with this error:
Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED,
NSLocalizedDescription=cancelled,
NSErrorFailingURLStringKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED}
Here's a few things to keep in mind:
- The URL used by the session is valid.
- All credentials are valid.
- It fails *instantly* with a "cancelled" error, that simply did not happen before. I am not cancelling the task anywhere, so it's being cancelled by the system. It doesn't look like it has time to hit the network, because the test fails as soon as it is started.
- **It also fails on Playgrounds with indefinite execution enabled**. This is not limited to my tests.
Here's a list of things I have tried:
- Because I suspect this is a bug, I first tried to clean my project, delete derived data, and reset all simulators. None of them worked.
- Even went as far restarting my Mac...
- Under the small suspicion that the upload task was getting deallocated due to it not having any strong pointers, and in turn calling `cancel`, I also rewrote `authorize` to return the task created by `buildPOSTTask` and assigned it to a variable in my test. The task was still getting cancelled.
I'm out of ideas of what to try. The generated logs don't seem to have any useful info.
(If anyone is willing to go above and beyond to help me, I can upload the whole project here, since it will be open source anyway. The project is really small currently, consisting of three small Swift files and one test file).
The from parameter of uploadTask(with:from:completionHandler) cannot be nil. While the signature of the method does mark from as a Data?, the task gets automatically cancelled when it is missing/nil.
I have had a radar on this for a few years (FB5986524), but I never got any response.