AFNetworking 2.0 додає заголовки до запиту GET


78

Я щойно почав використовувати AFNetworking 2.0, і мені було цікаво, як я вставляю заголовки в запит на отримання HTTP. Документація встановлює 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.

Будь-яка допомога буде вдячна.
З повагою,
Майк



3
@RyanR не дублікат. Тобто з AFN 1.x, а не 2.0. Відтоді все повністю змінилося.
Mackey18,

Згідно з керівництвом з міграції AFHttpClient все ще існує і все ще несе відповідальність за виконання запитів Http для вашого додатка
RyanR

2
Проект з відкритим кодом із суперечливою документацією? НЕВАР. AFHTTPClient -> AFHTTPSessionManager очевидно. Ви маєте рацію, використовуючи setDefaultHeaderвідстій. 30-секундний пошук документів, і я виявляю, що AFHTTPRequestSerializer відповідає за HTTPHeaders на основі кожного запиту.
RyanR

2
@RyanR D'oh пропустив це! Знайшов правильний метод завдяки вашій знахідці:manager.requestSerializer setValue:<#(NSString *)#> forHTTPHeaderField:<#(NSString *)#>
Mackey18

Відповіді:


84

Фантастична документація для 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];
}

4
u, додайте фрагмент того, як це буде використано? я андроїд хлопець намагається вивчити ios і я не зовсім впевнений, як застосувати цю відповідь.
ChuckKelly

1
але чому заголовки встановлюються в серіалізаторі ??? Я також помітив, що таким чином вони стійкі, тому, як тільки ви встановите поле заголовка, воно заповниться і залишиться там назавжди! (мені довелося додати власний метод їх видалення)
Пітер Лапісу,

4
@PeterLapisu, який викликає цей метод nilза допомогою value, видалить його. Ви не повинні використовувати заголовки для передачі ефемерних значень від клієнта на сервер - це частина вашого корисного навантаження. Заголовки призначені для значень, які не змінюються часто, таких як дані автентифікації, контроль кеш-пам’яті тощо. Деякі сервери навіть визначатимуть, чи повертати кешовані дані на основі відповідності параметрів заголовка, чого ви не хочете випадково запобігти. Якщо вам потрібно встановити заголовки лише для окремих запитів, я підозрюю, що саме дані належать до корисного навантаження.
RyanR

2
@PeterLapisu Я не знаю, якими були міркування команд AFN, але це, безумовно, має сенс з точки зору дизайну. Серіалізатор - це те, що знає, як кодувати / декодувати запит і відповідь для будь-якого протоколу, який ви використовуєте. Якби це було через FTP, ви б серіалізували цю інформацію інакше, ніж через Чергу повідомлень. Таким чином, лише компонент, відповідальний за такий вид транспорту, знає деталі транспорту (це частина [інкапсуляції] ( en.wikipedia.org/wiki/… )
RyanR

2
як і раніше вірити своєму поганому дизайну github.com/AFNetworking/AFNetworking/issues/1793
Пітер Лапісу

146

Ось приклад використання 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"];

1
Дякую за приклад !!
дієгоми

17

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

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

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

7

Я використав цю форму, щоб записатися на зустріч із певним заголовком.

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]);

               }
 ];

Вам не здається, що ці заголовки будуть надіслані з будь-яким запитом з моменту, коли ви їх встановите?
vahotm

6

Ось, що я вважаю найкращим варіантом. Де-небудь в одній одиниці налаштуйте AFHTTPSessionManagerвикористання NSURLSessionConfiguration, а потім використовуйте це AFHTTPSessionManagerкожен раз, коли ви хочете зробити запит.

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

mySingletonSessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:kMyBaseUrl] sessionConfiguration:config];

3

Я зробив це ... для тих, хто передає жетон

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

-3

Використовуйте наступний код, щоб вказати будь-який тип заголовка:

[[FRHTTPReqManager sharedManager].requestSerializer setValue:value forHTTPHeaderField:key];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.