Search code examples
iosafnetworking-2nsurlsession

Re-run a failed NSURLSessionTask


I was wondering if it was possible to re-run a failed NSURLSessionDataTask. Here is the context in which I am encountering this problem.

I've got a web service object which uses AFNetworking 2.0 to handle the requests. In one of my methods, I've got this:

[HTTPSessionManager GET:path parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {

} failure:^(NSURLSessionDataTask *task, NSError *error) {
    //sometimes we fail here due to a 401 and have to re-authenticate.
}];

Now, sometimes the GET request fails because the user's auth token in my backend is . So what I'd like to do is run a re-authentication block to see if we can log in again. Something like this:

[HTTPSessionManager GET:path parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {

} failure:^(NSURLSessionDataTask *task, NSError *error) {
    if (task.response.statusCode == 401)
       RunReAuthenticationBlockWithSuccess:^(BOOL success) {
           //somehow re-run 'task'
        } failure:^{}
}];

Is there any way to start the task over again?

Thanks!


Solution

  • If anyone is still interested, I ended up implementing my solution by subclassing HTTPSessionManager like so:

    typedef void(^AuthenticationCallback)(NSString *updatedAuthToken, NSError *error);
    typedef void(^AuthenticationBlock)(AuthenticationCallback);
    
    
    @interface MYHTTPSessionManager : AFHTTPSessionManager
    @property (nonatomic, copy) AuthenticationBlock authenticationBlock;
    @end
    
    @implementation MYHTTPSessionManager
    
    
    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    
    void (^callback)(NSString *, NSError *) = ^(NSString *tokenString, NSError *error) {
        if (tokenString) {
            //ugh...the request here needs to be re-serialized. Can't think of another way to do this
            NSMutableURLRequest *mutableRequest = [request mutableCopy];
            [mutableRequest addValue:AuthorizationHeaderValueWithTokenString(tokenString) forHTTPHeaderField:@"Authorization"];
            NSURLSessionDataTask *task = [super dataTaskWithRequest:[mutableRequest copy] completionHandler:completionHandler];
            [task resume];
        } else {
            completionHandler(nil, nil, error);
        }
    };
    
    void (^reauthCompletion)(NSURLResponse *, id, NSError *) = ^(NSURLResponse *response, id responseObject, NSError *error){
    
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        NSInteger unauthenticated = 401;
        if (httpResponse.statusCode == unauthenticated) {
            if (self.authenticationBlock != NULL) {
                self.authenticationBlock(callback); return;
            }
        }
    
        completionHandler(response, responseObject, error);
    };
    
    return [super dataTaskWithRequest:request completionHandler:reauthCompletion];
    }
    
    @end