I have a use case that should be rather common but I can't find an easy way to handle it with AFNetworking:
Whenever the server returns a specific status code for any request, I want to:
- remove a cached authentication token
- re-authenticate (which is a separate request)
- repeat the failed request.
I thought that this could be done via some global completion/error handler in AFHTTPClient
, but I didn't find anything useful. So, what's the "right" way to do what I want? Override enqueueHTTPRequestOperation:
in my AFHTTPClient
subclass, copy the operation and wrap the original completion handler with a block that does what I want (re-authenticate, enqueue copied operation)? Or am I on the wrong track altogether?
Thanks!
EDIT: Removed reference to 401 status code, since that's probably reserved for HTTP basic while I'm using token auth.
To ensure that multiple token refreshes are not issued at around the same time, it is beneficial to either queue your network requests and block the queue when the token is refreshing, or add a mutex lock (@synchronized directive) to your token refresh method.
Here is the Swift implementation of user @adamup 's answer
where refreshToken (...) is an extension method I wrote to get a new token from the server.
Took a similar approach, but I couldn't get the status code object with phix23's answer so I needed a different plan of action. AFNetworking 2.0 changed a couple of things.
In the AFHTTPClient's init method register for the
AFNetworkingOperationDidFinishNotification
which will be posted after a request finishes.In the notification handler check the status code and
copy
theAFHTTPRequestOperation
or create a new one.EDIT:
In general you should not need to do that and just handle the authentication with this AFNetworking method:
I use an alternative means for doing this with AFNetworking 2.0.
You can subclass
dataTaskWithRequest:success:failure:
and wrap the passed completion block with some error checking. For example, if you're working with OAuth, you could watch for a 401 error (expiry) and refresh your access token.If you are subclassing
AFHTTPSessionManager
or using directly anAFURLSessionManager
you could use the following method to set a block executed after the completion of a task:Just perform whatever you want to do for each tasks of the session in it:
EDIT: In fact if you need to handle an error returned in the response object the above method won't do the job. One way if you are subclassing
AFHTTPSessionManager
could be to subclass and set a custom response serializer with it'sresponseObjectForResponse:data:error:
overloaded like that:and set it in your
AFHTTPSessionManager
subclass: