Как получить код статуса в 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"
}