1
votes

I have some long standing code that has used NSUrlConnection to make async requests, and a completionHandler block to handle it. I switched over to NSUrlSession not long ago, for some small extras, but mainly assumed they were similar in implementations. They both took my completionHandler block in the same way, and called it on completion. The setup is a little different.

Recently I discovered a disturbing problem, that the NSUrlSession is not returning an NSError to the completionHandler block when an error actually occurs. The use case is for a http 401 auth issue, which normally comes back with a NSError code -1012. For NSUrlSession, the NSError is nil.

This is true whether I'm using delegates for it or not. And didFailWithError delegate isn't returned either.

Why would NSUrlSession not be returning this error??

void (^connectionCompletionHandlerBlock)(NSData *data, NSURLResponse *response, NSError *error) = ^(NSData *data, NSURLResponse *response, NSError *error){
   if(error){
      // handle error
      if(error.code == -1012){  // such as http 401 login error
         // auth error
      }
   } else {
      // no error
   }
}

NSString *url = @"http://blahblah.com";
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];

// configure urlRequest with params, etc

NSUrlConnection way: (nserror -1012 returned for 401 error)

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:connectionCompletionHandlerBlock];

NSUrlSession way: (no nserror -1012 returned for 401 error)

NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest completionHandler:connectionCompletionHandlerBlock];
[task resume];

The NSError I expected to get for my 401:

Error Domain=NSURLErrorDomain Code=-1012 "(null)" UserInfo={NSErrorFailingURLStringKey=https://api/blah, NSUnderlyingError=0x600004047890 {Error Domain=kCFErrorDomainCFNetwork Code=-1012 "(null)" UserInfo={_kCFURLErrorAuthFailedResponseKey={url = https://api/blah}}}, NSErrorFailingURLKey=https://api/blah}

1

1 Answers

3
votes

Discovered after a little research. NSUrlSession does not return server side errors, by design.

From the NSUrlSession Apple documentation

Note: NSURLSession does not report server errors through the error parameter. The only errors your app receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host.

Server-side errors are reported through the HTTP status code in the NSHTTPURLResponse object. For more information, read the documentation for the NSHTTPURLResponse and NSURLResponse classes.