78
votes

I've just started using AFNetworking 2.0 and I was wondering how I put in headers into a HTTP Get request. The documentation sets up a GET like this:

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

But since we're not handling NSURLRequests I'm not sure how to set HTTP Headers.

Any help would be appreciated.
Regards,
Mike

7
@RyanR not a duplicate. That is from AFN 1.x not 2.0. Everything has completely changed since then.Mackey18
According to the migration guide AFHttpClient still exists and still has the responsibility of executing Http requests for your appRyanR
An open source project with conflicting documentation? NEVAR. AFHTTPClient -> AFHTTPSessionManager apparently. You're right, using setDefaultHeader sucks. A 30 second search of the docs and I find AFHTTPRequestSerializer is responsible for HTTPHeaders on a per-request basis.RyanR
@RyanR D'oh missed that! Found the correct method thanks to your finding: manager.requestSerializer setValue:<#(NSString *)#> forHTTPHeaderField:<#(NSString *)#>Mackey18

7 Answers

84
votes

The fantastic documentation for AFNetworking 2.0 makes this a little hard to find, but it is there. On the AFHTTPRequestSerializer is -setValue:forHTTPHeaderField:.

Alternatively, if you follow their recommended approach of creating a session manager that derives from AFHTTPSessionManager then that class can override a method to modify headers on each request -dataTaskWithRequest:completionHandler:. I use this to inspect requests and modify headers on a case-by-case basis, and prefer it to modifying the serializer as it keeps the responsibility for networking contained in that manager (and avoids mucking with singletons)

- (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];
}
146
votes

Here's an example using 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);
}];

The key are the following 2 lines:

manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"calvinAndHobbessRock" forHTTPHeaderField:@"X-I-do-what-I-want"];
17
votes

adding response and request serializer solved my problem.

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

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

I have used this form to make an appointment with a specific header.

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

               }
 ];
6
votes

Here's what i believe to be a best option. In a singleton somewhere, configure an AFHTTPSessionManager using an NSURLSessionConfiguration, and then use that AFHTTPSessionManager every time you want to make a request.

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

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

I did this...for those that are passing token

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

Use the following code to put any type of header value:

[[FRHTTPReqManager sharedManager].requestSerializer setValue:value forHTTPHeaderField:key];