Contents
  1. 1. NSError in failure block
  2. 2. How AFNetworking creates NSError
    1. 2.1. AFURLSessionManager.m
    2. 2.2. AFErrorWithUnderlyingError
    3. 2.3. Error Domain
  3. 3. HTTP Status code
    1. 3.1. Inspect userInfo of NSError
    2. 3.2. Replace NSError
  4. 4. Reference

When using AFNetworking, I want to get the status code in case of failure

NSError in failure block

1
2
3
4
5
6
AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
[sessionManager GET:@"" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {

} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"%@", error);
}];

The error.code is not the HTTP status code, it is NSError that AFNetworking creates due to serializer error

How AFNetworking creates NSError

AFURLSessionManager.m

In URLSession:task:didCompleteWithError:

1
2
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:[NSData dataWithData:self.mutableData] error:&serializationError];

AFErrorWithUnderlyingError

This is called in validateResponse:data:error: and responseObjectForResponse:data:error of AFURLResponseSerialization classes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
if (!error) {
return underlyingError;
}

if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
return error;
}

NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;

return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
}

Error Domain

In AFURLResponseSerialization.h


Error codes for AFURLResponseSerializationErrorDomain correspond to codes in NSURLErrorDomain.

For example

1
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);

HTTP Status code

Inspect userInfo of NSError

The NSError userInfo contains AFNetworkingOperationFailingURLResponseErrorKey and AFNetworkingOperationFailingURLResponseDataErrorKey that we can inspect to get NSURLResponse and NSData

Replace NSError

Sometimes we don’t care about NSURLErrorDomain, we can get HTTP Status Code from NSURResponse and replace the code in the NSError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:request
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error)
{
if (error) {
error = [self errorFromError:error
responseObject:responseObject
response:response];
[subscriber sendError:error];
} else {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
}
}];
- (NSError *)errorFromError:(NSError *)error
responseObject:(id)responseObject
response:(NSURLResponse *)response {

NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:error.userInfo];
if (responseObject) {
userInfo[kNetworkProviderResponseObjectKey] = responseObject;
}

NSInteger HTTPStatusCode = error.code;
if (response) {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *HTTPResponse = (id)response;
HTTPStatusCode = HTTPResponse.statusCode;
}
} else {
HTTPStatusCode = 408;
}

return [NSError errorWithDomain:error.domain code:HTTPStatusCode userInfo:userInfo];
}

Reference

  1. OSStatus
Contents
  1. 1. NSError in failure block
  2. 2. How AFNetworking creates NSError
    1. 2.1. AFURLSessionManager.m
    2. 2.2. AFErrorWithUnderlyingError
    3. 2.3. Error Domain
  3. 3. HTTP Status code
    1. 3.1. Inspect userInfo of NSError
    2. 3.2. Replace NSError
  4. 4. Reference