Ошибка типа содержимого AFNetworking версии 2

Я пытаюсь сделать приложение iphone, которое будет взаимодействовать с конкретным сервером JIRA. У меня есть следующий код для входа в систему:

NSURL *url = [[NSURL alloc] initWithString:@"https://mycompany.atlassian.net/rest/auth/latest/session/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *postString = [NSString stringWithFormat:@"{\"username\":\"%@\",\"password\":\"%@\"}", username, password];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept" ];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:
    ^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"ERROR: %@", error);

    }
 ];
 [operation start];

Но это дает мне следующую ошибку, связанную с Content-Type:

ERROR: Error Domain=AFNetworkingErrorDomain Code=-1011
"Request failed: unsupported media type (415)"
UserInfo=0x8cd6540
{
  NSErrorFailingURLKey=https://mycompany.atlassian.net/rest/auth/latest/session/,
  NSLocalizedDescription=Request failed: unsupported media type (415),
  NSUnderlyingError=0x8c72e70
  "Request failed: unacceptable content-type: text/html", 

Я не уверен, в чем проблема. Я нашел этот вопрос, который, как я думал, может быть аналогичной проблемой, но ответы говорят либо использовать класс AFJSONRequestOperation (который я не может, потому что я использую AFNetworking версии 2, которая не имеет этого класса), или исправить ее на стороне сервера (что я также не могу по понятным причинам).

Что я могу исправить эту ошибку, если не могу исправить серверную часть, и я не могу использовать AFJSONRequestOperation?

Ответ 1

Если вы используете AFNetworking 2.0, вы можете использовать метод POST, который немного упрощает это:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = @{@"username":username, @"password":password};
[manager POST:@"https://mycompany.atlassian.net/rest/auth/latest/session/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

Это создает запрос, устанавливая его Content-Type в соответствии с настройкой requestSerializer и кодируя JSON для вас. Одним из преимуществ AFNetworking является то, что вы можете выйти из сорняков при конструировании и настройке объектов NSURLRequest вручную.


Кстати, ошибка "Ошибка запроса: неприемлемый тип контента: текст /html " означает, что независимо от того, что вы ожидали получить (например, JSON), вы получили ответ HTML. Это очень распространено: многие ошибки сервера (например, сервер, информирующий вас о том, что запрос был искажен и т.д.) Генерируют сообщения об ошибках HTML. Если вы хотите увидеть этот HTML-код в своем блоке failure, просто запишите operation.responseString.

Ответ 2

Оказывается, проблема в том, что эта одна строка:

[request setValue:@"application/json" forHTTPHeaderField:@"Accept" ];

Должно быть

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type" ];

Ошибка теперь решена. ( Изменить: мне нужно иметь оба, см. комментарий CouchDeveloper.)

ИЗМЕНИТЬ
Решение Rob лучше, поэтому я собираюсь с ним. Я действительно попробовал аналогичное решение того, что он показывает, но где у него была линия,

manager.requestSerializer = [AFJSONRequestSerializer serializer];

У меня была строка:

[manager.requestSerializer
    setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

... который не работал. Престижность Робу за то, что он работает!

Ответ 3

У меня была такая же проблема в AFNetworking 2.0, и я решил, что должен установить тип AFHTTPRequestSerializer (в случае, если ваш запрос JSON), он должен быть таким.

AFHTTPSessionManager *myHTTPManager = ...
[myManager setRequestSerializer:[AFJSONRequestSerializer serializer]];

Вы должны установить как AFHTTPResponseSerializer, так и AFHTTPRequestSerializer

Ответ 4

если вы используете класс по умолчанию AFAppDotNetAPIClient, и вы сталкиваетесь с этой ошибкой. Необходимо добавить responseSerializer. см. ваш общий метод должен выглядеть так:

+ (instancetype)sharedClient {

static AFAppDotNetAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
    _sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
    _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    _sharedClient.responseSerializer = [AFHTTPResponseSerializer serializer];
});
return _sharedClient;}

Ответ 5

Используйте эту строку кода.

operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];