How see the error of a json POST with AFNetworking?
-
22-12-2019 - |
Question
After look at POST request with AFNetworking 2.0 - AFHTTPSessionManager I can't see where the error message can be found.
This is my setup:
-(id)init
{
if ((self = [super init])) {
NSURL *url = [NSURL URLWithString:DebugURLString];
self.session = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
self.session.requestSerializer = [AFJSONRequestSerializer serializer];
self.session.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
}
return self;
}
-(void) login:(NSString *)email pwd:(NSString *)pwd result:(void(^)(NSError* result))handler
{
NSDictionary *params = @{@"username": email, @"password":pwd};
[self.session POST:@"auth/api-token/" parameters:params
success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"%@", responseObject);
handler(nil);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"%@", task);
NSLog(@"%@", error.userInfo);
handler(error);
}];
}
I call http://www.django-rest-framework.org/api-guide/authentication#tokenauthentication, directly the rest_framework.authtoken.views.obtain_auth_token
that ask for a username & password and return a token.
If the user/pass is correct this work fine. But if not I get:
error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey]
<NSHTTPURLResponse: 0xb388f20> { URL: http://localhost:8000/auth/api-token/ } { status code: 400, headers {
Allow = "POST, OPTIONS";
"Content-Type" = "application/json";
Date = "Sat, 11 Jan 2014 02:14:13 GMT";
Server = "WSGIServer/0.1 Python/2.7.5";
Vary = "Accept, Cookie";
} }
However, when I do the same call with python + requests, I get:
{u'non_field_errors': [u'Unable to login with provided credentials.']}
But I don't find it in the NSError
.
Also, despite that I set responseSerializer
, it report in the task:
(lldb) po task.response
<NSHTTPURLResponse: 0xb388f20> { URL: http://localhost:8000/auth/api-token/ } { status code: 400, headers {
Allow = "POST, OPTIONS";
"Content-Type" = "application/json";
Date = "Sat, 11 Jan 2014 02:14:13 GMT";
Server = "WSGIServer/0.1 Python/2.7.5";
Vary = "Accept, Cookie";
Instead of the JSon one. What I need to fix?
Solution
You've hit a quirk of AFNetworking
v2 — by default the response body is not passed into the failure block. Check the discussion on Github for the details.
The bottom line is you need to subclass AFJSONResponseSerializer
in order to add the response data you need to the userInfo
dictionary of the NSError
during responseObjectForResponse:data:error:
. (You'll then be able to access it.)
Your question prompted me to revisit the Github issue (same as above). There's now a blog post and a repo with an example subclass available.
I hope all that helps.
AFNetworking
v2 is great; this behaviour was an oddity when adopting it. My initial thought was "This can't be right", but I think the underlying reasoning is that you are encouraged to create your own response serialisers. The shipped examples are fairly light-weight. It's easy create your own, and the response serialiser is a good place to encapsulate network related logic that otherwise ends up back in your application.