AFNetworking 2.0 добавляет заголовки в запрос GET

Я только начал использовать AFNetworking 2.0, и мне было интересно, как я добавляю заголовки в HTTP-запрос Get. Документация устанавливает GET следующим образом:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];

Но поскольку мы не обрабатываем NSURLRequests, я не знаю, как установить заголовки HTTP.

Любая помощь будет оценена по достоинству.
С уважением,
Майк


person Mackey18    schedule 19.10.2013    source источник
comment
возможный дубликат Как добавить собственный заголовок в AFNetworking на JSONRequestOperation   -  person RyanR    schedule 19.10.2013
comment
@RyanR не дубликат. Это из AFN 1.x, а не 2.0. С тех пор все полностью изменилось.   -  person Mackey18    schedule 19.10.2013
comment
Согласно руководству по миграции, AFHttpClient все еще существует и имеет ответственность за выполнение запросов Http для вашего приложения   -  person RyanR    schedule 19.10.2013
comment
@RyanR с использованием метода setDefaultHeader AFHTTPClient - неприятный способ действий. Мне нужен способ установки заголовков на уровне отдельного запроса.   -  person Mackey18    schedule 19.10.2013
comment
@RyanR, кроме того, что AFHTTPClient больше не входит в 2.0   -  person Mackey18    schedule 19.10.2013
comment
Проект с открытым исходным кодом с противоречивой документацией? НЕВАР. AFHTTPClient -> AFHTTPSessionManager видимо. Вы правы, использование setDefaultHeader отстой. 30-секундный поиск документов, и я нахожу AFHTTPRequestSerializer отвечает за заголовки HTTP для каждого запроса.   -  person RyanR    schedule 19.10.2013
comment
@RyanR D'о пропустил это! Благодаря вашей находке найден правильный метод: manager.requestSerializer setValue:<#(NSString *)#> forHTTPHeaderField:<#(NSString *)#>   -  person Mackey18    schedule 19.10.2013
comment
давайте продолжим это обсуждение в чате   -  person RyanR    schedule 19.10.2013


Ответы (7)


Фантастическая документация по AFNetworking 2.0 затрудняет поиск, но она есть. На AFHTTPRequestSerializer находится -setValue:forHTTPHeaderField:< /а>.

В качестве альтернативы, если вы будете следовать их рекомендуемому подходу к созданию диспетчера сеансов, производного от AFHTTPSessionManager, тогда этот класс может переопределить метод изменения заголовков для каждого запроса -dataTaskWithRequest:completionHandler:. Я использую это для проверки запросов и изменения заголовков в каждом конкретном случае и предпочитаю это модификации сериализатора, поскольку он берет на себя ответственность за сеть, содержащуюся в этом менеджере (и избегает гадости с синглтонами)

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *, id, NSError *))completionHandler
{
    static NSString *deviceId;
    if(!deviceId)
    {
        deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    }

    NSMutableURLRequest *req = (NSMutableURLRequest *)request;
    // Give each request a unique ID for tracing
    NSString *reqId = [NSString stringWithFormat:@"%@+%@", deviceId, [[NSUUID UUID] UUIDString] ];
    [req setValue:reqId forHTTPHeaderField:"x-myapp-requestId"];
    return [super dataTaskWithRequest:req completionHandler:completionHandler];
}
person RyanR    schedule 19.10.2013
comment
Спасибо друг. Ценится. - person Mackey18; 19.10.2013
comment
Не могли бы вы добавить фрагмент того, как это будет использоваться? я парень с Android, пытающийся изучить ios, и я не совсем уверен, как использовать этот ответ. - person ChuckKelly; 30.11.2013
comment
но почему заголовки установлены в сериализаторе??? Я также заметил, что таким образом они сохраняются, поэтому, как только вы установите поле заголовка, оно заполнится навсегда! (мне пришлось добавить свой собственный метод, чтобы удалить их) - person Peter Lapisu; 29.01.2014
comment
@PeterLapisu, вызвав этот метод с nil для value, удалит его. Вы не должны использовать заголовки для передачи эфемерных значений от клиента к серверу — это часть вашей полезной нагрузки. Заголовки предназначены для значений, которые не меняются часто, таких как данные аутентификации, управление кешем и т. д. Некоторые серверы даже определяют, следует ли возвращать кэшированные данные, на основе совпадения параметров заголовка, что вы не хотели бы предотвратить случайно. Если вам нужно установить заголовки только для одиночных запросов, я подозреваю, что это данные, которые принадлежат полезной нагрузке. - person RyanR; 29.01.2014
comment
я устанавливал настраиваемые заголовки аутентификации каждый раз перед запросом (потому что я думал, что заголовки предназначены для текущего запроса)... после выхода из системы заголовки все еще присутствовали: / позже я понял, что они «постоянны». ... но все равно не знаю, почему они принадлежат сериализатору - person Peter Lapisu; 29.01.2014
comment
@PeterLapisu Я не знаю, как рассуждали команды AFN, но это определенно имеет смысл с точки зрения дизайна. Сериализатор — это то, что знает, как кодировать/декодировать запрос и ответ для любого протокола, который вы используете. Если бы это было через FTP, вы бы сериализовали эту информацию иначе, чем через очередь сообщений. Таким образом, только компонент, ответственный за этот тип транспорта, знает детали транспорта (это часть [инкапсуляции](en.wikipedia.org/wiki/ ) - person RyanR; 29.01.2014
comment
все еще полагаю, что это плохая проблема с дизайном github.com/AFNetworking/AFNetworking/issues/1793 - person Peter Lapisu; 04.02.2014
comment
Я думаю, что пример и объяснение в дополнение к просто ссылке были бы здесь на своем месте. - person jake_hetfield; 16.07.2014

Вот пример использования AFNetworking 2.0.

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"calvinAndHobbesRock" forHTTPHeaderField:@"X-I do what I want"];

[manager GET:@"http://localhost:3000" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

Ключевыми являются следующие 2 строки:

manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"calvinAndHobbessRock" forHTTPHeaderField:@"X-I-do-what-I-want"];
person Shaheen Ghiassy    schedule 03.12.2013
comment
Спасибо за пример!! - person diegomen; 27.11.2014

добавление сериализатора ответа и запроса решило мою проблему.

manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
person user2073541    schedule 03.04.2014

Я использовал эту форму, чтобы назначить встречу с определенным заголовком.

AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[operationManager.requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

[operationManager POST:url
            parameters:params
               success:^(AFHTTPRequestOperation *operation, id responseObject) {

                   if (success) {
                       success(responseObject);
                   }

               }
               failure:^(AFHTTPRequestOperation *operation, NSError *error) {

                   NSLog(@"Error: %@", [error description]);

               }
 ];
person Carlos Avalos    schedule 26.06.2014
comment
Вам не кажется, что эти заголовки будут отправляться с любым запросом с момента их установки? - person vahotm; 16.02.2016

Вот что я считаю лучшим вариантом. Где-нибудь в синглтоне настройте AFHTTPSessionManager с помощью NSURLSessionConfiguration, а затем используйте этот AFHTTPSessionManager каждый раз, когда хотите сделать запрос.

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.HTTPAdditionalHeaders = @{@"Accepts": @"application/json"};

mySingletonSessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:kMyBaseUrl] sessionConfiguration:config];
person Chris    schedule 27.08.2014

Я сделал это... для тех, кто передает токен

[manager.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", _userObj.oAuth] forHTTPHeaderField:@"Authorization"];
person Serge Pedroza    schedule 21.05.2015

Используйте следующий код, чтобы поместить любой тип значения заголовка:

[[FRHTTPReqManager sharedManager].requestSerializer setValue:value forHTTPHeaderField:key];
person Evana    schedule 11.07.2014