Unable to catch errors thrown from NSURLConnection.sendSynchronousRequest in Swift when HTTP response body is not nil

Originator:aaronmaxlevy
Number:rdar://FB8955913 Date Originated:12/28/2020
Status:Open Resolved:
Product:macOS Product Version:
Classification: Reproducible:
 
Basic Information
Please provide a descriptive title for your feedback:
Unable to catch errors thrown from NSURLConnection.sendSynchronousRequest in Swift when HTTP response body is not nil
Which area are you seeing an issue with?
Foundation
What type of issue are you reporting?
Incorrect/Unexpected Behavior
Description
Please describe the issue and what steps we can take to reproduce it:
The NSURLConnection.sendSynchronousRequest function will return a non-nil value when there is an error, as long as a valid HTTP response was received with a "Content-Length" greater than 0. Because of how Swift / Objective-C error interoperability works, the error pointer is only checked if the function itself returns nil.

Expected Behavior:
1. Use NSURLConnection.sendSynchronousRequest to call an HTTP endpoint that returns a "401 Unauthorized" status code, but also containing content in the body (i.e. Content-Length greater than 0)
2. NSURLConnection.sendSynchronousRequest throws an NSError (specifically "Error Domain=NSURLErrorDomain Code=-1012") which can be caught in Swift

Actual Behavior:
1. Use NSURLConnection.sendSynchronousRequest to call an HTTP endpoint that returns a "401 Unauthorized" status code, but also containing content in the body (i.e. Content-Length greater than 0)
2. NSURLConnection.sendSynchronousRequest throws an NSError (specifically "Error Domain=NSURLErrorDomain Code=-1012") which Swift does not catch because sendSynchronousRequest also returns a non-nil value (an NSData object containing the body of the response). Note that the response (URLResponse) pointer is nil in this case, so by dropping the NSError, it makes it nearly impossible to tell what the actual error/issue is.

While I'm aware that NSURLConnection is deprecated, a Github search for Swift code calling this function ( https://github.com/search?l=Swift&q=NSURLConnection.sendSynchronousRequest&type=Code ) returns over 1000 results, and so I believe this is worth fixing.

Comments

Response from Apple

After reviewing your feedback, we have some additional information for you, or some additional information, or action is necessary for this issue:

This is a source-breaking change that is no longer allowed in Swift 4 and later versions. Please switch to URLSession, or call this method in Objective-C.

By aaronmaxlevy at Jan. 7, 2021, 6:49 p.m. (reply...)

In this case, I would suggest fixing this by adding __attribute__((swift_error(nonnull_error))) to the end of the method definition in the header.

By aaronmaxlevy at Dec. 29, 2020, 7:44 p.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!