Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using AFNetworking and HTTP Basic Authentication

The following code successfully connects to my Ruby on Rails API and returns JSON using AFNetworking. What do I need to do to edit this to pass in a username and password so my API can use HTTP Basic Authentication?

I've read their documentation, but I am new to both Objective-C and AFNetworking and it isn't currently making sense.

NSURL *url = [[NSURL alloc] initWithString:@"http://localhost:3000/tasks.json"];

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

AFJSONRequestOperation *operation = [AFJSONRequestOperation
                                     JSONRequestOperationWithRequest:request
                                     success:^(NSURLRequest *request
                                     , NSHTTPURLResponse *response
                                     , id JSON) {

    self.tasks = [JSON objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");

} failure:^(NSURLRequest *request
                , NSHTTPURLResponse *response
                , NSError *error
                , id JSON) {
    NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
}];

[operation start];
like image 878
Paul Sylling Avatar asked Sep 15 '12 18:09

Paul Sylling


1 Answers

Answer updated for AFNetworking 2.x

For AFNetworking 2.x:

In 2.x, they did away with AFHTTPClient, so you'll need to extend AFHTTPRequestOperationManager with your own class. Then, you can call that class from other code. For example, here's a sample class that extends the AFHTTPRequestOperationManager:

SBAPIManager.h:

#import "AFHTTPRequestOperationManager.h"

@interface SBAPIManager : AFHTTPRequestOperationManager

- (void)setUsername:(NSString *)username andPassword:(NSString *)password;

+ (SBAPIManager *)sharedManager;

@end

SBAPIManager.m:

#import "SBAPIManager.h"
#import "AFNetworkActivityIndicatorManager.h"

@implementation SBAPIManager

#pragma mark - Methods

- (void)setUsername:(NSString *)username andPassword:(NSString *)password
{
    [self.requestSerializer clearAuthorizationHeader];
    [self.requestSerializer setAuthorizationHeaderFieldWithUsername:username password:password];
}

#pragma mark - Initialization

- (id)initWithBaseURL:(NSURL *)url
{
    self = [super initWithBaseURL:url];
    if(!self)
        return nil;

    self.requestSerializer = [AFJSONRequestSerializer serializer];

    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];

    return self;
}

#pragma mark - Singleton Methods

+ (SBAPIManager *)sharedManager
{
    static dispatch_once_t pred;
    static SBAPIManager *_sharedManager = nil;

    dispatch_once(&pred, ^{ _sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://localhost:3000"]]; }); // You should probably make this a constant somewhere
    return _sharedManager;
}

@end

Then, in your code, you can call it like this:

[[SBAPIManager sharedManager] setUsername:yourUsernameVariableHere andPassword:yourPasswordVariableHere];

[[SBAPIManager sharedManager] GET:@"/tasks.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    self.tasks = [responseObject objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // error stuff here
}];

For AFNetworking 1.x:

The best practice for this in AFNetworking is to extend the AFHTTPClient with your own class. Then, you can call that class from other code. For example, here's a sample class that extends the AFHTTPClient:

SBAPIManager.h:

#import "AFNetworking/AFHTTPClient.h"

@interface SBAPIManager : AFHTTPClient

- (void)setUsername:(NSString *)username andPassword:(NSString *)password;

+ (SBAPIManager *)sharedManager;

@end

SBAPIManager.m:

#import "SBAPIManager.h"
#import "AFJSONRequestOperation.h"
#import "AFNetworkActivityIndicatorManager.h"

@implementation SBAPIManager

#pragma mark - Methods

- (void)setUsername:(NSString *)username andPassword:(NSString *)password
{
    [self clearAuthorizationHeader];    
    [self setAuthorizationHeaderWithUsername:username password:password];
}

#pragma mark - Initialization

- (id)initWithBaseURL:(NSURL *)url
{
    self = [super initWithBaseURL:url];
    if(!self)
        return nil;

    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"application/json"];
    [self setParameterEncoding:AFJSONParameterEncoding];

    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];

    return self;
}

#pragma mark - Singleton Methods

+ (SBAPIManager *)sharedManager
{
    static dispatch_once_t pred;
    static SBAPIManager *_sharedManager = nil;

    dispatch_once(&pred, ^{ _sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://localhost:3000"]]; }); // You should probably make this a constant somewhere
    return _sharedManager;
}

@end

Then, in your code, you can call it like this:

[[SBAPIManager sharedManager] setUsername:yourUsernameVariableHere andPassword:yourPasswordVariableHere];

[[SBAPIManager sharedManager] getPath:@"/tasks.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    self.tasks = [responseObject objectForKey:@"results"];
    [self.activityIndicatorView stopAnimating];
    [self.tableView setHidden:NO];
    [self.tableView reloadData];

    NSLog(@"JSON");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // error stuff here
}];
like image 66
gilletty Avatar answered Nov 21 '22 06:11

gilletty