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?

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top