Как получить код статуса в AFNetworking

У меня есть метод для авторизации пользователя. Мне нужна основная авторизация.

    NSString *url = [NSString stringWithFormat:@"%@/rest/api/person/auth", host];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
    [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:_loginField.text password:_passwordField.text];
    [manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error %@ ",error);
    }];

Основная проблема здесь заключается в определении типа ошибки. У меня может быть ошибка для авторизации и ошибки для проблемы сетевого подключения (хост недоступен). Когда логин и пароль не соответствуют критериям, выполняется блок отказов. Например, если я помещаю неправильный пароль и логин, я беру это сообщение об ошибке.:

Ошибка домена = NSCocoaErrorDomain Code = 3840 "Операция не может быть завершено. (Cocoa ошибка 3840.)" (текст JSON не начинался с массива или объект и параметр, позволяющий не создавать фрагменты.)

Как я могу улавливать типы ошибок?

Ответы

Ответ 1

Наконец нашел ответ, может быть, это будет полезно для кого-то. Мне просто нужно было использовать:

NSInteger statusCode = operation.response.statusCode;

И я могу поймать его, как:

    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response:%@", responseObject);
        [self parseResponseForUser:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger statusCode = operation.response.statusCode;
        if(statusCode == 401) {
        } else if (statusCode == 404) {
        }
    }];

Ответ 2

В AFNetworking 3.0+ и в случае ошибки вы можете получить доступ к коду состояния в блоке ошибки error.userInfo:

failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

    NSHTTPURLResponse *response = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];

    NSInteger statusCode = response.statusCode;

    // Do something with the status code
}];

Ответ 3

вы можете попытаться получить код от ошибки, а затем отобразить сообщения соответственно.

failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSInteger statusCode = error.code;
    if(statusCode == -1001) {
      // request timed out
    } else if (statusCode == -1009 || statusCode || -1004) {
      // no internet connectivity
    }
}];

Аналогичным образом вы можете проверить другой код.

Ответ 4

Вот как я это делаю.

[self.httpClient GET:@"someAPI"
          parameters:parametersDictionary
             success:^(NSURLSessionDataTask *task, id responseObject) {
             } failure:^(NSURLSessionDataTask *task, NSError *error) {
               NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
               NSInteger statusCode = [response statusCode];
               switch (statusCode) {
                 case 404:
                   break;
                 default:
                   break;
               }
             }];

Ответ 5

Вот как это сделать в Swift

((NSURLSessionDataTask, NSError) -> Void) = { (sessionDataTask :NSURLSessionDataTask, responseError : NSError) -> Void in
    let response  = sessionDataTask.response as! NSHTTPURLResponse
    switch (statusCode) {
      case 404:
        // do stuff
      case 401:
        // do stuff
      default:
        break;
    }
}

Ответ 6

Похоже, ваш сервер может отвечать HTML, или он может ответить JSON. Но когда вы печатаете:

[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];

Вы сообщаете AFNetworking ожидать JSON.

Вместо этого попробуйте сообщить ему обрабатывать обычный HTTP-ответ, если он не JSON:

NSArray *serializers = @[[AFJSONResponseSerializer serializer], [AFHTTPResponseSerializer serializer]];
AFCompoundSerializer *compoundResponseSerializer = [AFCompoundSerializer compoundSerializerWithResponseSerializers:serializers];
[manager setResponseSerializer:compoundResponseSerializer];

Теперь, если сериализатор JSON завершится с ошибкой, запрос будет передан AFHTTPResponseSerializer, который должен вызывать ваш блок отказов с соответствующим кодом ошибки HTTP вместо ошибки анализа JSON.

Кстати, AFHTTPResponseSerializer является подклассом, поэтому не стесняйтесь взглянуть на эту опцию, если вы хотите более конкретного поведения.

Ответ 7

Часто бывает так, что серверы могут отправлять ответ в другом типе контента, чем запрос, если они отправляют сообщение об ошибке.

Например, при отправке запроса с JSON как Content-Type и ожидании ответа JSON с сервера, можно указать следующие заголовки запросов:

Content-Type: application/json
Accept: application/json

Когда запрос выходит из строя из-за ошибки аутентификации, сервер может отправить вам код состояния 401 (Unauthorized) плюс необязательный ответ, содержащий соответствующую диагностическую информацию.

Строго говоря, веб-серверы должны уважать заголовок Accept, но, к сожалению, некоторые из них не отправляют "стандартный" ответ об ошибке в text/html, например. Однако детали должны быть указаны в API.

Ваша реализация должна обработать этот случай изящно. То есть, ваш обработчик ответа должен кодировать (или анализировать) данные ответа в соответствии с ответом Content-Type ответа, например text/html или игнорировать его, если это подходит. Точнее, вы всегда должны запрашивать код состояния HTTP и тип содержимого, а затем принимать обоснованное решение о том, как вы хотите обработать ответ.

См. Aron Brager, ответьте, как решить эту проблему с AFN.

Ответ 8

Улучшенный ответ alok srivastava с использованием перечисления NSURLError:

failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSInteger statusCode = error.code;
if(statusCode == NSURLErrorTimedOut) {
  // request timed out
} else if (statusCode == NSURLErrorNotConnectedToInternet || statusCode || NSURLErrorCannotConnectToHost) {
  // no internet connectivity
}}];

Ответ 9

ваш Json должен быть:

{
    "access" : "1",
    "admin" : "0",
    "code" : "constantine2",

    ...

    "positions" : [
                {
            "departmentID" : "992c93ee-2fa7-4e53-be5f-4e32a45ba5e6",
            "departmentName" : "Dev-C++ resources page (libraries, sources, updates...)",
            ....
        }
    ],
    "userid" : "3b660c13-b856-41fa-a386-814a7b43bacc"
}