api - iOS - Re-Attempt Failed NSURLRequests In NSURLSession -


in app, 2-4 api calls server can happening @ same time (asynchronously) within api class's nsurlsession. in order make api requests server, must supply authentication token in httpheaderfield of each nsurlrequest. token valid 1 day, , if becomes invalid after 1 day, need refresh token.

i in following code in api class:

/*!  * @brief sends request nshttpurlresponse. method private.  * @param request request send.  * @param success block called if request successful.  * @param error block called if request fails.  */ -(void)sendtask:(nsurlrequest*)request successcallback:(void (^)(nsdictionary*))success errorcallback:(void (^)(nsstring*))errorcallback {     nsurlsessiondatatask *task = [self.session datataskwithrequest:request completionhandler:^(nsdata *data, nsurlresponse *response, nserror *error)     {         [self parseresponse:response data:data fromrequest:request successcallback:success errorcallback:^(nsstring *error)         {             //if auth token expired , getting "not authenticated" error (status 401)             nshttpurlresponse *httpresp = (nshttpurlresponse*) response;             if (httpresp.statuscode == 401) {                 [self refreshauthenticationtokenwithsuccesscallback:^(nsdictionary *response) {                     self.authtoken = response[@"token"];                     //attempt re-try request failed due token expiration                     [self sendtask:request successcallback:success errorcallback:errorcallback];                 } errorcallback:^(nsstring *error) {                     //two weeks have passed , token no longer refreshable                     nslog(@"token not refreshable! have log in manually");                 }];             }         }];     }];     [task resume]; } 

this sendtask method gets executed every api request make in app, realized bad way of doing it. if 3 api requests fail due token being invalid (one day passed), 3 of these api requests going attempt make api call refresh authentication token.

is there way me to, in case 1 of api requests fail, refresh authentication token once , re-attempt failed api calls?

edit

i edited title of question indicate i'm working nsurlsession

progress

so far, prevent several failed api requests trying refresh authentication token @ same time, have nsarray failed requests , nsnumber serves lock make sure authentication token trying refreshed once. in following code:

-(void)sendtask:(nsurlrequest*)request successcallback:(void (^)(nsdictionary*))success errorcallback:(void (^)(nsstring*))errorcallback {     nsurlsessiondatatask *task = [self.session datataskwithrequest:request completionhandler:^(nsdata *data, nsurlresponse *response, nserror *error)     {         myapiinterface *__weak weakself = self;         [self parseresponse:response data:data fromrequest:request successcallback:success errorcallback:^(nsstring *error)         {             nshttpurlresponse *httpresp = (nshttpurlresponse*) response;             if (httpresp.statuscode == 401) {                 if ([error isequaltostring:@"invalid_credentials"]) {                     errorcallback(@"invalid username and/or password");                 }                 else if ([error isequaltostring:@"unknown error"]) {                     errorcallback(error);                 }                 else {                     if (!weakself.alreadyrefreshingtoken.boolvalue) {                          //lock alreadyrefreshingtoken boolean                         weakself.alreadyrefreshingtoken = [nsnumber numberwithbool:yes];                         nslog(@"not refreshing token");                          // add failed request failedrequests array                         nsmutablearray *mutablefailedrequests = [weakself.failedrequests mutablecopy];                         [mutablefailedrequests addobject:request];                         weakself.failedrequests = [mutablefailedrequests copy];                          // refresh auth token                         [weakself refreshauthenticationtokenwithsuccesscallback:^(nsdictionary *response) {                              //store authtoken                             weakself.authtoken = response[@"token"];                             nsuserdefaults* defaults = [nsuserdefaults standarduserdefaults];                             [defaults setobject:weakself.authtoken forkey:@"authtoken"];                             [defaults synchronize];                              //attempt re-try requests failed due token expiration                             (nsurlrequest *failedrequest in weakself.failedrequests) {                                 [weakself sendtask:failedrequest successcallback:success errorcallback:errorcallback];                             }                              //clear failedrequests array , unlock alreadyrefreshingtoken boolean                             [weakself clearfailedrequests];                             weakself.alreadyrefreshingtoken = [nsnumber numberwithbool:no];                              nslog(@"token refreshing successful tho");                          } errorcallback:^(nsstring *error) {                              nslog(@"token not refreshable! have log in manually");                              //clear failedrequests array                             [weakself clearfailedrequests];                              errorcallback(@"your login session has expired");                          }];                     }                     else  {                         nslog(@"already refreshing token. add failed list");                         nsmutablearray *mutablefailedrequests = [weakself.failedrequests mutablecopy];                         [mutablefailedrequests addobject:request];                         weakself.failedrequests = [mutablefailedrequests copy];                     }                 }             }             else {                 nslog(@"error string tho: %@", error);                 errorcallback(error);             }         }];     }];     [task resume]; }  #pragma mark custom methods  -(void)clearfailedrequests {     nsmutablearray *mutablefailedrequests = [self.failedrequests mutablecopy];     [mutablefailedrequests removeallobjects];     self.failedrequests = [mutablefailedrequests copy]; } 

am going correctly? 1 part i'm paranoid i'm not calling success or error callback @ points. can lead problems?

instead of using [self sendtask:], try [weakself sendtask]. check below code:

-(void)sendtask:(nsurlrequest*)request successcallback:(void (^)(nsdictionary*))success errorcallback:(void (^)(nsstring*))errorcallback {     __weak __typeof(self)weakself = self;     nsurlsessiondatatask *task = [self.session datataskwithrequest:request completionhandler:^(nsdata *data, nsurlresponse *response, nserror *error)     {         [self parseresponse:response data:data fromrequest:request successcallback:success errorcallback:^(nsstring *error)         {             //if auth token expired , getting "not authenticated" error (status 401)             nshttpurlresponse *httpresp = (nshttpurlresponse*) response;             if (httpresp.statuscode == 401) {                 [self refreshauthenticationtokenwithsuccesscallback:^(nsdictionary *response) {                     self.authtoken = response[@"token"];                     //attempt re-try request failed due token expiration                     [weakself sendtask:request successcallback:success errorcallback:errorcallback];                 } errorcallback:^(nsstring *error) {                     //two weeks have passed , token no longer refreshable                     nslog(@"token not refreshable! have log in manually");                 }];             }         }];     }];     [task resume]; } 

Comments

Popular posts from this blog

c - How to retrieve a variable from the Apache configuration inside the module? -

c# - Constructor arguments cannot be passed for interface mocks -

python - malformed header from script index.py Bad header -