URLSession upload task loops

I'm first going to ask this without full listings and logs, because it feels like the sort of thing that people might recognize generically from their own work.

iOS 16 simulator, Xcode 14.2.

Aim

I want to upload a file to a REST server. I'm using URLSessionUploadTask. HTTP Basic authentication goes through (by the low-level fact that once I provide basic creds, URLSession stops asking).

I can assume that the bytes are getting there: My task delegate's urlSession(_:task:didSendBodyData:... is called with the right number of bytes, and equal to the expected number of bytes. I assume that's not a count of what was cast into the net, but the product of some client/server acknowledgement.

The minor odd thing is that I see in my logs is first the server-trust auth challenge, then the did-send, and only then HTTPBasic.

∞ Loop

The major odd thing is:

didReceive challenge: NSURLAuthenticationMethodServerTrust
didSend: 296 / 296
didReceive challenge: NSURLAuthenticationMethodHTTPBasic
didReceive challenge: NSURLAuthenticationMethodServerTrust
didSend: 592 / 592
didReceive challenge: NSURLAuthenticationMethodHTTPBasic

... and so on, ad infinitum, accumulating by multiples of the total data. I admit I have not checked the arithmetic on payload size, I suspect that the count is not necessarily common-sensical. If you have some experience to which the counts are critical, I'm glad to hear from you.

The delegate methods for end-of-transfer, success or failure, are never called. The closure argument for URLSession.shared.dataTask... is never called.

The server's listing page does not show the file present.

Supplement: Multipart

Content-Type: multipart/form-data; boundary=593FBDC3-7A99-415D-B6B4-3F553CB6C9C2
--Boundary-593FBDC3-7A99-415D-B6B4-3F553CB6C9C2
Content-Disposition: form-data; name="file"; filename="InputSample.zip"
Content-Type: application/zip

0123456
--Boundary-593FBDC3-7A99-415D-B6B4-3F553CB6C9C2-

I cam't help the forum's line-wrapping. The linebreaks I intend are \r\n, per the general standard. "0123456" is a part of this package as Data containing that string. I wonder if the promise of .zip content without actual .zip-formatted data is a problem. I hadn't thought J. Random Apache would be that "helpful."

Oh, and:

My upload task calls .resume() once and only once. Instruments shows no hotspot or deep stack into my code, which I'd expect in a coded infinite loop.

The major odd thing is:

This suggests that something is going wrong with the authentication challenge. This sequence looks like this:

  1. The client opens a TCP connection.

  2. It starts TLS on top of that. That triggers the server trust authentication challenge.

  3. It sends the request.

  4. The server responds with a Basic authentication challenge.

  5. The client starts the retry with the new credential, which sends you back to step 1.

A good first step in debugging problems like this is to look at the HTTP requests and responses going back and forth. See Analyzing HTTP Traffic with Instruments.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

URLSession upload task loops
 
 
Q