Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AFNetworking iOS11 - HTTP load failed -999

I have an app in production that has been running fine for a while. However, since iOS 11 - I am receiving this error:

Task <51E07EF5-6F31-4E58-8818-7712CB3E49A6>.<20> HTTP load failed (error code: -999 [1:89]) Task <51E07EF5-6F31-4E58-8818-7712CB3E49A6>.<20> finished with error - code: -999

This happens on iOS 11 only. Also, it is not consistent. Out of five requests to the same URL, two will fail with this. On a Cellular connection, it happens less often, but its still there.

I am using AFNetworking and as said; this has never been an issue until iOS11.

Any ideas?

Update to add more details:

I am using SSL Pinning with valid certificates. My info.plist looks like this:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>url.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>

Using the SSL pinning like this:

    NSString *pathToProdCert = [[NSBundle mainBundle]pathForResource:@"MY_CERT" ofType:@"cer"];

if(pathToProdCert){
       manager.securityPolicy.pinnedCertificates = [NSSet setWithObjects[NSData dataWithContentsOfFile:pathToProdCert], nil];
            manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
        }

Update: In response to the comments: this is how the manager is declared:

@property (nonatomic) AFHTTPSessionManager *manager;

The manager is initialised through an init method of my web service class:

-(instancetype)initWithBaseUrl:(NSURL *)url {

    self  = [super init];
    if (self){
        self.manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
        self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    }

    return self;
}

It is only initialised once per app session.

Update: As requested this is the userInfo inside the error that comes back:

NSErrorFailingURLKey = "https://MY_URL/PARAMS"; NSErrorFailingURLStringKey = "https://MY_URL/PARAMS"; NSLocalizedDescription = cancelled; NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-999 \"(null)\" UserInfo={_kCFStreamErrorCodeKey=89, _kCFStreamErrorDomainKey=1}"; "_kCFStreamErrorCodeKey" = 89; "_kCFStreamErrorDomainKey" = 1;

Upon more testing, I have noticed that if I recreate the network class, where the manageris declared - on each network call - I never get this error.

like image 872
Robert J. Clegg Avatar asked Feb 06 '18 14:02

Robert J. Clegg


1 Answers

-999 or ErrorCancelled

The initialized manager is not owned, and is deallocated shortly after it goes out of scope. As a result, any pending tasks are cancelled.

Create a singleton class with AFHTTPSessionManager and use that for all your requests.

YourAPIClient.h

#import "AFHTTPSessionManager.h"
@interface YourAPIClient : AFHTTPSessionManager
+(YourAPIClient *) sharedClient;
@end

YourAPIClient.m

#import "YourAPIClient.h"

@implementation YourAPIClient

//Singleton Shared Client
+(YourAPIClient *)sharedClient
{
    static YourAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

        // Initialize Session Manager
       _sharedClient = [[YourAPIClient alloc] initWithSessionConfiguration:sessionConfiguration];
        // Configure Manager
        [_sharedClient setResponseSerializer:[AFHTTPResponseSerializer serializer]];

    });

    return _sharedClient;
}
like image 79
Rukshan Avatar answered Sep 18 '22 15:09

Rukshan